diff options
2239 files changed, 61619 insertions, 24278 deletions
diff --git a/Android.mk b/Android.mk index 5690d6f208c9..e61d7c2a5c0f 100644 --- a/Android.mk +++ b/Android.mk @@ -270,6 +270,7 @@ LOCAL_SRC_FILES += \ core/java/android/os/IRecoverySystemProgressListener.aidl \ core/java/android/os/IRemoteCallback.aidl \ core/java/android/os/ISchedulingPolicyService.aidl \ + core/java/android/os/IStatsManager.aidl \ core/java/android/os/IThermalEventListener.aidl \ core/java/android/os/IThermalService.aidl \ core/java/android/os/IUpdateLock.aidl \ @@ -1099,6 +1100,31 @@ framework_docs_LOCAL_DROIDDOC_OPTIONS += \ -federate SupportLib https://developer.android.com \ -federationapi SupportLib prebuilts/sdk/current/support-api.txt +# ==== the api diff =========================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(framework_docs_LOCAL_API_CHECK_SRC_FILES) +LOCAL_INTERMEDIATE_SOURCES := $(framework_docs_LOCAL_INTERMEDIATE_SOURCES) +LOCAL_JAVA_LIBRARIES := $(framework_docs_LOCAL_API_CHECK_JAVA_LIBRARIES) +LOCAL_MODULE_CLASS := $(framework_docs_LOCAL_MODULE_CLASS) +LOCAL_ADDITIONAL_JAVA_DIR := $(framework_docs_LOCAL_API_CHECK_ADDITIONAL_JAVA_DIR) +LOCAL_ADDITIONAL_DEPENDENCIES := \ + $(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES) \ + $(INTERNAL_PLATFORM_API_FILE) + +LOCAL_MODULE := offline-sdk-referenceonly + +last_released_sdk_version := $(lastword $(call numerically_sort, \ + $(filter-out current, \ + $(patsubst $(SRC_API_DIR)/%.txt,%, $(wildcard $(SRC_API_DIR)/*.txt)) \ + )\ + )) + +LOCAL_APIDIFF_OLDAPI := $(LOCAL_PATH)/../../$(SRC_API_DIR)/$(last_released_sdk_version) +LOCAL_APIDIFF_NEWAPI := $(LOCAL_PATH)/../../$(basename $(INTERNAL_PLATFORM_API_FILE)) + +include $(BUILD_APIDIFF) + # ==== the api stubs and current.xml =========================== include $(CLEAR_VARS) diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java index 519d1f4c96b1..eed1db032d9f 100644 --- a/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java +++ b/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java @@ -51,7 +51,6 @@ public class CanvasPerfTest { while (state.keepRunning()) { canvas = node.start(200, 200); - canvas.setHighContrastText(false); int save = canvas.save(); canvas.clipRect(1, 1, 199, 199); canvas.insertReorderBarrier(); diff --git a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java new file mode 100644 index 000000000000..57a61ec8218f --- /dev/null +++ b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package android.text; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; + +import android.support.test.filters.LargeTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.nio.CharBuffer; +import java.util.Random; + +@LargeTest +@RunWith(AndroidJUnit4.class) +public class StaticLayoutPerfTest { + + public StaticLayoutPerfTest() { + } + + @Rule + public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + private static final String FIXED_TEXT = "Lorem ipsum dolor sit amet, consectetur adipiscing " + + "elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad " + + "minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea " + + "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse " + + "cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non " + + "proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; + private static final int FIXED_TEXT_LENGTH = FIXED_TEXT.length(); + + private static TextPaint PAINT = new TextPaint(); + private static final int TEXT_WIDTH = 20 * (int) PAINT.getTextSize(); + + @Test + public void testCreate() { + final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StaticLayout.Builder.obtain(FIXED_TEXT, 0, FIXED_TEXT_LENGTH, PAINT, TEXT_WIDTH) + .build(); + } + } + + private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + private static final int ALPHABET_LENGTH = ALPHABET.length(); + + private static final int PARA_LENGTH = 500; + private final char[] mBuffer = new char[PARA_LENGTH]; + private final Random mRandom = new Random(31415926535L); + + private CharSequence generateRandomParagraph(int wordLen) { + for (int i = 0; i < PARA_LENGTH; i++) { + if (i % (wordLen + 1) == wordLen) { + mBuffer[i] = ' '; + } else { + mBuffer[i] = ALPHABET.charAt(mRandom.nextInt(ALPHABET_LENGTH)); + } + } + return CharBuffer.wrap(mBuffer); + } + + // This tries to simulate the case where the cache hit rate is low, and most of the text is + // new text. + @Test + public void testCreateRandom() { + final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + final CharSequence text = generateRandomParagraph(9); + StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) + .build(); + } + } + + @Test + public void testCreateRandom_breakBalanced() { + final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + final CharSequence text = generateRandomParagraph(9); + StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) + .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) + .build(); + } + } +} diff --git a/api/current.txt b/api/current.txt index f1f6fb7532f3..61b0989a86ac 100644 --- a/api/current.txt +++ b/api/current.txt @@ -1524,6 +1524,7 @@ package android { field public static final int windowHideAnimation = 16842935; // 0x10100b7 field public static final int windowIsFloating = 16842839; // 0x1010057 field public static final int windowIsTranslucent = 16842840; // 0x1010058 + field public static final int windowLightNavigationBar = 16844140; // 0x101056c field public static final int windowLightStatusBar = 16844000; // 0x10104e0 field public static final int windowMinWidthMajor = 16843606; // 0x1010356 field public static final int windowMinWidthMinor = 16843607; // 0x1010357 @@ -4214,12 +4215,6 @@ package android.app { public class Application extends android.content.ContextWrapper implements android.content.ComponentCallbacks2 { ctor public Application(); - method public android.app.Activity instantiateActivity(java.lang.ClassLoader, java.lang.String, android.content.Intent); - method public android.app.backup.BackupAgent instantiateBackupAgent(java.lang.ClassLoader, java.lang.String); - method public android.app.Instrumentation instantiateInstrumentation(java.lang.ClassLoader, java.lang.String); - method public android.content.ContentProvider instantiateProvider(java.lang.ClassLoader, java.lang.String); - method public android.content.BroadcastReceiver instantiateReceiver(java.lang.ClassLoader, java.lang.String, android.content.Intent); - method public android.app.Service instantiateService(java.lang.ClassLoader, java.lang.String, android.content.Intent); method public void onConfigurationChanged(android.content.res.Configuration); method public void onCreate(); method public void onLowMemory(); @@ -6140,7 +6135,6 @@ package android.app { } public class WallpaperManager { - method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener); method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler); method public void clear() throws java.io.IOException; method public void clear(int) throws java.io.IOException; @@ -6289,6 +6283,7 @@ package android.app.admin { method public void addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName); method public void addUserRestriction(android.content.ComponentName, java.lang.String); method public boolean bindDeviceAdminServiceAsUser(android.content.ComponentName, android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle); + method public boolean clearApplicationUserData(android.content.ComponentName, java.lang.String, android.app.admin.DevicePolicyManager.OnClearApplicationUserDataListener, android.os.Handler); method public void clearCrossProfileIntentFilters(android.content.ComponentName); method public deprecated void clearDeviceOwnerApp(java.lang.String); method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String); @@ -6543,6 +6538,10 @@ package android.app.admin { field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2 } + public static abstract interface DevicePolicyManager.OnClearApplicationUserDataListener { + method public abstract void onApplicationUserDataCleared(java.lang.String, boolean); + } + public final class DnsEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable { method public java.lang.String getHostname(); method public java.util.List<java.net.InetAddress> getInetAddresses(); @@ -10888,6 +10887,7 @@ package android.content.pm { field public static final int PROTECTION_FLAG_APPOP = 64; // 0x40 field public static final int PROTECTION_FLAG_DEVELOPMENT = 32; // 0x20 field public static final int PROTECTION_FLAG_INSTALLER = 256; // 0x100 + field public static final int PROTECTION_FLAG_INSTANT = 4096; // 0x1000 field public static final int PROTECTION_FLAG_PRE23 = 128; // 0x80 field public static final int PROTECTION_FLAG_PREINSTALLED = 1024; // 0x400 field public static final int PROTECTION_FLAG_PRIVILEGED = 16; // 0x10 @@ -15871,6 +15871,7 @@ package android.hardware.fingerprint { field public static final int FINGERPRINT_ERROR_NO_SPACE = 4; // 0x4 field public static final int FINGERPRINT_ERROR_TIMEOUT = 3; // 0x3 field public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; // 0x2 + field public static final int FINGERPRINT_ERROR_USER_CANCELED = 10; // 0xa field public static final int FINGERPRINT_ERROR_VENDOR = 8; // 0x8 } @@ -18119,11 +18120,13 @@ package android.icu.text { method public synchronized void applyLocalizedPattern(java.lang.String); method public synchronized void applyPattern(java.lang.String); method public synchronized boolean areSignificantDigitsUsed(); + method public synchronized boolean equals(java.lang.Object); method public java.lang.StringBuffer format(double, java.lang.StringBuffer, java.text.FieldPosition); method public java.lang.StringBuffer format(long, java.lang.StringBuffer, java.text.FieldPosition); method public java.lang.StringBuffer format(java.math.BigInteger, java.lang.StringBuffer, java.text.FieldPosition); method public java.lang.StringBuffer format(java.math.BigDecimal, java.lang.StringBuffer, java.text.FieldPosition); method public java.lang.StringBuffer format(android.icu.math.BigDecimal, java.lang.StringBuffer, java.text.FieldPosition); + method public synchronized android.icu.util.Currency getCurrency(); method public synchronized android.icu.text.CurrencyPluralInfo getCurrencyPluralInfo(); method public synchronized android.icu.util.Currency.CurrencyUsage getCurrencyUsage(); method public synchronized android.icu.text.DecimalFormatSymbols getDecimalFormatSymbols(); @@ -18131,8 +18134,12 @@ package android.icu.text { method public synchronized int getGroupingSize(); method public synchronized java.math.MathContext getMathContext(); method public synchronized android.icu.math.MathContext getMathContextICU(); + method public synchronized int getMaximumFractionDigits(); + method public synchronized int getMaximumIntegerDigits(); method public synchronized int getMaximumSignificantDigits(); method public synchronized byte getMinimumExponentDigits(); + method public synchronized int getMinimumFractionDigits(); + method public synchronized int getMinimumIntegerDigits(); method public synchronized int getMinimumSignificantDigits(); method public synchronized int getMultiplier(); method public synchronized java.lang.String getNegativePrefix(); @@ -18143,13 +18150,19 @@ package android.icu.text { method public synchronized java.lang.String getPositivePrefix(); method public synchronized java.lang.String getPositiveSuffix(); method public synchronized java.math.BigDecimal getRoundingIncrement(); + method public synchronized int getRoundingMode(); method public synchronized int getSecondaryGroupingSize(); + method public synchronized int hashCode(); method public synchronized boolean isDecimalPatternMatchRequired(); method public synchronized boolean isDecimalSeparatorAlwaysShown(); method public synchronized boolean isExponentSignAlwaysShown(); + method public synchronized boolean isGroupingUsed(); method public synchronized boolean isParseBigDecimal(); + method public synchronized boolean isParseIntegerOnly(); + method public synchronized boolean isParseStrict(); method public synchronized boolean isScientificNotation(); method public java.lang.Number parse(java.lang.String, java.text.ParsePosition); + method public synchronized void setCurrency(android.icu.util.Currency); method public synchronized void setCurrencyPluralInfo(android.icu.text.CurrencyPluralInfo); method public synchronized void setCurrencyUsage(android.icu.util.Currency.CurrencyUsage); method public synchronized void setDecimalFormatSymbols(android.icu.text.DecimalFormatSymbols); @@ -18158,10 +18171,15 @@ package android.icu.text { method public synchronized void setExponentSignAlwaysShown(boolean); method public synchronized void setFormatWidth(int); method public synchronized void setGroupingSize(int); + method public synchronized void setGroupingUsed(boolean); method public synchronized void setMathContext(java.math.MathContext); method public synchronized void setMathContextICU(android.icu.math.MathContext); + method public synchronized void setMaximumFractionDigits(int); + method public synchronized void setMaximumIntegerDigits(int); method public synchronized void setMaximumSignificantDigits(int); method public synchronized void setMinimumExponentDigits(byte); + method public synchronized void setMinimumFractionDigits(int); + method public synchronized void setMinimumIntegerDigits(int); method public synchronized void setMinimumSignificantDigits(int); method public synchronized void setMultiplier(int); method public synchronized void setNegativePrefix(java.lang.String); @@ -18169,12 +18187,15 @@ package android.icu.text { method public synchronized void setPadCharacter(char); method public synchronized void setPadPosition(int); method public synchronized void setParseBigDecimal(boolean); + method public synchronized void setParseIntegerOnly(boolean); method public deprecated void setParseMaxDigits(int); + method public synchronized void setParseStrict(boolean); method public synchronized void setPositivePrefix(java.lang.String); method public synchronized void setPositiveSuffix(java.lang.String); method public synchronized void setRoundingIncrement(java.math.BigDecimal); method public synchronized void setRoundingIncrement(android.icu.math.BigDecimal); method public synchronized void setRoundingIncrement(double); + method public synchronized void setRoundingMode(int); method public synchronized void setScientificNotation(boolean); method public synchronized void setSecondaryGroupingSize(int); method public synchronized void setSignificantDigitsUsed(boolean); @@ -26065,8 +26086,8 @@ package android.net { method public boolean protect(java.net.Socket); method public boolean protect(java.net.DatagramSocket); method public boolean setUnderlyingNetworks(android.net.Network[]); - field public static final java.lang.String METADATA_SUPPORTS_ALWAYS_ON = "android.net.VpnService.SUPPORTS_ALWAYS_ON"; field public static final java.lang.String SERVICE_INTERFACE = "android.net.VpnService"; + field public static final java.lang.String SERVICE_META_DATA_SUPPORTS_ALWAYS_ON = "android.net.VpnService.SUPPORTS_ALWAYS_ON"; } public class VpnService.Builder { @@ -30658,7 +30679,8 @@ package android.os { field public static final int N = 24; // 0x18 field public static final int N_MR1 = 25; // 0x19 field public static final int O = 26; // 0x1a - field public static final int O_MR1 = 10000; // 0x2710 + field public static final int O_MR1 = 27; // 0x1b + field public static final int P = 10000; // 0x2710 } public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable { @@ -37061,13 +37083,14 @@ package android.service.autofill { public final class FillEventHistory implements android.os.Parcelable { method public int describeContents(); - method public android.os.Bundle getClientState(); + method public deprecated android.os.Bundle getClientState(); method public java.util.List<android.service.autofill.FillEventHistory.Event> getEvents(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.service.autofill.FillEventHistory> CREATOR; } public static final class FillEventHistory.Event { + method public android.os.Bundle getClientState(); method public java.lang.String getDatasetId(); method public int getType(); field public static final int TYPE_AUTHENTICATION_SELECTED = 2; // 0x2 @@ -38915,7 +38938,7 @@ package android.telecom { public static final class Call.RttCall { method public int getRttAudioMode(); - method public java.lang.String read() throws java.io.IOException; + method public java.lang.String read(); method public java.lang.String readImmediately() throws java.io.IOException; method public void setRttMode(int); method public void write(java.lang.String) throws java.io.IOException; @@ -39000,6 +39023,7 @@ package android.telecom { method public final void setActive(); method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>); method public final void setConnectionCapabilities(int); + method public final void setConnectionElapsedTime(long); method public final void setConnectionProperties(int); method public final void setConnectionTime(long); method public final void setDialing(); @@ -39632,11 +39656,13 @@ package android.telephony { field public static final java.lang.String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string"; field public static final java.lang.String KEY_DIAL_STRING_REPLACE_STRING_ARRAY = "dial_string_replace_string_array"; field public static final java.lang.String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool"; + field public static final java.lang.String KEY_DISPLAY_HD_AUDIO_PROPERTY_BOOL = "display_hd_audio_property_bool"; field public static final java.lang.String KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL = "drop_video_call_when_answering_audio_call_bool"; field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool"; field public static final java.lang.String KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT = "duration_blocking_disabled_after_emergency_int"; field public static final java.lang.String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool"; field public static final java.lang.String KEY_EDITABLE_VOICEMAIL_NUMBER_BOOL = "editable_voicemail_number_bool"; + field public static final java.lang.String KEY_ENABLE_APPS_STRING_ARRAY = "enable_apps_string_array"; field public static final java.lang.String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_key_vibration_bool"; field public static final java.lang.String KEY_FORCE_HOME_NETWORK_BOOL = "force_home_network_bool"; field public static final java.lang.String KEY_GSM_DTMF_TONE_DELAY_INT = "gsm_dtmf_tone_delay_int"; @@ -39896,11 +39922,12 @@ package android.telephony { } public class MbmsStreamingManager { - method public static android.telephony.MbmsStreamingManager create(android.content.Context, android.telephony.mbms.MbmsStreamingManagerCallback, int) throws android.telephony.mbms.MbmsException; + method public static android.telephony.MbmsStreamingManager create(android.content.Context, android.telephony.mbms.MbmsStreamingManagerCallback, int, android.os.Handler) throws android.telephony.mbms.MbmsException; + method public static android.telephony.MbmsStreamingManager create(android.content.Context, android.telephony.mbms.MbmsStreamingManagerCallback, android.os.Handler) throws android.telephony.mbms.MbmsException; method public static android.telephony.MbmsStreamingManager create(android.content.Context, android.telephony.mbms.MbmsStreamingManagerCallback) throws android.telephony.mbms.MbmsException; method public void dispose(); method public void getStreamingServices(java.util.List<java.lang.String>) throws android.telephony.mbms.MbmsException; - method public android.telephony.mbms.StreamingService startStreaming(android.telephony.mbms.StreamingServiceInfo, android.telephony.mbms.StreamingServiceCallback) throws android.telephony.mbms.MbmsException; + method public android.telephony.mbms.StreamingService startStreaming(android.telephony.mbms.StreamingServiceInfo, android.telephony.mbms.StreamingServiceCallback, android.os.Handler) throws android.telephony.mbms.MbmsException; } public class NeighboringCellInfo implements android.os.Parcelable { @@ -40105,9 +40132,12 @@ package android.telephony { field public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; // 0x3 field public static final int MMS_ERROR_UNSPECIFIED = 1; // 0x1 field public static final int RESULT_ERROR_GENERIC_FAILURE = 1; // 0x1 + field public static final int RESULT_ERROR_LIMIT_EXCEEDED = 5; // 0x5 field public static final int RESULT_ERROR_NO_SERVICE = 4; // 0x4 field public static final int RESULT_ERROR_NULL_PDU = 3; // 0x3 field public static final int RESULT_ERROR_RADIO_OFF = 2; // 0x2 + field public static final int RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED = 8; // 0x8 + field public static final int RESULT_ERROR_SHORT_CODE_NOT_ALLOWED = 7; // 0x7 field public static final int STATUS_ON_ICC_FREE = 0; // 0x0 field public static final int STATUS_ON_ICC_READ = 1; // 0x1 field public static final int STATUS_ON_ICC_SENT = 5; // 0x5 @@ -40540,7 +40570,6 @@ package android.telephony.mbms { } public static class MbmsException.GeneralErrors { - ctor public MbmsException.GeneralErrors(); field public static final int ERROR_CARRIER_CHANGE_NOT_ALLOWED = 207; // 0xcf field public static final int ERROR_IN_E911 = 204; // 0xcc field public static final int ERROR_MIDDLEWARE_NOT_YET_READY = 201; // 0xc9 @@ -40551,36 +40580,31 @@ package android.telephony.mbms { } public static class MbmsException.InitializationErrors { - ctor public MbmsException.InitializationErrors(); field public static final int ERROR_APP_PERMISSIONS_NOT_GRANTED = 102; // 0x66 field public static final int ERROR_DUPLICATE_INITIALIZE = 101; // 0x65 field public static final int ERROR_UNABLE_TO_INITIALIZE = 103; // 0x67 } public static class MbmsException.StreamingErrors { - ctor public MbmsException.StreamingErrors(); field public static final int ERROR_CONCURRENT_SERVICE_LIMIT_REACHED = 301; // 0x12d field public static final int ERROR_DUPLICATE_START_STREAM = 303; // 0x12f field public static final int ERROR_UNABLE_TO_START_SERVICE = 302; // 0x12e } - public class MbmsStreamingManagerCallback extends android.os.Binder { + public class MbmsStreamingManagerCallback { ctor public MbmsStreamingManagerCallback(); - method public void error(int, java.lang.String) throws android.os.RemoteException; - method public void middlewareReady() throws android.os.RemoteException; - method public void streamingServicesUpdated(java.util.List<android.telephony.mbms.StreamingServiceInfo>) throws android.os.RemoteException; + method public void onError(int, java.lang.String); + method public void onMiddlewareReady(); + method public void onStreamingServicesUpdated(java.util.List<android.telephony.mbms.StreamingServiceInfo>); } - public class ServiceInfo implements android.os.Parcelable { - method public int describeContents(); + public class ServiceInfo { method public java.lang.String getClassName(); method public java.util.List<java.util.Locale> getLocales(); method public java.util.Map<java.util.Locale, java.lang.String> getNames(); method public java.lang.String getServiceId(); method public java.util.Date getSessionEndTime(); method public java.util.Date getSessionStartTime(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.telephony.mbms.ServiceInfo> CREATOR; } public class StreamingService { @@ -40592,7 +40616,7 @@ package android.telephony.mbms { field public static final int REASON_BY_USER_REQUEST = 1; // 0x1 field public static final int REASON_END_OF_SESSION = 2; // 0x2 field public static final int REASON_FREQUENCY_CONFLICT = 3; // 0x3 - field public static final int REASON_LEFT_MBMS_BROADCAST_AREA = 5; // 0x5 + field public static final int REASON_LEFT_MBMS_BROADCAST_AREA = 6; // 0x6 field public static final int REASON_NONE = 0; // 0x0 field public static final int REASON_NOT_CONNECTED_TO_HOMECARRIER_LTE = 5; // 0x5 field public static final int REASON_OUT_OF_MEMORY = 4; // 0x4 @@ -40602,17 +40626,19 @@ package android.telephony.mbms { field public static final int UNICAST_METHOD = 2; // 0x2 } - public class StreamingServiceCallback extends android.os.Binder { + public class StreamingServiceCallback { ctor public StreamingServiceCallback(); - method public void broadcastSignalStrengthUpdated(int) throws android.os.RemoteException; - method public void error(int, java.lang.String) throws android.os.RemoteException; - method public void mediaDescriptionUpdated() throws android.os.RemoteException; - method public void streamMethodUpdated(int) throws android.os.RemoteException; - method public void streamStateUpdated(int, int) throws android.os.RemoteException; + method public void onBroadcastSignalStrengthUpdated(int); + method public void onError(int, java.lang.String); + method public void onMediaDescriptionUpdated(); + method public void onStreamMethodUpdated(int); + method public void onStreamStateUpdated(int, int); field public static final int SIGNAL_STRENGTH_UNAVAILABLE = -1; // 0xffffffff } - public class StreamingServiceInfo extends android.telephony.mbms.ServiceInfo implements android.os.Parcelable { + public final class StreamingServiceInfo extends android.telephony.mbms.ServiceInfo implements android.os.Parcelable { + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.telephony.mbms.StreamingServiceInfo> CREATOR; } @@ -41390,6 +41416,22 @@ package android.text { method public int getTopPadding(); } + public static final class DynamicLayout.Builder { + method public android.text.DynamicLayout build(); + method public static android.text.DynamicLayout.Builder obtain(java.lang.CharSequence, android.text.TextPaint, int); + method public android.text.DynamicLayout.Builder setAlignment(android.text.Layout.Alignment); + method public android.text.DynamicLayout.Builder setBreakStrategy(int); + method public android.text.DynamicLayout.Builder setDisplayText(java.lang.CharSequence); + method public android.text.DynamicLayout.Builder setEllipsize(android.text.TextUtils.TruncateAt); + method public android.text.DynamicLayout.Builder setEllipsizedWidth(int); + method public android.text.DynamicLayout.Builder setHyphenationFrequency(int); + method public android.text.DynamicLayout.Builder setIncludePad(boolean); + method public android.text.DynamicLayout.Builder setJustificationMode(int); + method public android.text.DynamicLayout.Builder setLineSpacing(float, float); + method public android.text.DynamicLayout.Builder setTextDirection(android.text.TextDirectionHeuristic); + method public android.text.DynamicLayout.Builder setUseLineSpacingFromFallbacks(boolean); + } + public abstract interface Editable implements java.lang.Appendable java.lang.CharSequence android.text.GetChars android.text.Spannable { method public abstract android.text.Editable append(java.lang.CharSequence); method public abstract android.text.Editable append(java.lang.CharSequence, int, int); @@ -41554,6 +41596,8 @@ package android.text { field public static final int BREAK_STRATEGY_BALANCED = 2; // 0x2 field public static final int BREAK_STRATEGY_HIGH_QUALITY = 1; // 0x1 field public static final int BREAK_STRATEGY_SIMPLE = 0; // 0x0 + field public static final float DEFAULT_LINESPACING_ADDITION = 0.0f; + field public static final float DEFAULT_LINESPACING_MULTIPLIER = 1.0f; field public static final int DIR_LEFT_TO_RIGHT = 1; // 0x1 field public static final int DIR_RIGHT_TO_LEFT = -1; // 0xffffffff field public static final int HYPHENATION_FREQUENCY_FULL = 2; // 0x2 @@ -41767,6 +41811,7 @@ package android.text { method public android.text.StaticLayout.Builder setMaxLines(int); method public android.text.StaticLayout.Builder setText(java.lang.CharSequence); method public android.text.StaticLayout.Builder setTextDirection(android.text.TextDirectionHeuristic); + method public android.text.StaticLayout.Builder setUseLineSpacingFromFallbacks(boolean); } public abstract interface TextDirectionHeuristic { @@ -44300,9 +44345,13 @@ package android.view { field public static final int CONTEXT_CLICK = 6; // 0x6 field public static final int FLAG_IGNORE_GLOBAL_SETTING = 2; // 0x2 field public static final int FLAG_IGNORE_VIEW_SETTING = 1; // 0x1 + field public static final int KEYBOARD_PRESS = 3; // 0x3 + field public static final int KEYBOARD_RELEASE = 7; // 0x7 field public static final int KEYBOARD_TAP = 3; // 0x3 field public static final int LONG_PRESS = 0; // 0x0 + field public static final int TEXT_HANDLE_MOVE = 9; // 0x9 field public static final int VIRTUAL_KEY = 1; // 0x1 + field public static final int VIRTUAL_KEY_RELEASE = 8; // 0x8 } public class InflateException extends java.lang.RuntimeException { @@ -44930,6 +44979,7 @@ package android.view { method public abstract void removeGroup(int); method public abstract void removeItem(int); method public abstract void setGroupCheckable(int, boolean, boolean); + method public default void setGroupDividerEnabled(boolean); method public abstract void setGroupEnabled(int, boolean); method public abstract void setGroupVisible(int, boolean); method public abstract void setQwertyMode(boolean); @@ -45362,15 +45412,11 @@ package android.view { public class Surface implements android.os.Parcelable { ctor public Surface(android.graphics.SurfaceTexture); method public int describeContents(); - method public boolean isAutoRefreshEnabled(); - method public boolean isSharedBufferModeEnabled(); method public boolean isValid(); method public android.graphics.Canvas lockCanvas(android.graphics.Rect) throws java.lang.IllegalArgumentException, android.view.Surface.OutOfResourcesException; method public android.graphics.Canvas lockHardwareCanvas(); method public void readFromParcel(android.os.Parcel); method public void release(); - method public void setAutoRefreshEnabled(boolean); - method public void setSharedBufferModeEnabled(boolean); method public deprecated void unlockCanvas(android.graphics.Canvas); method public void unlockCanvasAndPost(android.graphics.Canvas); method public void writeToParcel(android.os.Parcel, int); @@ -47340,6 +47386,7 @@ package android.view.accessibility { method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int); method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList(); method public void interrupt(); + method public static boolean isAccessibilityButtonSupported(); method public boolean isEnabled(); method public boolean isTouchExplorationEnabled(); method public void removeAccessibilityRequestPreparer(android.view.accessibility.AccessibilityRequestPreparer); @@ -47622,6 +47669,8 @@ package android.view.accessibility { method public int getMaxScrollY(); method public android.os.Parcelable getParcelableData(); method public int getRemovedCount(); + method public int getScrollDeltaX(); + method public int getScrollDeltaY(); method public int getScrollX(); method public int getScrollY(); method public android.view.accessibility.AccessibilityNodeInfo getSource(); @@ -47651,6 +47700,8 @@ package android.view.accessibility { method public void setParcelableData(android.os.Parcelable); method public void setPassword(boolean); method public void setRemovedCount(int); + method public void setScrollDeltaX(int); + method public void setScrollDeltaY(int); method public void setScrollX(int); method public void setScrollY(int); method public void setScrollable(boolean); @@ -49204,7 +49255,6 @@ package android.webkit { method public void goBack(); method public void goBackOrForward(int); method public void goForward(); - method public static void initSafeBrowsing(android.content.Context, android.webkit.ValueCallback<java.lang.Boolean>); method public void invokeZoomPicker(); method public boolean isPrivateBrowsingEnabled(); method public void loadData(java.lang.String, java.lang.String, java.lang.String); @@ -49252,7 +49302,7 @@ package android.webkit { method public void setWebViewClient(android.webkit.WebViewClient); method public deprecated boolean shouldDelayChildPressedState(); method public deprecated boolean showFindDialog(java.lang.String, boolean); - method public static void shutdownSafeBrowsing(); + method public static void startSafeBrowsing(android.content.Context, android.webkit.ValueCallback<java.lang.Boolean>); method public void stopLoading(); method public void zoomBy(float); method public boolean zoomIn(); diff --git a/api/removed.txt b/api/removed.txt index 6c37a8fbf133..fbd09f77dcde 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -227,13 +227,6 @@ package android.net { field public static final int BADGING_SD = 10; // 0xa } - public abstract class PskKeyManager { - ctor public PskKeyManager(); - field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80 - field public static final int MAX_IDENTITY_LENGTH_BYTES = 128; // 0x80 - field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100 - } - public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory { method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache); } diff --git a/api/system-current.txt b/api/system-current.txt index 6c497293e344..bacbd551c332 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -127,6 +127,7 @@ package android { field public static final java.lang.String INSTALL_GRANT_RUNTIME_PERMISSIONS = "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS"; field public static final java.lang.String INSTALL_LOCATION_PROVIDER = "android.permission.INSTALL_LOCATION_PROVIDER"; field public static final java.lang.String INSTALL_PACKAGES = "android.permission.INSTALL_PACKAGES"; + field public static final java.lang.String INSTALL_SELF_UPDATES = "android.permission.INSTALL_SELF_UPDATES"; field public static final java.lang.String INSTALL_SHORTCUT = "com.android.launcher.permission.INSTALL_SHORTCUT"; field public static final java.lang.String INSTANT_APP_FOREGROUND_SERVICE = "android.permission.INSTANT_APP_FOREGROUND_SERVICE"; field public static final java.lang.String INTENT_FILTER_VERIFICATION_AGENT = "android.permission.INTENT_FILTER_VERIFICATION_AGENT"; @@ -201,6 +202,7 @@ package android { field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS"; field public static final java.lang.String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS"; field public static final java.lang.String READ_VOICEMAIL = "com.android.voicemail.permission.READ_VOICEMAIL"; + field public static final java.lang.String READ_WALLPAPER_INTERNAL = "android.permission.READ_WALLPAPER_INTERNAL"; field public static final java.lang.String READ_WIFI_CREDENTIAL = "android.permission.READ_WIFI_CREDENTIAL"; field public static final java.lang.String REAL_GET_TASKS = "android.permission.REAL_GET_TASKS"; field public static final java.lang.String REBOOT = "android.permission.REBOOT"; @@ -1659,6 +1661,7 @@ package android { field public static final int windowHideAnimation = 16842935; // 0x10100b7 field public static final int windowIsFloating = 16842839; // 0x1010057 field public static final int windowIsTranslucent = 16842840; // 0x1010058 + field public static final int windowLightNavigationBar = 16844140; // 0x101056c field public static final int windowLightStatusBar = 16844000; // 0x10104e0 field public static final int windowMinWidthMajor = 16843606; // 0x1010356 field public static final int windowMinWidthMinor = 16843607; // 0x1010357 @@ -4377,12 +4380,6 @@ package android.app { public class Application extends android.content.ContextWrapper implements android.content.ComponentCallbacks2 { ctor public Application(); - method public android.app.Activity instantiateActivity(java.lang.ClassLoader, java.lang.String, android.content.Intent); - method public android.app.backup.BackupAgent instantiateBackupAgent(java.lang.ClassLoader, java.lang.String); - method public android.app.Instrumentation instantiateInstrumentation(java.lang.ClassLoader, java.lang.String); - method public android.content.ContentProvider instantiateProvider(java.lang.ClassLoader, java.lang.String); - method public android.content.BroadcastReceiver instantiateReceiver(java.lang.ClassLoader, java.lang.String, android.content.Intent); - method public android.app.Service instantiateService(java.lang.ClassLoader, java.lang.String, android.content.Intent); method public void onConfigurationChanged(android.content.res.Configuration); method public void onCreate(); method public void onLowMemory(); @@ -6349,7 +6346,6 @@ package android.app { } public class WallpaperManager { - method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener); method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler); method public void clear() throws java.io.IOException; method public void clear(int) throws java.io.IOException; @@ -6503,6 +6499,7 @@ package android.app.admin { method public void addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName); method public void addUserRestriction(android.content.ComponentName, java.lang.String); method public boolean bindDeviceAdminServiceAsUser(android.content.ComponentName, android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle); + method public boolean clearApplicationUserData(android.content.ComponentName, java.lang.String, android.app.admin.DevicePolicyManager.OnClearApplicationUserDataListener, android.os.Handler); method public void clearCrossProfileIntentFilters(android.content.ComponentName); method public deprecated void clearDeviceOwnerApp(java.lang.String); method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String); @@ -6790,6 +6787,10 @@ package android.app.admin { field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2 } + public static abstract interface DevicePolicyManager.OnClearApplicationUserDataListener { + method public abstract void onApplicationUserDataCleared(java.lang.String, boolean); + } + public final class DnsEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable { method public java.lang.String getHostname(); method public java.util.List<java.net.InetAddress> getInetAddresses(); @@ -10904,7 +10905,6 @@ package android.content.pm { method public int getVersionCode(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.content.pm.InstantAppResolveInfo> CREATOR; - field public static final java.lang.String SHA_ALGORITHM = "SHA-256"; } public static final class InstantAppResolveInfo.InstantAppDigest implements android.os.Parcelable { @@ -11605,8 +11605,8 @@ package android.content.pm { field public static final int PROTECTION_DANGEROUS = 1; // 0x1 field public static final int PROTECTION_FLAG_APPOP = 64; // 0x40 field public static final int PROTECTION_FLAG_DEVELOPMENT = 32; // 0x20 - field public static final int PROTECTION_FLAG_EPHEMERAL = 4096; // 0x1000 field public static final int PROTECTION_FLAG_INSTALLER = 256; // 0x100 + field public static final int PROTECTION_FLAG_INSTANT = 4096; // 0x1000 field public static final int PROTECTION_FLAG_PRE23 = 128; // 0x80 field public static final int PROTECTION_FLAG_PREINSTALLED = 1024; // 0x400 field public static final int PROTECTION_FLAG_PRIVILEGED = 16; // 0x10 @@ -16572,6 +16572,7 @@ package android.hardware.display { method public android.view.Display getDisplay(int); method public android.view.Display[] getDisplays(); method public android.view.Display[] getDisplays(java.lang.String); + method public android.graphics.Point getStableDisplaySize(); method public void registerDisplayListener(android.hardware.display.DisplayManager.DisplayListener, android.os.Handler); method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener); field public static final java.lang.String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION"; @@ -16624,6 +16625,7 @@ package android.hardware.fingerprint { field public static final int FINGERPRINT_ERROR_NO_SPACE = 4; // 0x4 field public static final int FINGERPRINT_ERROR_TIMEOUT = 3; // 0x3 field public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; // 0x2 + field public static final int FINGERPRINT_ERROR_USER_CANCELED = 10; // 0xa field public static final int FINGERPRINT_ERROR_VENDOR = 8; // 0x8 } @@ -17594,6 +17596,7 @@ package android.hardware.usb { public class UsbManager { method public android.hardware.usb.UsbAccessory[] getAccessoryList(); method public java.util.HashMap<java.lang.String, android.hardware.usb.UsbDevice> getDeviceList(); + method public void grantPermission(android.hardware.usb.UsbDevice, java.lang.String); method public boolean hasPermission(android.hardware.usb.UsbDevice); method public boolean hasPermission(android.hardware.usb.UsbAccessory); method public android.os.ParcelFileDescriptor openAccessory(android.hardware.usb.UsbAccessory); @@ -19663,11 +19666,13 @@ package android.icu.text { method public synchronized void applyLocalizedPattern(java.lang.String); method public synchronized void applyPattern(java.lang.String); method public synchronized boolean areSignificantDigitsUsed(); + method public synchronized boolean equals(java.lang.Object); method public java.lang.StringBuffer format(double, java.lang.StringBuffer, java.text.FieldPosition); method public java.lang.StringBuffer format(long, java.lang.StringBuffer, java.text.FieldPosition); method public java.lang.StringBuffer format(java.math.BigInteger, java.lang.StringBuffer, java.text.FieldPosition); method public java.lang.StringBuffer format(java.math.BigDecimal, java.lang.StringBuffer, java.text.FieldPosition); method public java.lang.StringBuffer format(android.icu.math.BigDecimal, java.lang.StringBuffer, java.text.FieldPosition); + method public synchronized android.icu.util.Currency getCurrency(); method public synchronized android.icu.text.CurrencyPluralInfo getCurrencyPluralInfo(); method public synchronized android.icu.util.Currency.CurrencyUsage getCurrencyUsage(); method public synchronized android.icu.text.DecimalFormatSymbols getDecimalFormatSymbols(); @@ -19675,8 +19680,12 @@ package android.icu.text { method public synchronized int getGroupingSize(); method public synchronized java.math.MathContext getMathContext(); method public synchronized android.icu.math.MathContext getMathContextICU(); + method public synchronized int getMaximumFractionDigits(); + method public synchronized int getMaximumIntegerDigits(); method public synchronized int getMaximumSignificantDigits(); method public synchronized byte getMinimumExponentDigits(); + method public synchronized int getMinimumFractionDigits(); + method public synchronized int getMinimumIntegerDigits(); method public synchronized int getMinimumSignificantDigits(); method public synchronized int getMultiplier(); method public synchronized java.lang.String getNegativePrefix(); @@ -19687,13 +19696,19 @@ package android.icu.text { method public synchronized java.lang.String getPositivePrefix(); method public synchronized java.lang.String getPositiveSuffix(); method public synchronized java.math.BigDecimal getRoundingIncrement(); + method public synchronized int getRoundingMode(); method public synchronized int getSecondaryGroupingSize(); + method public synchronized int hashCode(); method public synchronized boolean isDecimalPatternMatchRequired(); method public synchronized boolean isDecimalSeparatorAlwaysShown(); method public synchronized boolean isExponentSignAlwaysShown(); + method public synchronized boolean isGroupingUsed(); method public synchronized boolean isParseBigDecimal(); + method public synchronized boolean isParseIntegerOnly(); + method public synchronized boolean isParseStrict(); method public synchronized boolean isScientificNotation(); method public java.lang.Number parse(java.lang.String, java.text.ParsePosition); + method public synchronized void setCurrency(android.icu.util.Currency); method public synchronized void setCurrencyPluralInfo(android.icu.text.CurrencyPluralInfo); method public synchronized void setCurrencyUsage(android.icu.util.Currency.CurrencyUsage); method public synchronized void setDecimalFormatSymbols(android.icu.text.DecimalFormatSymbols); @@ -19702,10 +19717,15 @@ package android.icu.text { method public synchronized void setExponentSignAlwaysShown(boolean); method public synchronized void setFormatWidth(int); method public synchronized void setGroupingSize(int); + method public synchronized void setGroupingUsed(boolean); method public synchronized void setMathContext(java.math.MathContext); method public synchronized void setMathContextICU(android.icu.math.MathContext); + method public synchronized void setMaximumFractionDigits(int); + method public synchronized void setMaximumIntegerDigits(int); method public synchronized void setMaximumSignificantDigits(int); method public synchronized void setMinimumExponentDigits(byte); + method public synchronized void setMinimumFractionDigits(int); + method public synchronized void setMinimumIntegerDigits(int); method public synchronized void setMinimumSignificantDigits(int); method public synchronized void setMultiplier(int); method public synchronized void setNegativePrefix(java.lang.String); @@ -19713,12 +19733,15 @@ package android.icu.text { method public synchronized void setPadCharacter(char); method public synchronized void setPadPosition(int); method public synchronized void setParseBigDecimal(boolean); + method public synchronized void setParseIntegerOnly(boolean); method public deprecated void setParseMaxDigits(int); + method public synchronized void setParseStrict(boolean); method public synchronized void setPositivePrefix(java.lang.String); method public synchronized void setPositiveSuffix(java.lang.String); method public synchronized void setRoundingIncrement(java.math.BigDecimal); method public synchronized void setRoundingIncrement(android.icu.math.BigDecimal); method public synchronized void setRoundingIncrement(double); + method public synchronized void setRoundingMode(int); method public synchronized void setScientificNotation(boolean); method public synchronized void setSecondaryGroupingSize(int); method public synchronized void setSignificantDigitsUsed(boolean); @@ -28365,8 +28388,8 @@ package android.net { method public boolean protect(java.net.Socket); method public boolean protect(java.net.DatagramSocket); method public boolean setUnderlyingNetworks(android.net.Network[]); - field public static final java.lang.String METADATA_SUPPORTS_ALWAYS_ON = "android.net.VpnService.SUPPORTS_ALWAYS_ON"; field public static final java.lang.String SERVICE_INTERFACE = "android.net.VpnService"; + field public static final java.lang.String SERVICE_META_DATA_SUPPORTS_ALWAYS_ON = "android.net.VpnService.SUPPORTS_ALWAYS_ON"; } public class VpnService.Builder { @@ -33373,7 +33396,8 @@ package android.os { field public static final int N = 24; // 0x18 field public static final int N_MR1 = 25; // 0x19 field public static final int O = 26; // 0x1a - field public static final int O_MR1 = 10000; // 0x2710 + field public static final int O_MR1 = 27; // 0x1b + field public static final int P = 10000; // 0x2710 } public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable { @@ -40150,13 +40174,14 @@ package android.service.autofill { public final class FillEventHistory implements android.os.Parcelable { method public int describeContents(); - method public android.os.Bundle getClientState(); + method public deprecated android.os.Bundle getClientState(); method public java.util.List<android.service.autofill.FillEventHistory.Event> getEvents(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.service.autofill.FillEventHistory> CREATOR; } public static final class FillEventHistory.Event { + method public android.os.Bundle getClientState(); method public java.lang.String getDatasetId(); method public int getType(); field public static final int TYPE_AUTHENTICATION_SELECTED = 2; // 0x2 @@ -42162,7 +42187,7 @@ package android.telecom { public static final class Call.RttCall { method public int getRttAudioMode(); - method public java.lang.String read() throws java.io.IOException; + method public java.lang.String read(); method public java.lang.String readImmediately() throws java.io.IOException; method public void setRttMode(int); method public void write(java.lang.String) throws java.io.IOException; @@ -42252,6 +42277,7 @@ package android.telecom { method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>); method public final deprecated void setConnectTimeMillis(long); method public final void setConnectionCapabilities(int); + method public final void setConnectionElapsedTime(long); method public final void setConnectionProperties(int); method public final void setConnectionTime(long); method public final void setDialing(); @@ -43073,11 +43099,13 @@ package android.telephony { field public static final java.lang.String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string"; field public static final java.lang.String KEY_DIAL_STRING_REPLACE_STRING_ARRAY = "dial_string_replace_string_array"; field public static final java.lang.String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool"; + field public static final java.lang.String KEY_DISPLAY_HD_AUDIO_PROPERTY_BOOL = "display_hd_audio_property_bool"; field public static final java.lang.String KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL = "drop_video_call_when_answering_audio_call_bool"; field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool"; field public static final java.lang.String KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT = "duration_blocking_disabled_after_emergency_int"; field public static final java.lang.String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool"; field public static final java.lang.String KEY_EDITABLE_VOICEMAIL_NUMBER_BOOL = "editable_voicemail_number_bool"; + field public static final java.lang.String KEY_ENABLE_APPS_STRING_ARRAY = "enable_apps_string_array"; field public static final java.lang.String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_key_vibration_bool"; field public static final java.lang.String KEY_FORCE_HOME_NETWORK_BOOL = "force_home_network_bool"; field public static final java.lang.String KEY_GSM_DTMF_TONE_DELAY_INT = "gsm_dtmf_tone_delay_int"; @@ -43337,11 +43365,12 @@ package android.telephony { } public class MbmsStreamingManager { - method public static android.telephony.MbmsStreamingManager create(android.content.Context, android.telephony.mbms.MbmsStreamingManagerCallback, int) throws android.telephony.mbms.MbmsException; + method public static android.telephony.MbmsStreamingManager create(android.content.Context, android.telephony.mbms.MbmsStreamingManagerCallback, int, android.os.Handler) throws android.telephony.mbms.MbmsException; + method public static android.telephony.MbmsStreamingManager create(android.content.Context, android.telephony.mbms.MbmsStreamingManagerCallback, android.os.Handler) throws android.telephony.mbms.MbmsException; method public static android.telephony.MbmsStreamingManager create(android.content.Context, android.telephony.mbms.MbmsStreamingManagerCallback) throws android.telephony.mbms.MbmsException; method public void dispose(); method public void getStreamingServices(java.util.List<java.lang.String>) throws android.telephony.mbms.MbmsException; - method public android.telephony.mbms.StreamingService startStreaming(android.telephony.mbms.StreamingServiceInfo, android.telephony.mbms.StreamingServiceCallback) throws android.telephony.mbms.MbmsException; + method public android.telephony.mbms.StreamingService startStreaming(android.telephony.mbms.StreamingServiceInfo, android.telephony.mbms.StreamingServiceCallback, android.os.Handler) throws android.telephony.mbms.MbmsException; field public static final java.lang.String MBMS_STREAMING_SERVICE_ACTION = "android.telephony.action.EmbmsStreaming"; } @@ -43549,9 +43578,12 @@ package android.telephony { field public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; // 0x3 field public static final int MMS_ERROR_UNSPECIFIED = 1; // 0x1 field public static final int RESULT_ERROR_GENERIC_FAILURE = 1; // 0x1 + field public static final int RESULT_ERROR_LIMIT_EXCEEDED = 5; // 0x5 field public static final int RESULT_ERROR_NO_SERVICE = 4; // 0x4 field public static final int RESULT_ERROR_NULL_PDU = 3; // 0x3 field public static final int RESULT_ERROR_RADIO_OFF = 2; // 0x2 + field public static final int RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED = 8; // 0x8 + field public static final int RESULT_ERROR_SHORT_CODE_NOT_ALLOWED = 7; // 0x7 field public static final int STATUS_ON_ICC_FREE = 0; // 0x0 field public static final int STATUS_ON_ICC_READ = 1; // 0x1 field public static final int STATUS_ON_ICC_SENT = 5; // 0x5 @@ -44099,7 +44131,6 @@ package android.telephony.mbms { } public static class MbmsException.GeneralErrors { - ctor public MbmsException.GeneralErrors(); field public static final int ERROR_CARRIER_CHANGE_NOT_ALLOWED = 207; // 0xcf field public static final int ERROR_IN_E911 = 204; // 0xcc field public static final int ERROR_MIDDLEWARE_NOT_YET_READY = 201; // 0xc9 @@ -44110,36 +44141,31 @@ package android.telephony.mbms { } public static class MbmsException.InitializationErrors { - ctor public MbmsException.InitializationErrors(); field public static final int ERROR_APP_PERMISSIONS_NOT_GRANTED = 102; // 0x66 field public static final int ERROR_DUPLICATE_INITIALIZE = 101; // 0x65 field public static final int ERROR_UNABLE_TO_INITIALIZE = 103; // 0x67 } public static class MbmsException.StreamingErrors { - ctor public MbmsException.StreamingErrors(); field public static final int ERROR_CONCURRENT_SERVICE_LIMIT_REACHED = 301; // 0x12d field public static final int ERROR_DUPLICATE_START_STREAM = 303; // 0x12f field public static final int ERROR_UNABLE_TO_START_SERVICE = 302; // 0x12e } - public class MbmsStreamingManagerCallback extends android.os.Binder { + public class MbmsStreamingManagerCallback { ctor public MbmsStreamingManagerCallback(); - method public void error(int, java.lang.String) throws android.os.RemoteException; - method public void middlewareReady() throws android.os.RemoteException; - method public void streamingServicesUpdated(java.util.List<android.telephony.mbms.StreamingServiceInfo>) throws android.os.RemoteException; + method public void onError(int, java.lang.String); + method public void onMiddlewareReady(); + method public void onStreamingServicesUpdated(java.util.List<android.telephony.mbms.StreamingServiceInfo>); } - public class ServiceInfo implements android.os.Parcelable { - method public int describeContents(); + public class ServiceInfo { method public java.lang.String getClassName(); method public java.util.List<java.util.Locale> getLocales(); method public java.util.Map<java.util.Locale, java.lang.String> getNames(); method public java.lang.String getServiceId(); method public java.util.Date getSessionEndTime(); method public java.util.Date getSessionStartTime(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.telephony.mbms.ServiceInfo> CREATOR; } public class StreamingService { @@ -44151,7 +44177,7 @@ package android.telephony.mbms { field public static final int REASON_BY_USER_REQUEST = 1; // 0x1 field public static final int REASON_END_OF_SESSION = 2; // 0x2 field public static final int REASON_FREQUENCY_CONFLICT = 3; // 0x3 - field public static final int REASON_LEFT_MBMS_BROADCAST_AREA = 5; // 0x5 + field public static final int REASON_LEFT_MBMS_BROADCAST_AREA = 6; // 0x6 field public static final int REASON_NONE = 0; // 0x0 field public static final int REASON_NOT_CONNECTED_TO_HOMECARRIER_LTE = 5; // 0x5 field public static final int REASON_OUT_OF_MEMORY = 4; // 0x4 @@ -44161,18 +44187,20 @@ package android.telephony.mbms { field public static final int UNICAST_METHOD = 2; // 0x2 } - public class StreamingServiceCallback extends android.os.Binder { + public class StreamingServiceCallback { ctor public StreamingServiceCallback(); - method public void broadcastSignalStrengthUpdated(int) throws android.os.RemoteException; - method public void error(int, java.lang.String) throws android.os.RemoteException; - method public void mediaDescriptionUpdated() throws android.os.RemoteException; - method public void streamMethodUpdated(int) throws android.os.RemoteException; - method public void streamStateUpdated(int, int) throws android.os.RemoteException; + method public void onBroadcastSignalStrengthUpdated(int); + method public void onError(int, java.lang.String); + method public void onMediaDescriptionUpdated(); + method public void onStreamMethodUpdated(int); + method public void onStreamStateUpdated(int, int); field public static final int SIGNAL_STRENGTH_UNAVAILABLE = -1; // 0xffffffff } - public class StreamingServiceInfo extends android.telephony.mbms.ServiceInfo implements android.os.Parcelable { + public final class StreamingServiceInfo extends android.telephony.mbms.ServiceInfo implements android.os.Parcelable { ctor public StreamingServiceInfo(java.util.Map<java.util.Locale, java.lang.String>, java.lang.String, java.util.List<java.util.Locale>, java.lang.String, java.util.Date, java.util.Date); + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.telephony.mbms.StreamingServiceInfo> CREATOR; } @@ -44187,6 +44215,7 @@ package android.telephony.mbms.vendor { method public android.net.Uri getPlaybackUri(int, java.lang.String) throws android.os.RemoteException; method public int getStreamingServices(int, java.util.List<java.lang.String>) throws android.os.RemoteException; method public int initialize(android.telephony.mbms.MbmsStreamingManagerCallback, int) throws android.os.RemoteException; + method public void onAppCallbackDied(int, int); method public int startStreaming(int, java.lang.String, android.telephony.mbms.StreamingServiceCallback) throws android.os.RemoteException; method public void stopStreaming(int, java.lang.String) throws android.os.RemoteException; } @@ -44992,6 +45021,22 @@ package android.text { method public int getTopPadding(); } + public static final class DynamicLayout.Builder { + method public android.text.DynamicLayout build(); + method public static android.text.DynamicLayout.Builder obtain(java.lang.CharSequence, android.text.TextPaint, int); + method public android.text.DynamicLayout.Builder setAlignment(android.text.Layout.Alignment); + method public android.text.DynamicLayout.Builder setBreakStrategy(int); + method public android.text.DynamicLayout.Builder setDisplayText(java.lang.CharSequence); + method public android.text.DynamicLayout.Builder setEllipsize(android.text.TextUtils.TruncateAt); + method public android.text.DynamicLayout.Builder setEllipsizedWidth(int); + method public android.text.DynamicLayout.Builder setHyphenationFrequency(int); + method public android.text.DynamicLayout.Builder setIncludePad(boolean); + method public android.text.DynamicLayout.Builder setJustificationMode(int); + method public android.text.DynamicLayout.Builder setLineSpacing(float, float); + method public android.text.DynamicLayout.Builder setTextDirection(android.text.TextDirectionHeuristic); + method public android.text.DynamicLayout.Builder setUseLineSpacingFromFallbacks(boolean); + } + public abstract interface Editable implements java.lang.Appendable java.lang.CharSequence android.text.GetChars android.text.Spannable { method public abstract android.text.Editable append(java.lang.CharSequence); method public abstract android.text.Editable append(java.lang.CharSequence, int, int); @@ -45156,6 +45201,8 @@ package android.text { field public static final int BREAK_STRATEGY_BALANCED = 2; // 0x2 field public static final int BREAK_STRATEGY_HIGH_QUALITY = 1; // 0x1 field public static final int BREAK_STRATEGY_SIMPLE = 0; // 0x0 + field public static final float DEFAULT_LINESPACING_ADDITION = 0.0f; + field public static final float DEFAULT_LINESPACING_MULTIPLIER = 1.0f; field public static final int DIR_LEFT_TO_RIGHT = 1; // 0x1 field public static final int DIR_RIGHT_TO_LEFT = -1; // 0xffffffff field public static final int HYPHENATION_FREQUENCY_FULL = 2; // 0x2 @@ -45369,6 +45416,7 @@ package android.text { method public android.text.StaticLayout.Builder setMaxLines(int); method public android.text.StaticLayout.Builder setText(java.lang.CharSequence); method public android.text.StaticLayout.Builder setTextDirection(android.text.TextDirectionHeuristic); + method public android.text.StaticLayout.Builder setUseLineSpacingFromFallbacks(boolean); } public abstract interface TextDirectionHeuristic { @@ -47904,9 +47952,13 @@ package android.view { field public static final int CONTEXT_CLICK = 6; // 0x6 field public static final int FLAG_IGNORE_GLOBAL_SETTING = 2; // 0x2 field public static final int FLAG_IGNORE_VIEW_SETTING = 1; // 0x1 + field public static final int KEYBOARD_PRESS = 3; // 0x3 + field public static final int KEYBOARD_RELEASE = 7; // 0x7 field public static final int KEYBOARD_TAP = 3; // 0x3 field public static final int LONG_PRESS = 0; // 0x0 + field public static final int TEXT_HANDLE_MOVE = 9; // 0x9 field public static final int VIRTUAL_KEY = 1; // 0x1 + field public static final int VIRTUAL_KEY_RELEASE = 8; // 0x8 } public class InflateException extends java.lang.RuntimeException { @@ -48534,6 +48586,7 @@ package android.view { method public abstract void removeGroup(int); method public abstract void removeItem(int); method public abstract void setGroupCheckable(int, boolean, boolean); + method public default void setGroupDividerEnabled(boolean); method public abstract void setGroupEnabled(int, boolean); method public abstract void setGroupVisible(int, boolean); method public abstract void setQwertyMode(boolean); @@ -48966,15 +49019,11 @@ package android.view { public class Surface implements android.os.Parcelable { ctor public Surface(android.graphics.SurfaceTexture); method public int describeContents(); - method public boolean isAutoRefreshEnabled(); - method public boolean isSharedBufferModeEnabled(); method public boolean isValid(); method public android.graphics.Canvas lockCanvas(android.graphics.Rect) throws java.lang.IllegalArgumentException, android.view.Surface.OutOfResourcesException; method public android.graphics.Canvas lockHardwareCanvas(); method public void readFromParcel(android.os.Parcel); method public void release(); - method public void setAutoRefreshEnabled(boolean); - method public void setSharedBufferModeEnabled(boolean); method public deprecated void unlockCanvas(android.graphics.Canvas); method public void unlockCanvasAndPost(android.graphics.Canvas); method public void writeToParcel(android.os.Parcel, int); @@ -51231,6 +51280,8 @@ package android.view.accessibility { method public int getMaxScrollY(); method public android.os.Parcelable getParcelableData(); method public int getRemovedCount(); + method public int getScrollDeltaX(); + method public int getScrollDeltaY(); method public int getScrollX(); method public int getScrollY(); method public android.view.accessibility.AccessibilityNodeInfo getSource(); @@ -51260,6 +51311,8 @@ package android.view.accessibility { method public void setParcelableData(android.os.Parcelable); method public void setPassword(boolean); method public void setRemovedCount(int); + method public void setScrollDeltaX(int); + method public void setScrollDeltaY(int); method public void setScrollX(int); method public void setScrollY(int); method public void setScrollable(boolean); @@ -52907,7 +52960,6 @@ package android.webkit { method public void goBack(); method public void goBackOrForward(int); method public void goForward(); - method public static void initSafeBrowsing(android.content.Context, android.webkit.ValueCallback<java.lang.Boolean>); method public void invokeZoomPicker(); method public boolean isPrivateBrowsingEnabled(); method public void loadData(java.lang.String, java.lang.String, java.lang.String); @@ -52955,7 +53007,7 @@ package android.webkit { method public void setWebViewClient(android.webkit.WebViewClient); method public deprecated boolean shouldDelayChildPressedState(); method public deprecated boolean showFindDialog(java.lang.String, boolean); - method public static void shutdownSafeBrowsing(); + method public static void startSafeBrowsing(android.content.Context, android.webkit.ValueCallback<java.lang.Boolean>); method public void stopLoading(); method public void zoomBy(float); method public boolean zoomIn(); @@ -53152,7 +53204,6 @@ package android.webkit { method public abstract android.net.Uri[] parseFileChooserResult(int, android.content.Intent); method public abstract void setSafeBrowsingWhitelist(java.util.List<java.lang.String>, android.webkit.ValueCallback<java.lang.Boolean>); method public abstract void setWebContentsDebuggingEnabled(boolean); - method public abstract void shutdownSafeBrowsing(); } public class WebViewFragment extends android.app.Fragment { diff --git a/api/system-removed.txt b/api/system-removed.txt index 4f78176e8c51..7ee261e88fc7 100644 --- a/api/system-removed.txt +++ b/api/system-removed.txt @@ -297,13 +297,6 @@ package android.net { field public static final int BADGING_SD = 10; // 0xa } - public abstract class PskKeyManager { - ctor public PskKeyManager(); - field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80 - field public static final int MAX_IDENTITY_LENGTH_BYTES = 128; // 0x80 - field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100 - } - public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory { method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache); } diff --git a/api/test-current.txt b/api/test-current.txt index 464ec492fdbc..d270f7c7c403 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1524,6 +1524,7 @@ package android { field public static final int windowHideAnimation = 16842935; // 0x10100b7 field public static final int windowIsFloating = 16842839; // 0x1010057 field public static final int windowIsTranslucent = 16842840; // 0x1010058 + field public static final int windowLightNavigationBar = 16844140; // 0x101056c field public static final int windowLightStatusBar = 16844000; // 0x10104e0 field public static final int windowMinWidthMajor = 16843606; // 0x1010356 field public static final int windowMinWidthMinor = 16843607; // 0x1010357 @@ -4227,12 +4228,6 @@ package android.app { public class Application extends android.content.ContextWrapper implements android.content.ComponentCallbacks2 { ctor public Application(); - method public android.app.Activity instantiateActivity(java.lang.ClassLoader, java.lang.String, android.content.Intent); - method public android.app.backup.BackupAgent instantiateBackupAgent(java.lang.ClassLoader, java.lang.String); - method public android.app.Instrumentation instantiateInstrumentation(java.lang.ClassLoader, java.lang.String); - method public android.content.ContentProvider instantiateProvider(java.lang.ClassLoader, java.lang.String); - method public android.content.BroadcastReceiver instantiateReceiver(java.lang.ClassLoader, java.lang.String, android.content.Intent); - method public android.app.Service instantiateService(java.lang.ClassLoader, java.lang.String, android.content.Intent); method public void onConfigurationChanged(android.content.res.Configuration); method public void onCreate(); method public void onLowMemory(); @@ -6161,7 +6156,6 @@ package android.app { } public class WallpaperManager { - method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener); method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler); method public void clear() throws java.io.IOException; method public void clear(int) throws java.io.IOException; @@ -6310,6 +6304,7 @@ package android.app.admin { method public void addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName); method public void addUserRestriction(android.content.ComponentName, java.lang.String); method public boolean bindDeviceAdminServiceAsUser(android.content.ComponentName, android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle); + method public boolean clearApplicationUserData(android.content.ComponentName, java.lang.String, android.app.admin.DevicePolicyManager.OnClearApplicationUserDataListener, android.os.Handler); method public void clearCrossProfileIntentFilters(android.content.ComponentName); method public deprecated void clearDeviceOwnerApp(java.lang.String); method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String); @@ -6574,6 +6569,10 @@ package android.app.admin { field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2 } + public static abstract interface DevicePolicyManager.OnClearApplicationUserDataListener { + method public abstract void onApplicationUserDataCleared(java.lang.String, boolean); + } + public final class DnsEvent extends android.app.admin.NetworkEvent implements android.os.Parcelable { method public java.lang.String getHostname(); method public java.util.List<java.net.InetAddress> getInetAddresses(); @@ -10929,8 +10928,8 @@ package android.content.pm { field public static final int PROTECTION_DANGEROUS = 1; // 0x1 field public static final int PROTECTION_FLAG_APPOP = 64; // 0x40 field public static final int PROTECTION_FLAG_DEVELOPMENT = 32; // 0x20 - field public static final int PROTECTION_FLAG_EPHEMERAL = 4096; // 0x1000 field public static final int PROTECTION_FLAG_INSTALLER = 256; // 0x100 + field public static final int PROTECTION_FLAG_INSTANT = 4096; // 0x1000 field public static final int PROTECTION_FLAG_PRE23 = 128; // 0x80 field public static final int PROTECTION_FLAG_PREINSTALLED = 1024; // 0x400 field public static final int PROTECTION_FLAG_PRIVILEGED = 16; // 0x10 @@ -12071,6 +12070,15 @@ package android.database.sqlite { field public int pageCacheOverflow; } + public final class SQLiteDirectCursorDriver implements android.database.sqlite.SQLiteCursorDriver { + ctor public SQLiteDirectCursorDriver(android.database.sqlite.SQLiteDatabase, java.lang.String, java.lang.String, android.os.CancellationSignal); + method public void cursorClosed(); + method public void cursorDeactivated(); + method public void cursorRequeried(android.database.Cursor); + method public android.database.Cursor query(android.database.sqlite.SQLiteDatabase.CursorFactory, java.lang.String[]); + method public void setBindArguments(java.lang.String[]); + } + public class SQLiteDiskIOException extends android.database.sqlite.SQLiteException { ctor public SQLiteDiskIOException(); ctor public SQLiteDiskIOException(java.lang.String); @@ -15949,6 +15957,7 @@ package android.hardware.fingerprint { field public static final int FINGERPRINT_ERROR_NO_SPACE = 4; // 0x4 field public static final int FINGERPRINT_ERROR_TIMEOUT = 3; // 0x3 field public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; // 0x2 + field public static final int FINGERPRINT_ERROR_USER_CANCELED = 10; // 0xa field public static final int FINGERPRINT_ERROR_VENDOR = 8; // 0x8 } @@ -18197,11 +18206,13 @@ package android.icu.text { method public synchronized void applyLocalizedPattern(java.lang.String); method public synchronized void applyPattern(java.lang.String); method public synchronized boolean areSignificantDigitsUsed(); + method public synchronized boolean equals(java.lang.Object); method public java.lang.StringBuffer format(double, java.lang.StringBuffer, java.text.FieldPosition); method public java.lang.StringBuffer format(long, java.lang.StringBuffer, java.text.FieldPosition); method public java.lang.StringBuffer format(java.math.BigInteger, java.lang.StringBuffer, java.text.FieldPosition); method public java.lang.StringBuffer format(java.math.BigDecimal, java.lang.StringBuffer, java.text.FieldPosition); method public java.lang.StringBuffer format(android.icu.math.BigDecimal, java.lang.StringBuffer, java.text.FieldPosition); + method public synchronized android.icu.util.Currency getCurrency(); method public synchronized android.icu.text.CurrencyPluralInfo getCurrencyPluralInfo(); method public synchronized android.icu.util.Currency.CurrencyUsage getCurrencyUsage(); method public synchronized android.icu.text.DecimalFormatSymbols getDecimalFormatSymbols(); @@ -18209,8 +18220,12 @@ package android.icu.text { method public synchronized int getGroupingSize(); method public synchronized java.math.MathContext getMathContext(); method public synchronized android.icu.math.MathContext getMathContextICU(); + method public synchronized int getMaximumFractionDigits(); + method public synchronized int getMaximumIntegerDigits(); method public synchronized int getMaximumSignificantDigits(); method public synchronized byte getMinimumExponentDigits(); + method public synchronized int getMinimumFractionDigits(); + method public synchronized int getMinimumIntegerDigits(); method public synchronized int getMinimumSignificantDigits(); method public synchronized int getMultiplier(); method public synchronized java.lang.String getNegativePrefix(); @@ -18221,13 +18236,19 @@ package android.icu.text { method public synchronized java.lang.String getPositivePrefix(); method public synchronized java.lang.String getPositiveSuffix(); method public synchronized java.math.BigDecimal getRoundingIncrement(); + method public synchronized int getRoundingMode(); method public synchronized int getSecondaryGroupingSize(); + method public synchronized int hashCode(); method public synchronized boolean isDecimalPatternMatchRequired(); method public synchronized boolean isDecimalSeparatorAlwaysShown(); method public synchronized boolean isExponentSignAlwaysShown(); + method public synchronized boolean isGroupingUsed(); method public synchronized boolean isParseBigDecimal(); + method public synchronized boolean isParseIntegerOnly(); + method public synchronized boolean isParseStrict(); method public synchronized boolean isScientificNotation(); method public java.lang.Number parse(java.lang.String, java.text.ParsePosition); + method public synchronized void setCurrency(android.icu.util.Currency); method public synchronized void setCurrencyPluralInfo(android.icu.text.CurrencyPluralInfo); method public synchronized void setCurrencyUsage(android.icu.util.Currency.CurrencyUsage); method public synchronized void setDecimalFormatSymbols(android.icu.text.DecimalFormatSymbols); @@ -18236,10 +18257,15 @@ package android.icu.text { method public synchronized void setExponentSignAlwaysShown(boolean); method public synchronized void setFormatWidth(int); method public synchronized void setGroupingSize(int); + method public synchronized void setGroupingUsed(boolean); method public synchronized void setMathContext(java.math.MathContext); method public synchronized void setMathContextICU(android.icu.math.MathContext); + method public synchronized void setMaximumFractionDigits(int); + method public synchronized void setMaximumIntegerDigits(int); method public synchronized void setMaximumSignificantDigits(int); method public synchronized void setMinimumExponentDigits(byte); + method public synchronized void setMinimumFractionDigits(int); + method public synchronized void setMinimumIntegerDigits(int); method public synchronized void setMinimumSignificantDigits(int); method public synchronized void setMultiplier(int); method public synchronized void setNegativePrefix(java.lang.String); @@ -18247,12 +18273,15 @@ package android.icu.text { method public synchronized void setPadCharacter(char); method public synchronized void setPadPosition(int); method public synchronized void setParseBigDecimal(boolean); + method public synchronized void setParseIntegerOnly(boolean); method public deprecated void setParseMaxDigits(int); + method public synchronized void setParseStrict(boolean); method public synchronized void setPositivePrefix(java.lang.String); method public synchronized void setPositiveSuffix(java.lang.String); method public synchronized void setRoundingIncrement(java.math.BigDecimal); method public synchronized void setRoundingIncrement(android.icu.math.BigDecimal); method public synchronized void setRoundingIncrement(double); + method public synchronized void setRoundingMode(int); method public synchronized void setScientificNotation(boolean); method public synchronized void setSecondaryGroupingSize(int); method public synchronized void setSignificantDigitsUsed(boolean); @@ -26201,8 +26230,8 @@ package android.net { method public boolean protect(java.net.Socket); method public boolean protect(java.net.DatagramSocket); method public boolean setUnderlyingNetworks(android.net.Network[]); - field public static final java.lang.String METADATA_SUPPORTS_ALWAYS_ON = "android.net.VpnService.SUPPORTS_ALWAYS_ON"; field public static final java.lang.String SERVICE_INTERFACE = "android.net.VpnService"; + field public static final java.lang.String SERVICE_META_DATA_SUPPORTS_ALWAYS_ON = "android.net.VpnService.SUPPORTS_ALWAYS_ON"; } public class VpnService.Builder { @@ -30794,7 +30823,8 @@ package android.os { field public static final int N = 24; // 0x18 field public static final int N_MR1 = 25; // 0x19 field public static final int O = 26; // 0x1a - field public static final int O_MR1 = 10000; // 0x2710 + field public static final int O_MR1 = 27; // 0x1b + field public static final int P = 10000; // 0x2710 } public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable { @@ -37251,13 +37281,14 @@ package android.service.autofill { public final class FillEventHistory implements android.os.Parcelable { method public int describeContents(); - method public android.os.Bundle getClientState(); + method public deprecated android.os.Bundle getClientState(); method public java.util.List<android.service.autofill.FillEventHistory.Event> getEvents(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.service.autofill.FillEventHistory> CREATOR; } public static final class FillEventHistory.Event { + method public android.os.Bundle getClientState(); method public java.lang.String getDatasetId(); method public int getType(); field public static final int TYPE_AUTHENTICATION_SELECTED = 2; // 0x2 @@ -39150,7 +39181,7 @@ package android.telecom { public static final class Call.RttCall { method public int getRttAudioMode(); - method public java.lang.String read() throws java.io.IOException; + method public java.lang.String read(); method public java.lang.String readImmediately() throws java.io.IOException; method public void setRttMode(int); method public void write(java.lang.String) throws java.io.IOException; @@ -39235,6 +39266,7 @@ package android.telecom { method public final void setActive(); method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>); method public final void setConnectionCapabilities(int); + method public final void setConnectionElapsedTime(long); method public final void setConnectionProperties(int); method public final void setConnectionTime(long); method public final void setDialing(); @@ -39883,11 +39915,13 @@ package android.telephony { field public static final java.lang.String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string"; field public static final java.lang.String KEY_DIAL_STRING_REPLACE_STRING_ARRAY = "dial_string_replace_string_array"; field public static final java.lang.String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool"; + field public static final java.lang.String KEY_DISPLAY_HD_AUDIO_PROPERTY_BOOL = "display_hd_audio_property_bool"; field public static final java.lang.String KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL = "drop_video_call_when_answering_audio_call_bool"; field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool"; field public static final java.lang.String KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT = "duration_blocking_disabled_after_emergency_int"; field public static final java.lang.String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool"; field public static final java.lang.String KEY_EDITABLE_VOICEMAIL_NUMBER_BOOL = "editable_voicemail_number_bool"; + field public static final java.lang.String KEY_ENABLE_APPS_STRING_ARRAY = "enable_apps_string_array"; field public static final java.lang.String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_key_vibration_bool"; field public static final java.lang.String KEY_FORCE_HOME_NETWORK_BOOL = "force_home_network_bool"; field public static final java.lang.String KEY_GSM_DTMF_TONE_DELAY_INT = "gsm_dtmf_tone_delay_int"; @@ -40147,11 +40181,12 @@ package android.telephony { } public class MbmsStreamingManager { - method public static android.telephony.MbmsStreamingManager create(android.content.Context, android.telephony.mbms.MbmsStreamingManagerCallback, int) throws android.telephony.mbms.MbmsException; + method public static android.telephony.MbmsStreamingManager create(android.content.Context, android.telephony.mbms.MbmsStreamingManagerCallback, int, android.os.Handler) throws android.telephony.mbms.MbmsException; + method public static android.telephony.MbmsStreamingManager create(android.content.Context, android.telephony.mbms.MbmsStreamingManagerCallback, android.os.Handler) throws android.telephony.mbms.MbmsException; method public static android.telephony.MbmsStreamingManager create(android.content.Context, android.telephony.mbms.MbmsStreamingManagerCallback) throws android.telephony.mbms.MbmsException; method public void dispose(); method public void getStreamingServices(java.util.List<java.lang.String>) throws android.telephony.mbms.MbmsException; - method public android.telephony.mbms.StreamingService startStreaming(android.telephony.mbms.StreamingServiceInfo, android.telephony.mbms.StreamingServiceCallback) throws android.telephony.mbms.MbmsException; + method public android.telephony.mbms.StreamingService startStreaming(android.telephony.mbms.StreamingServiceInfo, android.telephony.mbms.StreamingServiceCallback, android.os.Handler) throws android.telephony.mbms.MbmsException; } public class NeighboringCellInfo implements android.os.Parcelable { @@ -40356,9 +40391,12 @@ package android.telephony { field public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; // 0x3 field public static final int MMS_ERROR_UNSPECIFIED = 1; // 0x1 field public static final int RESULT_ERROR_GENERIC_FAILURE = 1; // 0x1 + field public static final int RESULT_ERROR_LIMIT_EXCEEDED = 5; // 0x5 field public static final int RESULT_ERROR_NO_SERVICE = 4; // 0x4 field public static final int RESULT_ERROR_NULL_PDU = 3; // 0x3 field public static final int RESULT_ERROR_RADIO_OFF = 2; // 0x2 + field public static final int RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED = 8; // 0x8 + field public static final int RESULT_ERROR_SHORT_CODE_NOT_ALLOWED = 7; // 0x7 field public static final int STATUS_ON_ICC_FREE = 0; // 0x0 field public static final int STATUS_ON_ICC_READ = 1; // 0x1 field public static final int STATUS_ON_ICC_SENT = 5; // 0x5 @@ -40791,7 +40829,6 @@ package android.telephony.mbms { } public static class MbmsException.GeneralErrors { - ctor public MbmsException.GeneralErrors(); field public static final int ERROR_CARRIER_CHANGE_NOT_ALLOWED = 207; // 0xcf field public static final int ERROR_IN_E911 = 204; // 0xcc field public static final int ERROR_MIDDLEWARE_NOT_YET_READY = 201; // 0xc9 @@ -40802,36 +40839,31 @@ package android.telephony.mbms { } public static class MbmsException.InitializationErrors { - ctor public MbmsException.InitializationErrors(); field public static final int ERROR_APP_PERMISSIONS_NOT_GRANTED = 102; // 0x66 field public static final int ERROR_DUPLICATE_INITIALIZE = 101; // 0x65 field public static final int ERROR_UNABLE_TO_INITIALIZE = 103; // 0x67 } public static class MbmsException.StreamingErrors { - ctor public MbmsException.StreamingErrors(); field public static final int ERROR_CONCURRENT_SERVICE_LIMIT_REACHED = 301; // 0x12d field public static final int ERROR_DUPLICATE_START_STREAM = 303; // 0x12f field public static final int ERROR_UNABLE_TO_START_SERVICE = 302; // 0x12e } - public class MbmsStreamingManagerCallback extends android.os.Binder { + public class MbmsStreamingManagerCallback { ctor public MbmsStreamingManagerCallback(); - method public void error(int, java.lang.String) throws android.os.RemoteException; - method public void middlewareReady() throws android.os.RemoteException; - method public void streamingServicesUpdated(java.util.List<android.telephony.mbms.StreamingServiceInfo>) throws android.os.RemoteException; + method public void onError(int, java.lang.String); + method public void onMiddlewareReady(); + method public void onStreamingServicesUpdated(java.util.List<android.telephony.mbms.StreamingServiceInfo>); } - public class ServiceInfo implements android.os.Parcelable { - method public int describeContents(); + public class ServiceInfo { method public java.lang.String getClassName(); method public java.util.List<java.util.Locale> getLocales(); method public java.util.Map<java.util.Locale, java.lang.String> getNames(); method public java.lang.String getServiceId(); method public java.util.Date getSessionEndTime(); method public java.util.Date getSessionStartTime(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.telephony.mbms.ServiceInfo> CREATOR; } public class StreamingService { @@ -40843,7 +40875,7 @@ package android.telephony.mbms { field public static final int REASON_BY_USER_REQUEST = 1; // 0x1 field public static final int REASON_END_OF_SESSION = 2; // 0x2 field public static final int REASON_FREQUENCY_CONFLICT = 3; // 0x3 - field public static final int REASON_LEFT_MBMS_BROADCAST_AREA = 5; // 0x5 + field public static final int REASON_LEFT_MBMS_BROADCAST_AREA = 6; // 0x6 field public static final int REASON_NONE = 0; // 0x0 field public static final int REASON_NOT_CONNECTED_TO_HOMECARRIER_LTE = 5; // 0x5 field public static final int REASON_OUT_OF_MEMORY = 4; // 0x4 @@ -40853,17 +40885,19 @@ package android.telephony.mbms { field public static final int UNICAST_METHOD = 2; // 0x2 } - public class StreamingServiceCallback extends android.os.Binder { + public class StreamingServiceCallback { ctor public StreamingServiceCallback(); - method public void broadcastSignalStrengthUpdated(int) throws android.os.RemoteException; - method public void error(int, java.lang.String) throws android.os.RemoteException; - method public void mediaDescriptionUpdated() throws android.os.RemoteException; - method public void streamMethodUpdated(int) throws android.os.RemoteException; - method public void streamStateUpdated(int, int) throws android.os.RemoteException; + method public void onBroadcastSignalStrengthUpdated(int); + method public void onError(int, java.lang.String); + method public void onMediaDescriptionUpdated(); + method public void onStreamMethodUpdated(int); + method public void onStreamStateUpdated(int, int); field public static final int SIGNAL_STRENGTH_UNAVAILABLE = -1; // 0xffffffff } - public class StreamingServiceInfo extends android.telephony.mbms.ServiceInfo implements android.os.Parcelable { + public final class StreamingServiceInfo extends android.telephony.mbms.ServiceInfo implements android.os.Parcelable { + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.telephony.mbms.StreamingServiceInfo> CREATOR; } @@ -41646,6 +41680,22 @@ package android.text { method public int getTopPadding(); } + public static final class DynamicLayout.Builder { + method public android.text.DynamicLayout build(); + method public static android.text.DynamicLayout.Builder obtain(java.lang.CharSequence, android.text.TextPaint, int); + method public android.text.DynamicLayout.Builder setAlignment(android.text.Layout.Alignment); + method public android.text.DynamicLayout.Builder setBreakStrategy(int); + method public android.text.DynamicLayout.Builder setDisplayText(java.lang.CharSequence); + method public android.text.DynamicLayout.Builder setEllipsize(android.text.TextUtils.TruncateAt); + method public android.text.DynamicLayout.Builder setEllipsizedWidth(int); + method public android.text.DynamicLayout.Builder setHyphenationFrequency(int); + method public android.text.DynamicLayout.Builder setIncludePad(boolean); + method public android.text.DynamicLayout.Builder setJustificationMode(int); + method public android.text.DynamicLayout.Builder setLineSpacing(float, float); + method public android.text.DynamicLayout.Builder setTextDirection(android.text.TextDirectionHeuristic); + method public android.text.DynamicLayout.Builder setUseLineSpacingFromFallbacks(boolean); + } + public abstract interface Editable implements java.lang.Appendable java.lang.CharSequence android.text.GetChars android.text.Spannable { method public abstract android.text.Editable append(java.lang.CharSequence); method public abstract android.text.Editable append(java.lang.CharSequence, int, int); @@ -41810,6 +41860,8 @@ package android.text { field public static final int BREAK_STRATEGY_BALANCED = 2; // 0x2 field public static final int BREAK_STRATEGY_HIGH_QUALITY = 1; // 0x1 field public static final int BREAK_STRATEGY_SIMPLE = 0; // 0x0 + field public static final float DEFAULT_LINESPACING_ADDITION = 0.0f; + field public static final float DEFAULT_LINESPACING_MULTIPLIER = 1.0f; field public static final int DIR_LEFT_TO_RIGHT = 1; // 0x1 field public static final int DIR_RIGHT_TO_LEFT = -1; // 0xffffffff field public static final int HYPHENATION_FREQUENCY_FULL = 2; // 0x2 @@ -42030,6 +42082,7 @@ package android.text { method public android.text.StaticLayout.Builder setMaxLines(int); method public android.text.StaticLayout.Builder setText(java.lang.CharSequence); method public android.text.StaticLayout.Builder setTextDirection(android.text.TextDirectionHeuristic); + method public android.text.StaticLayout.Builder setUseLineSpacingFromFallbacks(boolean); } public abstract interface TextDirectionHeuristic { @@ -44476,10 +44529,13 @@ package android.view { } public final class Choreographer { + method public static long getFrameDelay(); method public static android.view.Choreographer getInstance(); method public void postFrameCallback(android.view.Choreographer.FrameCallback); method public void postFrameCallbackDelayed(android.view.Choreographer.FrameCallback, long); method public void removeFrameCallback(android.view.Choreographer.FrameCallback); + method public static void setFrameDelay(long); + field public static final int CALLBACK_ANIMATION = 1; // 0x1 } public static abstract interface Choreographer.FrameCallback { @@ -44730,9 +44786,13 @@ package android.view { field public static final int CONTEXT_CLICK = 6; // 0x6 field public static final int FLAG_IGNORE_GLOBAL_SETTING = 2; // 0x2 field public static final int FLAG_IGNORE_VIEW_SETTING = 1; // 0x1 + field public static final int KEYBOARD_PRESS = 3; // 0x3 + field public static final int KEYBOARD_RELEASE = 7; // 0x7 field public static final int KEYBOARD_TAP = 3; // 0x3 field public static final int LONG_PRESS = 0; // 0x0 + field public static final int TEXT_HANDLE_MOVE = 9; // 0x9 field public static final int VIRTUAL_KEY = 1; // 0x1 + field public static final int VIRTUAL_KEY_RELEASE = 8; // 0x8 } public class InflateException extends java.lang.RuntimeException { @@ -45365,6 +45425,7 @@ package android.view { method public abstract void removeGroup(int); method public abstract void removeItem(int); method public abstract void setGroupCheckable(int, boolean, boolean); + method public default void setGroupDividerEnabled(boolean); method public abstract void setGroupEnabled(int, boolean); method public abstract void setGroupVisible(int, boolean); method public abstract void setQwertyMode(boolean); @@ -45799,15 +45860,11 @@ package android.view { public class Surface implements android.os.Parcelable { ctor public Surface(android.graphics.SurfaceTexture); method public int describeContents(); - method public boolean isAutoRefreshEnabled(); - method public boolean isSharedBufferModeEnabled(); method public boolean isValid(); method public android.graphics.Canvas lockCanvas(android.graphics.Rect) throws java.lang.IllegalArgumentException, android.view.Surface.OutOfResourcesException; method public android.graphics.Canvas lockHardwareCanvas(); method public void readFromParcel(android.os.Parcel); method public void release(); - method public void setAutoRefreshEnabled(boolean); - method public void setSharedBufferModeEnabled(boolean); method public deprecated void unlockCanvas(android.graphics.Canvas); method public void unlockCanvasAndPost(android.graphics.Canvas); method public void writeToParcel(android.os.Parcel, int); @@ -47791,6 +47848,7 @@ package android.view.accessibility { method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int); method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList(); method public void interrupt(); + method public static boolean isAccessibilityButtonSupported(); method public boolean isEnabled(); method public boolean isTouchExplorationEnabled(); method public void removeAccessibilityRequestPreparer(android.view.accessibility.AccessibilityRequestPreparer); @@ -48074,6 +48132,8 @@ package android.view.accessibility { method public int getMaxScrollY(); method public android.os.Parcelable getParcelableData(); method public int getRemovedCount(); + method public int getScrollDeltaX(); + method public int getScrollDeltaY(); method public int getScrollX(); method public int getScrollY(); method public android.view.accessibility.AccessibilityNodeInfo getSource(); @@ -48103,6 +48163,8 @@ package android.view.accessibility { method public void setParcelableData(android.os.Parcelable); method public void setPassword(boolean); method public void setRemovedCount(int); + method public void setScrollDeltaX(int); + method public void setScrollDeltaY(int); method public void setScrollX(int); method public void setScrollY(int); method public void setScrollable(boolean); @@ -49658,7 +49720,6 @@ package android.webkit { method public void goBack(); method public void goBackOrForward(int); method public void goForward(); - method public static void initSafeBrowsing(android.content.Context, android.webkit.ValueCallback<java.lang.Boolean>); method public void invokeZoomPicker(); method public boolean isPrivateBrowsingEnabled(); method public void loadData(java.lang.String, java.lang.String, java.lang.String); @@ -49706,7 +49767,7 @@ package android.webkit { method public void setWebViewClient(android.webkit.WebViewClient); method public deprecated boolean shouldDelayChildPressedState(); method public deprecated boolean showFindDialog(java.lang.String, boolean); - method public static void shutdownSafeBrowsing(); + method public static void startSafeBrowsing(android.content.Context, android.webkit.ValueCallback<java.lang.Boolean>); method public void stopLoading(); method public void zoomBy(float); method public boolean zoomIn(); diff --git a/api/test-removed.txt b/api/test-removed.txt index 6c37a8fbf133..fbd09f77dcde 100644 --- a/api/test-removed.txt +++ b/api/test-removed.txt @@ -227,13 +227,6 @@ package android.net { field public static final int BADGING_SD = 10; // 0xa } - public abstract class PskKeyManager { - ctor public PskKeyManager(); - field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80 - field public static final int MAX_IDENTITY_LENGTH_BYTES = 128; // 0x80 - field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100 - } - public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory { method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache); } diff --git a/cmds/bootanimation/iot/BootAction.cpp b/cmds/bootanimation/iot/BootAction.cpp index 8fda87e99099..889eb2fbabce 100644 --- a/cmds/bootanimation/iot/BootAction.cpp +++ b/cmds/bootanimation/iot/BootAction.cpp @@ -37,7 +37,7 @@ BootAction::~BootAction() { } } -bool BootAction::init(const std::string& libraryPath, const std::string& config) { +bool BootAction::init(const std::string& libraryPath) { APeripheralManagerClient* client = nullptr; ALOGD("Connecting to peripheralmanager"); // Wait for peripheral manager to come up. @@ -51,16 +51,11 @@ bool BootAction::init(const std::string& libraryPath, const std::string& config) ALOGD("Peripheralmanager is up."); APeripheralManagerClient_delete(client); - std::string path_to_lib = libraryPath; - if (!parseConfig(config, &path_to_lib)) { - return false; - } - - ALOGI("Loading boot action %s", path_to_lib.c_str()); - mLibHandle = dlopen(path_to_lib.c_str(), RTLD_NOW); + ALOGI("Loading boot action %s", libraryPath.c_str()); + mLibHandle = dlopen(libraryPath.c_str(), RTLD_NOW); if (mLibHandle == nullptr) { ALOGE("Unable to load library at %s :: %s", - path_to_lib.c_str(), dlerror()); + libraryPath.c_str(), dlerror()); return false; } @@ -115,61 +110,4 @@ bool BootAction::loadSymbol(const char* symbol, void** loaded) { return true; } - -bool BootAction::parseConfig(const std::string& config, std::string* path) { - auto lines = Split(config, "\n"); - - if (lines.size() < 1) { - ALOGE("Config format invalid, expected one line, found %d", - lines.size()); - return false; - } - - size_t lineNumber = 0; - auto& line1 = lines.at(lineNumber); - while (StartsWith(line1, "#")) { - if (lines.size() < ++lineNumber) { - ALOGE("Config file contains no non-comment lines."); - return false; - } - line1 = lines.at(lineNumber); - } - - const std::string libraryNameToken("LIBRARY_NAME="); - if (!StartsWith(line1, libraryNameToken.c_str())) { - ALOGE("Invalid config format, expected second line to start with %s " - "Instead found: %s", libraryNameToken.c_str(), line1.c_str()); - return false; - } - - std::string libraryName = line1.substr(libraryNameToken.length()); - - *path += "/"; - *path += architectureDirectory(); - *path += "/"; - *path += libraryName; - - return true; -} - -const char* BootAction::architectureDirectory() { - switch(android_getCpuFamily()) { - case ANDROID_CPU_FAMILY_ARM: - return "arm"; - case ANDROID_CPU_FAMILY_X86: - return "x86"; - case ANDROID_CPU_FAMILY_MIPS: - return "mips"; - case ANDROID_CPU_FAMILY_ARM64: - return "arm64"; - case ANDROID_CPU_FAMILY_X86_64: - return "x86_64"; - case ANDROID_CPU_FAMILY_MIPS64: - return "mips64"; - default: - ALOGE("Unsupported cpu family: %d", android_getCpuFamily()); - return ""; - } -} - } // namespace android diff --git a/cmds/bootanimation/iot/BootAction.h b/cmds/bootanimation/iot/BootAction.h index 31d0d1f65b95..495aa4f2180c 100644 --- a/cmds/bootanimation/iot/BootAction.h +++ b/cmds/bootanimation/iot/BootAction.h @@ -26,11 +26,9 @@ namespace android { class BootAction : public RefBase { public: ~BootAction(); - // Parse the contents of the config file. We expect one line: - // LIBRARY_NAME= - // - // LIBRARY_NAME is the name of the shared library that contains the boot action. - bool init(const std::string& libraryPath, const std::string& config); + + // libraryPath is a fully qualified path to the target .so library. + bool init(const std::string& libraryPath); // The animation is going to start playing partNumber for the playCount'th // time, update the action as needed. @@ -47,9 +45,7 @@ private: typedef void (*libStartPart)(int partNumber, int playNumber); typedef void (*libShutdown)(); - bool parseConfig(const std::string& config, std::string* path); bool loadSymbol(const char* symbol, void** loaded); - const char* architectureDirectory(); void* mLibHandle = nullptr; libInit mLibInit = nullptr; diff --git a/cmds/bootanimation/iot/iotbootanimation_main.cpp b/cmds/bootanimation/iot/iotbootanimation_main.cpp index d1ae786e83af..d62478b27638 100644 --- a/cmds/bootanimation/iot/iotbootanimation_main.cpp +++ b/cmds/bootanimation/iot/iotbootanimation_main.cpp @@ -39,17 +39,21 @@ namespace { class BootActionAnimationCallbacks : public android::BootAnimation::Callbacks {public: void init(const Vector<Animation::Part>&) override { - // Create and initialize BootActions if we have a boot_action.conf. - std::string bootActionConf; - if (ReadFileToString("/oem/app/etc/boot_action.conf", &bootActionConf)) { - mBootAction = new BootAction(); - if (!mBootAction->init("/oem/app/lib", bootActionConf)) { - mBootAction = NULL; - } - } else { - ALOGI("No boot actions specified"); + std::string library_path("/oem/lib/"); + + // This value is optionally provided by the user and will be written to + // /oem/oem.prop. + char property[PROP_VALUE_MAX] = {0}; + if (property_get("ro.oem.bootactions.lib", property, "") < 1) { + ALOGI("No bootaction specified"); + return; } + library_path += property; + mBootAction = new BootAction(); + if (!mBootAction->init(library_path)) { + mBootAction = NULL; + } }; void playPart(int partNumber, const Animation::Part&, int playNumber) override { diff --git a/cmds/incident/Android.mk b/cmds/incident/Android.mk index e1c9b93a8e6d..8615f9b63e43 100644 --- a/cmds/incident/Android.mk +++ b/cmds/incident/Android.mk @@ -37,7 +37,7 @@ gen_src_dir := $(local-generated-sources-dir) gen := $(gen_src_dir)/incident_sections.cpp $(gen): $(HOST_OUT_EXECUTABLES)/incident-section-gen $(gen): PRIVATE_CUSTOM_TOOL = \ - $(HOST_OUT_EXECUTABLES)/incident-section-gen > $@ + $(HOST_OUT_EXECUTABLES)/incident-section-gen incident > $@ $(gen): $(HOST_OUT_EXECUTABLES)/incident-section-gen $(transform-generated-source) LOCAL_GENERATED_SOURCES += $(gen) diff --git a/cmds/incident_helper/IncidentHelper.cpp b/cmds/incident_helper/IncidentHelper.cpp index 664c48f75f9f..fba5e662b7c1 100644 --- a/cmds/incident_helper/IncidentHelper.cpp +++ b/cmds/incident_helper/IncidentHelper.cpp @@ -29,8 +29,37 @@ using namespace android::base; using namespace android::os; +using namespace google::protobuf; using namespace std; +static bool +SetTableField(::google::protobuf::Message* message, string field_name, string field_value) { + const Descriptor* descriptor = message->GetDescriptor(); + const Reflection* reflection = message->GetReflection(); + + const FieldDescriptor* field = descriptor->FindFieldByName(field_name); + switch (field->type()) { + case FieldDescriptor::TYPE_STRING: + reflection->SetString(message, field, field_value); + return true; + case FieldDescriptor::TYPE_INT64: + reflection->SetInt64(message, field, atol(field_value.c_str())); + return true; + case FieldDescriptor::TYPE_UINT64: + reflection->SetUInt64(message, field, atol(field_value.c_str())); + return true; + case FieldDescriptor::TYPE_INT32: + reflection->SetInt32(message, field, atoi(field_value.c_str())); + return true; + case FieldDescriptor::TYPE_UINT32: + reflection->SetUInt32(message, field, atoi(field_value.c_str())); + return true; + default: + // Add new scalar types + return false; + } +} + // ================================================================================ status_t ReverseParser::Parse(const int in, const int out) const { @@ -51,31 +80,6 @@ status_t ReverseParser::Parse(const int in, const int out) const // ================================================================================ static const string KERNEL_WAKEUP_LINE_DELIMITER = "\t"; -static void SetWakeupSourceField(WakeupSourceProto* source, string name, string value) { - if (name == "name") { - source->set_name(value.c_str()); - } else if (name == "active_count") { - source->set_active_count(atoi(value.c_str())); - } else if (name == "event_count") { - source->set_event_count(atoi(value.c_str())); - } else if (name == "wakeup_count") { - source->set_wakeup_count(atoi(value.c_str())); - } else if (name == "expire_count") { - source->set_expire_count(atoi(value.c_str())); - } else if (name == "active_count") { - source->set_active_since(atol(value.c_str())); - } else if (name == "total_time") { - source->set_total_time(atol(value.c_str())); - } else if (name == "max_time") { - source->set_max_time(atol(value.c_str())); - } else if (name == "last_change") { - source->set_last_change(atol(value.c_str())); - } else if (name == "prevent_suspend_time") { - source->set_prevent_suspend_time(atol(value.c_str())); - } - // add new fields -} - status_t KernelWakesParser::Parse(const int in, const int out) const { Reader reader(in); string line; @@ -90,12 +94,12 @@ status_t KernelWakesParser::Parse(const int in, const int out) const { if (line.empty()) continue; // parse head line if (nline++ == 0) { - split(line, header, KERNEL_WAKEUP_LINE_DELIMITER); + header = parseHeader(line, KERNEL_WAKEUP_LINE_DELIMITER); continue; } // parse for each record, the line delimiter is \t only! - split(line, record, KERNEL_WAKEUP_LINE_DELIMITER); + record = parseRecord(line, KERNEL_WAKEUP_LINE_DELIMITER); if (record.size() != header.size()) { // TODO: log this to incident report! @@ -105,7 +109,10 @@ status_t KernelWakesParser::Parse(const int in, const int out) const { WakeupSourceProto* source = proto.add_wakeup_sources(); for (int i=0; i<(int)record.size(); i++) { - SetWakeupSourceField(source, header[i], record[i]); + if (!SetTableField(source, header[i], record[i])) { + fprintf(stderr, "[%s]Line %d has bad value %s of %s\n", + this->name.string(), nline, header[i].c_str(), record[i].c_str()); + } } } @@ -123,32 +130,6 @@ status_t KernelWakesParser::Parse(const int in, const int out) const { } // ================================================================================ -// Remove K for numeric fields -static void SetProcessField(ProcessProto* process, string name, string value) { - ssize_t len = value.size(); - if (name == "PID") { - process->set_pid(atoi(value.c_str())); - } else if (name == "Vss") { - process->set_vss(atol(value.substr(0, len - 1).c_str())); - } else if (name == "Rss") { - process->set_rss(atol(value.substr(0, len - 1).c_str())); - } else if (name == "Pss") { - process->set_pss(atol(value.substr(0, len - 1).c_str())); - } else if (name == "Uss") { - process->set_uss(atol(value.substr(0, len - 1).c_str())); - } else if (name == "Swap") { - process->set_swap(atol(value.substr(0, len - 1).c_str())); - } else if (name == "PSwap") { - process->set_pswap(atol(value.substr(0, len - 1).c_str())); - } else if (name == "USwap") { - process->set_uswap(atol(value.substr(0, len - 1).c_str())); - } else if (name == "ZSwap") { - process->set_zswap(atol(value.substr(0, len - 1).c_str())); - } else if (name == "cmdline") { - process->set_cmdline(value); - } -} - status_t ProcrankParser::Parse(const int in, const int out) const { Reader reader(in); string line, content; @@ -164,22 +145,22 @@ status_t ProcrankParser::Parse(const int in, const int out) const { // parse head line if (nline++ == 0) { - split(line, header); + header = parseHeader(line); continue; } - split(line, record); + record = parseRecord(line); if (record.size() != header.size()) { if (record[record.size() - 1] == "TOTAL") { // TOTAL record ProcessProto* total = proto.mutable_summary()->mutable_total(); for (int i=1; i<=(int)record.size(); i++) { - SetProcessField(total, header[header.size() - i], record[record.size() - i]); + SetTableField(total, header[header.size() - i], record[record.size() - i]); } } else if (record[0] == "ZRAM:") { - split(line, record, ":"); + record = parseRecord(line, ":"); proto.mutable_summary()->mutable_zram()->set_raw_text(record[1]); } else if (record[0] == "RAM:") { - split(line, record, ":"); + record = parseRecord(line, ":"); proto.mutable_summary()->mutable_ram()->set_raw_text(record[1]); } else { fprintf(stderr, "[%s]Line %d has missing fields\n%s\n", this->name.string(), nline, @@ -190,7 +171,10 @@ status_t ProcrankParser::Parse(const int in, const int out) const { ProcessProto* process = proto.add_processes(); for (int i=0; i<(int)record.size(); i++) { - SetProcessField(process, header[i], record[i]); + if (!SetTableField(process, header[i], record[i])) { + fprintf(stderr, "[%s]Line %d has bad value %s of %s\n", + this->name.string(), nline, header[i].c_str(), record[i].c_str()); + } } } diff --git a/cmds/incident_helper/ih_util.cpp b/cmds/incident_helper/ih_util.cpp index bbb625f28c48..b2fda23ac391 100644 --- a/cmds/incident_helper/ih_util.cpp +++ b/cmds/incident_helper/ih_util.cpp @@ -23,16 +23,24 @@ const ssize_t BUFFER_SIZE = 16 * 1024; // 4KB -std::string trim(const std::string& s, const std::string& whitespace) { - const auto head = s.find_first_not_of(whitespace); + +static std::string trim(const std::string& s) { + const auto head = s.find_first_not_of(DEFAULT_WHITESPACE); if (head == std::string::npos) return ""; - const auto tail = s.find_last_not_of(whitespace); + const auto tail = s.find_last_not_of(DEFAULT_WHITESPACE); return s.substr(head, tail - head + 1); } +static std::string trimHeader(const std::string& s) { + std::string res = trim(s); + std::transform(res.begin(), res.end(), res.begin(), ::tolower); + return res; +} + // This is similiar to Split in android-base/file.h, but it won't add empty string -void split(const std::string& line, std::vector<std::string>& words, const std::string& delimiters) { +static void split(const std::string& line, std::vector<std::string>& words, + const trans_func& func, const std::string& delimiters) { words.clear(); // clear the buffer before split size_t base = 0; @@ -40,7 +48,7 @@ void split(const std::string& line, std::vector<std::string>& words, const std:: while (true) { found = line.find_first_of(delimiters, base); if (found != base) { - std::string word = trim(line.substr(base, found - base)); + std::string word = (*func) (line.substr(base, found - base)); if (!word.empty()) { words.push_back(word); } @@ -50,13 +58,18 @@ void split(const std::string& line, std::vector<std::string>& words, const std:: } } -bool assertHeaders(const char* expected[], const std::vector<std::string>& actual) { - for (size_t i = 0; i < actual.size(); i++) { - if (expected[i] == NULL || std::string(expected[i]) != actual[i]) { - return false; - } - } - return true; +header_t parseHeader(const std::string& line, const std::string& delimiters) { + header_t header; + trans_func f = &trimHeader; + split(line, header, f, delimiters); + return header; +} + +record_t parseRecord(const std::string& line, const std::string& delimiters) { + record_t record; + trans_func f = &trim; + split(line, record, f, delimiters); + return record; } Reader::Reader(const int fd) : Reader(fd, BUFFER_SIZE) {}; diff --git a/cmds/incident_helper/ih_util.h b/cmds/incident_helper/ih_util.h index 9e0c18ee7498..5598eed8d824 100644 --- a/cmds/incident_helper/ih_util.h +++ b/cmds/incident_helper/ih_util.h @@ -23,16 +23,13 @@ typedef std::vector<std::string> header_t; typedef std::vector<std::string> record_t; +typedef std::string (*trans_func) (const std::string&); const char DEFAULT_NEWLINE = '\n'; const std::string DEFAULT_WHITESPACE = " \t"; -std::string trim(const std::string& s, const std::string& whitespace = DEFAULT_WHITESPACE); - -void split(const std::string& line, std::vector<std::string>& words, - const std::string& delimiters = DEFAULT_WHITESPACE); - -bool assertHeaders(const char* expected[], const std::vector<std::string>& actual); +header_t parseHeader(const std::string& line, const std::string& delimiters = DEFAULT_WHITESPACE); +record_t parseRecord(const std::string& line, const std::string& delimiters = DEFAULT_WHITESPACE); /** * Reader class reads data from given fd in streaming fashion. diff --git a/cmds/incident_helper/tests/IncidentHelper_test.cpp b/cmds/incident_helper/tests/IncidentHelper_test.cpp index 04109c9a3ecd..04dd8de11a15 100644 --- a/cmds/incident_helper/tests/IncidentHelper_test.cpp +++ b/cmds/incident_helper/tests/IncidentHelper_test.cpp @@ -97,7 +97,7 @@ TEST_F(IncidentHelperTest, KernelWakesParser) { record2->set_last_change(2067286206l); record2->set_prevent_suspend_time(0l); - int fd = open(testFile.c_str(), O_RDONLY, 0444); + int fd = open(testFile.c_str(), O_RDONLY); ASSERT_TRUE(fd != -1); CaptureStdout(); @@ -149,7 +149,7 @@ TEST_F(IncidentHelperTest, ProcrankParser) { expected.mutable_summary()->mutable_ram() ->set_raw_text("3843972K total, 281424K free, 116764K buffers, 1777452K cached, 1136K shmem, 217916K slab"); - int fd = open(testFile.c_str(), O_RDONLY, 0444); + int fd = open(testFile.c_str(), O_RDONLY); ASSERT_TRUE(fd != -1); CaptureStdout(); @@ -187,11 +187,11 @@ TEST_F(IncidentHelperTest, ProcrankParserShortHeader) { expected.mutable_summary()->mutable_ram() ->set_raw_text("3843972K total, 281424K free, 116764K buffers, 1777452K cached, 1136K shmem, 217916K slab"); - int fd = open(testFile.c_str(), O_RDONLY, 0444); + int fd = open(testFile.c_str(), O_RDONLY); ASSERT_TRUE(fd != -1); CaptureStdout(); ASSERT_EQ(NO_ERROR, parser.Parse(fd, STDOUT_FILENO)); EXPECT_EQ(GetCapturedStdout(), getSerializedString(expected)); close(fd); -}
\ No newline at end of file +} diff --git a/cmds/incident_helper/tests/ih_util_test.cpp b/cmds/incident_helper/tests/ih_util_test.cpp index 5158e0a285bc..3b9ed403b77a 100644 --- a/cmds/incident_helper/tests/ih_util_test.cpp +++ b/cmds/incident_helper/tests/ih_util_test.cpp @@ -26,25 +26,38 @@ using namespace android::base; using namespace std; using ::testing::StrEq; -TEST(IhUtilTest, Trim) { - EXPECT_THAT(trim(" \t 100 00\toooh \t wqrw "), StrEq("100 00\toooh \t wqrw")); - EXPECT_THAT(trim(" \t 100 00\toooh \t wqrw ", " "), StrEq("\t 100 00\toooh \t wqrw")); +TEST(IhUtilTest, ParseHeader) { + header_t result, expected; + result = parseHeader(" \t \t\t "); + EXPECT_EQ(expected, result); + + result = parseHeader(" \t 100 00\tOpQ \t wqrw"); + expected = { "100", "00", "opq", "wqrw" }; + EXPECT_EQ(expected, result); + + result = parseHeader(" \t 100 00\toooh \t wTF", "\t"); + expected = { "100 00", "oooh", "wtf" }; + EXPECT_EQ(expected, result); + + result = parseHeader("123,456,78_9", ","); + expected = { "123", "456", "78_9" }; + EXPECT_EQ(expected, result); } -TEST(IhUtilTest, Split) { - vector<string> result, expected; - split(" \t \t\t ", result); +TEST(IhUtilTest, ParseRecord) { + record_t result, expected; + result = parseRecord(" \t \t\t "); EXPECT_EQ(expected, result); - split(" \t 100 00\toooh \t wqrw", result); + result = parseRecord(" \t 100 00\toooh \t wqrw"); expected = { "100", "00", "oooh", "wqrw" }; EXPECT_EQ(expected, result); - split(" \t 100 00\toooh \t wqrw", result, "\t"); + result = parseRecord(" \t 100 00\toooh \t wqrw", "\t"); expected = { "100 00", "oooh", "wqrw" }; EXPECT_EQ(expected, result); - split("123,456,78_9", result, ","); + result = parseRecord("123,456,78_9", ","); expected = { "123", "456", "78_9" }; EXPECT_EQ(expected, result); } diff --git a/cmds/incidentd/Android.mk b/cmds/incidentd/Android.mk index 537c91093112..835a7b94507b 100644 --- a/cmds/incidentd/Android.mk +++ b/cmds/incidentd/Android.mk @@ -29,8 +29,7 @@ LOCAL_SRC_FILES := \ src/Section.cpp \ src/main.cpp \ src/protobuf.cpp \ - src/report_directory.cpp \ - src/section_list.cpp \ + src/report_directory.cpp LOCAL_CFLAGS += \ -Wall -Werror -Wno-missing-field-initializers -Wno-unused-variable -Wunused-parameter @@ -44,6 +43,8 @@ else -Os endif +LOCAL_C_INCLUDES += $(LOCAL_PATH)/src + LOCAL_SHARED_LIBRARIES := \ libbase \ libbinder \ @@ -54,9 +55,21 @@ LOCAL_SHARED_LIBRARIES := \ libservices \ libutils -ifeq (BUILD_WITH_INCIDENTD_RC,true) +LOCAL_MODULE_CLASS := EXECUTABLES +gen_src_dir := $(local-generated-sources-dir) + +GEN := $(gen_src_dir)/src/section_list.cpp +$(GEN): $(HOST_OUT_EXECUTABLES)/incident-section-gen +$(GEN): PRIVATE_CUSTOM_TOOL = \ + $(HOST_OUT_EXECUTABLES)/incident-section-gen incidentd > $@ +$(GEN): $(HOST_OUT_EXECUTABLES)/incident-section-gen + $(transform-generated-source) +LOCAL_GENERATED_SOURCES += $(GEN) + +gen_src_dir:= +GEN:= + LOCAL_INIT_RC := incidentd.rc -endif include $(BUILD_EXECUTABLE) @@ -80,7 +93,7 @@ LOCAL_SRC_FILES := \ src/Section.cpp \ src/protobuf.cpp \ src/report_directory.cpp \ - src/section_list.cpp \ + tests/section_list.cpp \ tests/FdBuffer_test.cpp \ tests/Reporter_test.cpp \ tests/Section_test.cpp \ diff --git a/cmds/incidentd/src/FdBuffer.cpp b/cmds/incidentd/src/FdBuffer.cpp index 7743301553a0..4d6a36cdba2e 100644 --- a/cmds/incidentd/src/FdBuffer.cpp +++ b/cmds/incidentd/src/FdBuffer.cpp @@ -174,7 +174,7 @@ FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeou if (rpos >= wpos) { amt = ::read(fd, cirBuf + rpos, BUFFER_SIZE - rpos); } else { - amt = :: read(fd, cirBuf + rpos, wpos - rpos); + amt = ::read(fd, cirBuf + rpos, wpos - rpos); } if (amt < 0) { if (!(errno == EAGAIN || errno == EWOULDBLOCK)) { @@ -241,6 +241,7 @@ FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeou size_t FdBuffer::size() { + if (mBuffers.empty()) return 0; return ((mBuffers.size() - 1) * BUFFER_SIZE) + mCurrentWritten; } @@ -255,4 +256,30 @@ FdBuffer::write(ReportRequestSet* reporter) return NO_ERROR; } +FdBuffer::iterator +FdBuffer::end() +{ + if (mBuffers.empty() || mCurrentWritten < 0) return begin(); + if (mCurrentWritten == BUFFER_SIZE) + // FdBuffer doesn't allocate another buf since no more bytes to read. + return FdBuffer::iterator(*this, mBuffers.size(), 0); + return FdBuffer::iterator(*this, mBuffers.size() - 1, mCurrentWritten); +} +FdBuffer::iterator& +FdBuffer::iterator::operator+(size_t offset) +{ + size_t newOffset = mOffset + offset; + while (newOffset >= BUFFER_SIZE) { + mIndex++; + newOffset -= BUFFER_SIZE; + } + mOffset = newOffset; + return *this; +} + +size_t +FdBuffer::iterator::bytesRead() +{ + return mIndex * BUFFER_SIZE + mOffset; +} diff --git a/cmds/incidentd/src/FdBuffer.h b/cmds/incidentd/src/FdBuffer.h index 03a6d1865036..e9a53ffe513a 100644 --- a/cmds/incidentd/src/FdBuffer.h +++ b/cmds/incidentd/src/FdBuffer.h @@ -21,7 +21,6 @@ #include <utils/Errors.h> -#include <set> #include <vector> using namespace android; @@ -74,7 +73,8 @@ public: size_t size(); /** - * Write the data that we recorded to the fd given. + * [Deprecated] Write the data that we recorded to the fd given. + * TODO: remove it once the iterator api is working */ status_t write(ReportRequestSet* requests); @@ -83,6 +83,37 @@ public: */ int64_t durationMs() { return mFinishTime - mStartTime; } + /** + * Read data stored in FdBuffer + */ + class iterator; + friend class iterator; + class iterator : public std::iterator<std::random_access_iterator_tag, uint8_t> { + private: + FdBuffer& mFdBuffer; + size_t mIndex; + size_t mOffset; + public: + explicit iterator(FdBuffer& buffer, ssize_t index, ssize_t offset) + : mFdBuffer(buffer), mIndex(index), mOffset(offset) {} + iterator& operator=(iterator& other) { return other; } + iterator& operator+(size_t offset); // this is implemented in .cpp + iterator& operator+=(size_t offset) { return *this + offset; } + iterator& operator++() { return *this + 1; } + iterator operator++(int) { return *this + 1; } + bool operator==(iterator other) const { + return mIndex == other.mIndex && mOffset == other.mOffset; + } + bool operator!=(iterator other) const { return !(*this == other); } + reference operator*() const { return mFdBuffer.mBuffers[mIndex][mOffset]; } + + // random access could make the iterator out of bound + size_t bytesRead(); + bool outOfBound() { return bytesRead() > mFdBuffer.size(); }; + }; + iterator begin() { return iterator(*this, 0, 0); } + iterator end(); + private: vector<uint8_t*> mBuffers; int64_t mStartTime; diff --git a/cmds/incidentd/src/Reporter.cpp b/cmds/incidentd/src/Reporter.cpp index ea73bcdebb95..4ffc11984224 100644 --- a/cmds/incidentd/src/Reporter.cpp +++ b/cmds/incidentd/src/Reporter.cpp @@ -225,9 +225,8 @@ Reporter::runReport() // and report to those that care that we're doing it. for (const Section** section=SECTION_LIST; *section; section++) { const int id = (*section)->id; - ALOGD("Taking incident report section %d '%s'", id, (*section)->name.string()); - if (this->batch.containsSection(id)) { + ALOGD("Taking incident report section %d '%s'", id, (*section)->name.string()); // Notify listener of starting for (ReportRequestSet::iterator it=batch.begin(); it!=batch.end(); it++) { if ((*it)->listener != NULL && (*it)->args.containsSection(id)) { @@ -251,6 +250,7 @@ Reporter::runReport() IIncidentReportStatusListener::STATUS_FINISHED); } } + ALOGD("Finish incident report section %d '%s'", id, (*section)->name.string()); } } @@ -324,6 +324,7 @@ Reporter::upload_backlog() struct stat st; status_t err; + ALOGD("Start uploading backlogs in %s", INCIDENT_DIRECTORY); if ((err = create_directory(INCIDENT_DIRECTORY)) != NO_ERROR) { ALOGE("directory doesn't exist: %s", strerror(-err)); return REPORT_FINISHED; @@ -337,6 +338,7 @@ Reporter::upload_backlog() sp<DropBoxManager> dropbox = new DropBoxManager(); // Enumerate, count and add up size + int count = 0; while ((entry = readdir(dir)) != NULL) { if (entry->d_name[0] == '.') { continue; @@ -360,8 +362,9 @@ Reporter::upload_backlog() // boot or the next checkin. If the directory gets too big older files will // be rotated out. unlink(filename.string()); + count++; } - + ALOGD("Successfully uploaded %d files to Dropbox.", count); closedir(dir); return REPORT_FINISHED; diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp index 9cc47ed4899a..ac87fe3b1e40 100644 --- a/cmds/incidentd/src/Section.cpp +++ b/cmds/incidentd/src/Section.cpp @@ -22,9 +22,6 @@ #include <private/android_filesystem_config.h> #include <binder/IServiceManager.h> #include <mutex> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> #include <wait.h> #include <unistd.h> @@ -37,7 +34,7 @@ const char* INCIDENT_HELPER = "/system/bin/incident_helper"; static pid_t forkAndExecuteIncidentHelper(const int id, const char* name, Fpipe& p2cPipe, Fpipe& c2pPipe) { - const char* ihArgs[] { INCIDENT_HELPER, "-s", to_string(id).c_str(), NULL }; + const char* ihArgs[] { INCIDENT_HELPER, "-s", String8::format("%d", id).string(), NULL }; // fork used in multithreaded environment, avoid adding unnecessary code in child process pid_t pid = fork(); @@ -330,11 +327,13 @@ WorkerThreadSection::Execute(ReportRequestSet* requests) const void CommandSection::init(const char* command, va_list args) { va_list copied_args; - va_copy(copied_args, args); int numOfArgs = 0; - while(va_arg(args, const char*) != NULL) { + + va_copy(copied_args, args); + while(va_arg(copied_args, const char*) != NULL) { numOfArgs++; } + va_end(copied_args); // allocate extra 1 for command and 1 for NULL terminator mCommand = (const char**)malloc(sizeof(const char*) * (numOfArgs + 2)); @@ -342,13 +341,12 @@ void CommandSection::init(const char* command, va_list args) mCommand[0] = command; name = command; for (int i=0; i<numOfArgs; i++) { - const char* arg = va_arg(copied_args, const char*); + const char* arg = va_arg(args, const char*); mCommand[i+1] = arg; name += " "; name += arg; } mCommand[numOfArgs+1] = NULL; - va_end(copied_args); } CommandSection::CommandSection(int id, const int64_t timeoutMs, const char* command, ...) diff --git a/cmds/incidentd/src/protobuf.cpp b/cmds/incidentd/src/protobuf.cpp index a703ef91e2e8..b865339a9b98 100644 --- a/cmds/incidentd/src/protobuf.cpp +++ b/cmds/incidentd/src/protobuf.cpp @@ -16,6 +16,7 @@ #include "protobuf.h" + uint8_t* write_raw_varint(uint8_t* buf, uint32_t val) { diff --git a/cmds/incidentd/src/section_list.h b/cmds/incidentd/src/section_list.h index c97751937d6d..1abdb5284001 100644 --- a/cmds/incidentd/src/section_list.h +++ b/cmds/incidentd/src/section_list.h @@ -21,8 +21,46 @@ /** * This is the mapping of section IDs to the commands that are run to get those commands. + * The section IDs are guaranteed in ascending order */ extern const Section* SECTION_LIST[]; +/* + * In order not to use libprotobuf-cpp-full nor libplatformprotos in incidentd + * privacy options's data structure are explicityly redefined in this file. + */ + +// DESTINATION enum +extern const uint8_t DEST_LOCAL; +extern const uint8_t DEST_EXPLICIT; +extern const uint8_t DEST_AUTOMATIC; + +// This is the default value of DEST enum +// field with this value doesn't generate Privacy to save too much generated code +extern const uint8_t DEST_DEFAULT_VALUE; + +// type of the field, identitical to protobuf definition +extern const uint8_t TYPE_STRING; +extern const uint8_t TYPE_MESSAGE; + +struct Privacy { + int field_id; + uint8_t type; + + // the following two fields are identitical to + // frameworks/base/libs/incident/proto/android/privacy.proto + uint8_t dest; + const char** patterns; + + // ignore parent's privacy flags if children are set, NULL-terminated + const Privacy** children; +}; + +/** + * This is the mapping of section IDs to each section's privacy policy. + * The section IDs are guaranteed in ascending order + */ +extern const Privacy* PRIVACY_POLICY_LIST[]; + #endif // SECTION_LIST_H diff --git a/cmds/incidentd/tests/FdBuffer_test.cpp b/cmds/incidentd/tests/FdBuffer_test.cpp index ba8b77a8bfac..403a2abf670a 100644 --- a/cmds/incidentd/tests/FdBuffer_test.cpp +++ b/cmds/incidentd/tests/FdBuffer_test.cpp @@ -92,6 +92,30 @@ TEST_F(FdBufferTest, ReadAndWrite) { AssertBufferContent(testdata.c_str()); } +TEST_F(FdBufferTest, IterateEmpty) { + FdBuffer::iterator it = buffer.begin(); + EXPECT_EQ(it, buffer.end()); + it += 1; + EXPECT_TRUE(it.outOfBound()); +} + +TEST_F(FdBufferTest, ReadAndIterate) { + std::string testdata = "FdBuffer test string"; + ASSERT_TRUE(WriteStringToFile(testdata, tf.path, false)); + ASSERT_EQ(NO_ERROR, buffer.read(tf.fd, READ_TIMEOUT)); + + int i=0; + for (FdBuffer::iterator it = buffer.begin(); it != buffer.end(); ++it) { + EXPECT_EQ(*it, (uint8_t)testdata[i++]); + } + + FdBuffer::iterator it = buffer.begin(); + it += buffer.size(); + EXPECT_EQ(it, buffer.end()); + EXPECT_EQ(it.bytesRead(), testdata.size()); + EXPECT_FALSE(it.outOfBound()); +} + TEST_F(FdBufferTest, ReadTimeout) { int pid = fork(); ASSERT_TRUE(pid != -1); @@ -202,6 +226,7 @@ TEST_F(FdBufferTest, ReadInStreamEmpty) { TEST_F(FdBufferTest, ReadInStreamMoreThan4MB) { const std::string testFile = kTestDataPath + "morethan4MB.txt"; + size_t fourMB = (size_t) 4 * 1024 * 1024; int fd = open(testFile.c_str(), O_RDONLY); ASSERT_NE(fd, -1); int pid = fork(); @@ -220,10 +245,18 @@ TEST_F(FdBufferTest, ReadInStreamMoreThan4MB) { ASSERT_EQ(NO_ERROR, buffer.readProcessedDataInStream(fd, p2cPipe.writeFd(), c2pPipe.readFd(), READ_TIMEOUT)); - EXPECT_EQ(buffer.size(), (size_t) (4 * 1024 * 1024)); + EXPECT_EQ(buffer.size(), fourMB); EXPECT_FALSE(buffer.timedOut()); EXPECT_TRUE(buffer.truncated()); wait(&pid); + FdBuffer::iterator it = buffer.begin(); + it += fourMB; + EXPECT_EQ(it.bytesRead(), fourMB); + EXPECT_EQ(it, buffer.end()); + for (FdBuffer::iterator it = buffer.begin(); it != buffer.end(); it++) { + char c = 'A' + (it.bytesRead() % 64 / 8); + ASSERT_TRUE(*it == c); + } } } diff --git a/cmds/incidentd/tests/section_list.cpp b/cmds/incidentd/tests/section_list.cpp new file mode 100644 index 000000000000..f0053355bd24 --- /dev/null +++ b/cmds/incidentd/tests/section_list.cpp @@ -0,0 +1,6 @@ +// This file is a dummy section_list.cpp used for test only. +#include "section_list.h" + +const Section* SECTION_LIST[] = { + NULL +}; diff --git a/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java b/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java index b9fedd365925..6a4a4beaa763 100644 --- a/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java +++ b/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java @@ -34,6 +34,8 @@ public final class LockSettingsCmd extends BaseCommand { " locksettings set-password [--old OLD_CREDENTIAL] NEW_PASSWORD\n" + " locksettings clear [--old OLD_CREDENTIAL]\n" + " locksettings verify [--old OLD_CREDENTIAL]\n" + + " locksettings set-disabled DISABLED\n" + + " locksettings get-disabled\n" + "\n" + "flags: \n" + " --user USER_ID: specify the user, default value is current user\n" + @@ -50,7 +52,11 @@ public final class LockSettingsCmd extends BaseCommand { "\n" + "locksettings clear: clears the unlock credential\n" + "\n" + - "locksettings verify: verifies the credential and unlocks the user\n"; + "locksettings verify: verifies the credential and unlocks the user\n" + + "\n" + + "locksettings set-disabled: sets whether the lock screen should be disabled\n" + + "\n" + + "locksettings get-disabled: retrieves whether the lock screen is disabled\n"; public static void main(String[] args) { (new LockSettingsCmd()).run(args); diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk new file mode 100644 index 000000000000..db8c89dafaba --- /dev/null +++ b/cmds/statsd/Android.mk @@ -0,0 +1,106 @@ +# Copyright (C) 2017 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH:= $(call my-dir) + +# ========= +# statsd +# ========= + +include $(CLEAR_VARS) + +LOCAL_MODULE := statsd + +LOCAL_SRC_FILES := \ + ../../core/java/android/os/IStatsManager.aidl \ + src/StatsService.cpp \ + src/LogEntryPrinter.cpp \ + src/LogReader.cpp \ + src/main.cpp + +LOCAL_CFLAGS += \ + -Wall \ + -Werror \ + -Wno-missing-field-initializers \ + -Wno-unused-variable \ + -Wno-unused-function \ + -Wno-unused-parameter + +ifeq (debug,) + LOCAL_CFLAGS += \ + -g -O0 +else + # optimize for size (protobuf glop can get big) + LOCAL_CFLAGS += \ + -Os +endif + +LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/../../core/java +LOCAL_C_INCLUDES += $(LOCAL_PATH)/src + +LOCAL_SHARED_LIBRARIES := \ + libbase \ + libbinder \ + libcutils \ + libincident \ + liblog \ + libselinux \ + libutils + +LOCAL_MODULE_CLASS := EXECUTABLES + +#LOCAL_INIT_RC := statsd.rc + +include $(BUILD_EXECUTABLE) + +# ============== +# statsd_test +# ============== + +include $(CLEAR_VARS) + +LOCAL_MODULE := statsd_test +LOCAL_COMPATIBILITY_SUITE := device-tests +LOCAL_MODULE_TAGS := tests + +LOCAL_CFLAGS += \ + -Wall \ + -Werror \ + -Wno-missing-field-initializers \ + -Wno-unused-variable \ + -Wno-unused-function \ + -Wno-unused-parameter + +LOCAL_C_INCLUDES += $(LOCAL_PATH)/src + +LOCAL_SRC_FILES := \ + ../../core/java/android/os/IStatsManager.aidl \ + src/StatsService.cpp \ + src/LogEntryPrinter.cpp \ + src/LogReader.cpp \ + tests/LogReader_test.cpp \ + +LOCAL_STATIC_LIBRARIES := \ + libgmock \ + +LOCAL_SHARED_LIBRARIES := \ + libbase \ + libbinder \ + libcutils \ + liblog \ + libselinux \ + libutils + +include $(BUILD_NATIVE_TEST) + diff --git a/cmds/statsd/src/LogEntryPrinter.cpp b/cmds/statsd/src/LogEntryPrinter.cpp new file mode 100644 index 000000000000..ba07308086ca --- /dev/null +++ b/cmds/statsd/src/LogEntryPrinter.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <LogEntryPrinter.h> + +#include <log/event_tag_map.h> +#include <log/logprint.h> +#include <utils/Errors.h> + +using namespace android; + +LogEntryPrinter::LogEntryPrinter(int out) + :m_out(out) +{ + // Initialize the EventTagMap, which is how we know the names of the numeric event tags. + // If this fails, we can't print well, but something will print. + m_tags = android_openEventTagMap(NULL); + + // Printing format + m_format = android_log_format_new(); + android_log_setPrintFormat(m_format, FORMAT_THREADTIME); +} + +LogEntryPrinter::~LogEntryPrinter() +{ + if (m_tags != NULL) { + android_closeEventTagMap(m_tags); + } + android_log_format_free(m_format); +} + +void +LogEntryPrinter::OnLogEvent(const log_msg& msg) +{ + status_t err; + AndroidLogEntry entry; + char buf[1024]; + + err = android_log_processBinaryLogBuffer(&(const_cast<log_msg*>(&msg)->entry_v1), + &entry, m_tags, buf, sizeof(buf)); + if (err == NO_ERROR) { + android_log_printLogLine(m_format, m_out, &entry); + } else { + printf("log entry: %s\n", buf); + fflush(stdout); + } +} + diff --git a/cmds/statsd/src/LogEntryPrinter.h b/cmds/statsd/src/LogEntryPrinter.h new file mode 100644 index 000000000000..61ffddca0916 --- /dev/null +++ b/cmds/statsd/src/LogEntryPrinter.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LOG_ENTRY_PRINTER_H +#define LOG_ENTRY_PRINTER_H + +#include "LogReader.h" + +#include <log/logprint.h> + +#include <stdio.h> + +/** + * Decodes the log entry and prints it to the supplied file descriptor. + */ +class LogEntryPrinter : public LogListener +{ +public: + LogEntryPrinter(int out); + virtual ~LogEntryPrinter(); + + virtual void OnLogEvent(const log_msg& msg); + +private: + /** + * Where to write to. + */ + int m_out; + + /** + * Numeric to string tag name mapping. + */ + EventTagMap* m_tags; + + /** + * Pretty printing format. + */ + AndroidLogFormat* m_format; +}; + +#endif // LOG_ENTRY_PRINTER_H diff --git a/cmds/statsd/src/LogReader.cpp b/cmds/statsd/src/LogReader.cpp new file mode 100644 index 000000000000..e0ed6464f4dc --- /dev/null +++ b/cmds/statsd/src/LogReader.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "LogReader.h" + +#include <log/log_read.h> + +#include <utils/Errors.h> + +#include <time.h> +#include <unistd.h> + +using namespace android; +using namespace std; + +#define SNOOZE_INITIAL_MS 100 +#define SNOOZE_MAX_MS (10 * 60 * 1000) // Ten minutes + + +// ================================================================================ +LogListener::LogListener() +{ +} + +LogListener::~LogListener() +{ +} + + +// ================================================================================ +LogReader::LogReader() +{ +} + +LogReader::~LogReader() +{ +} + +void +LogReader::AddListener(const sp<LogListener>& listener) +{ + m_listeners.push_back(listener); +} + +void +LogReader::Run() +{ + int nextSnoozeMs = SNOOZE_INITIAL_MS; + + // In an ideal world, this outer loop will only ever run one iteration, but it + // exists to handle crashes in logd. The inner loop inside connect_and_read() + // reads from logd forever, but if that read fails, we fall out to the outer + // loop, do the backoff (resetting the backoff timeout if we successfully read + // something), and then try again. + while (true) { + // Connect and read + int lineCount = connect_and_read(); + + // Figure out how long to sleep. + if (lineCount > 0) { + // If we managed to read at least one line, reset the backoff + nextSnoozeMs = SNOOZE_INITIAL_MS; + } else { + // Otherwise, expontial backoff + nextSnoozeMs *= 1.5f; + if (nextSnoozeMs > 10 * 60 * 1000) { + // Don't wait for toooo long. + nextSnoozeMs = SNOOZE_MAX_MS; + } + } + + // Sleep + timespec ts; + timespec rem; + ts.tv_sec = nextSnoozeMs / 1000; + ts.tv_nsec = (nextSnoozeMs % 1000) * 1000000L; + while (nanosleep(&ts, &rem) == -1) { + if (errno == EINTR) { + ts = rem; + } + // other errors are basically impossible + } + } +} + +int +LogReader::connect_and_read() +{ + int lineCount = 0; + status_t err; + logger_list* loggers; + logger* eventLogger; + + // Prepare the logging context + loggers = android_logger_list_alloc(ANDROID_LOG_RDONLY, + /* don't stop after N lines */ 0, + /* no pid restriction */ 0); + + // Open the buffer(s) + eventLogger = android_logger_open(loggers, LOG_ID_EVENTS); + + // Read forever + if (eventLogger) { + while (true) { + log_msg msg; + + // Read a message + err = android_logger_list_read(loggers, &msg); + if (err < 0) { + fprintf(stderr, "logcat read failure: %s\n", strerror(err)); + break; + } + + // Record that we read one (used above to know how to snooze). + lineCount++; + + // Call the listeners + for (vector<sp<LogListener> >::iterator it = m_listeners.begin(); + it != m_listeners.end(); it++) { + (*it)->OnLogEvent(msg); + } + } + } + + // Free the logger list and close the individual loggers + android_logger_list_free(loggers); + + return lineCount; +} + diff --git a/cmds/statsd/src/LogReader.h b/cmds/statsd/src/LogReader.h new file mode 100644 index 000000000000..08a17a31aa18 --- /dev/null +++ b/cmds/statsd/src/LogReader.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LOGREADER_H +#define LOGREADER_H + +#include <log/log_read.h> + +#include <utils/RefBase.h> + +#include <vector> + +/** + * Callback for LogReader + */ +class LogListener : public virtual android::RefBase +{ +public: + LogListener(); + virtual ~LogListener(); + + // TODO: Rather than using log_msg, which doesn't have any real internal structure + // here, we should pull this out into our own LogEntry class. + virtual void OnLogEvent(const log_msg& msg) = 0; +}; + +/** + * Class to read logs from logd. + */ +class LogReader : public virtual android::RefBase +{ +public: + /** + * Construct the LogReader with a pointer back to the StatsService + */ + LogReader(); + + /** + * Destructor. + */ + virtual ~LogReader(); + + /** + * Add a LogListener class. + */ + void AddListener(const android::sp<LogListener>& listener); + + /** + * Run the main LogReader loop + */ + void Run(); + +private: + /** + * List of listeners to call back on when we do get an event. + */ + std::vector<android::sp<LogListener> > m_listeners; + + /** + * Connect to a single instance of logd, and read until there's a read error. + * Logd can crash, exit, be killed etc. + * + * Returns the number of lines that were read. + */ + int connect_and_read(); +}; + +#endif // LOGREADER_H diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp new file mode 100644 index 000000000000..13c6f67dd37d --- /dev/null +++ b/cmds/statsd/src/StatsService.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "statsd" + +#include "StatsService.h" + +#include <binder/IPCThreadState.h> +#include <binder/IServiceManager.h> +#include <cutils/log.h> +#include <private/android_filesystem_config.h> +#include <utils/Looper.h> + +#include <unistd.h> +#include <stdio.h> + +using namespace android; + +// ================================================================================ +StatsService::StatsService(const sp<Looper>& handlerLooper) +{ + ALOGD("stats service constructed"); +} + +StatsService::~StatsService() +{ +} + +status_t +StatsService::dump(int fd, const Vector<String16>& args) +{ + FILE* out = fdopen(fd, "w"); + if (out == NULL) { + return NO_MEMORY; // the fd is already open + } + + fprintf(out, "StatsService::dump:"); + ALOGD("StatsService::dump:"); + const int N = args.size(); + for (int i=0; i<N; i++) { + fprintf(out, " %s", String8(args[i]).string()); + ALOGD(" %s", String8(args[i]).string()); + } + fprintf(out, "\n"); + + fclose(out); + return NO_ERROR; +} + +Status +StatsService::systemRunning() +{ + if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { + return Status::fromExceptionCode(Status::EX_SECURITY, + "Only system uid can call systemRunning"); + } + + // When system_server is up and running, schedule the dropbox task to run. + ALOGD("StatsService::systemRunning"); + + return Status::ok(); +} + diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h new file mode 100644 index 000000000000..0f34882b4b60 --- /dev/null +++ b/cmds/statsd/src/StatsService.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STATS_SERVICE_H +#define STATS_SERVICE_H + +#include <android/os/BnStatsManager.h> +#include <utils/Looper.h> + +#include <deque> +#include <mutex> + +using namespace android; +using namespace android::base; +using namespace android::binder; +using namespace android::os; +using namespace std; + + +// ================================================================================ +class StatsService : public BnStatsManager { +public: + StatsService(const sp<Looper>& handlerLooper); + virtual ~StatsService(); + + virtual status_t dump(int fd, const Vector<String16>& args); + virtual Status systemRunning(); + +}; + +#endif // STATS_SERVICE_H diff --git a/cmds/statsd/src/main.cpp b/cmds/statsd/src/main.cpp new file mode 100644 index 000000000000..93405cb6bf95 --- /dev/null +++ b/cmds/statsd/src/main.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "statsd" + +#include "LogEntryPrinter.h" +#include "LogReader.h" +#include "StatsService.h" + +#include <binder/IInterface.h> +#include <binder/IPCThreadState.h> +#include <binder/IServiceManager.h> +#include <binder/ProcessState.h> +#include <binder/Status.h> +#include <cutils/log.h> +#include <utils/Looper.h> +#include <utils/StrongPointer.h> + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +using namespace android; + +// ================================================================================ +/** + * Thread function data. + */ +struct log_reader_thread_data { + sp<StatsService> service; +}; + +/** + * Thread func for where the log reader runs. + */ +static void* +log_reader_thread_func(void* cookie) +{ + log_reader_thread_data* data = static_cast<log_reader_thread_data*>(cookie); + + sp<LogReader> reader = new LogReader(); + + // Put the printer one first, so it will print before the real ones. + if (true) { + reader->AddListener(new LogEntryPrinter(STDOUT_FILENO)); + } + + // TODO: Construct and add real LogListners here. + + reader->Run(); + + ALOGW("statsd LogReader.Run() is not supposed to return."); + + delete data; + return NULL; +} + +/** + * Creates and starts the thread to own the LogReader. + */ +static status_t +start_log_reader_thread(const sp<StatsService>& service) +{ + status_t err; + pthread_attr_t attr; + pthread_t thread; + + // Thread data. + log_reader_thread_data* data = new log_reader_thread_data(); + data->service = service; + + // Create the thread + err = pthread_attr_init(&attr); + if (err != NO_ERROR) { + return err; + } + // TODO: Do we need to tweak thread priority? + err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + if (err != NO_ERROR) { + pthread_attr_destroy(&attr); + return err; + } + err = pthread_create(&thread, &attr, log_reader_thread_func, static_cast<void*>(data)); + if (err != NO_ERROR) { + pthread_attr_destroy(&attr); + return err; + } + pthread_attr_destroy(&attr); + + return NO_ERROR; +} + +// ================================================================================ +int +main(int /*argc*/, char** /*argv*/) +{ + status_t err; + + // Set up the looper + sp<Looper> looper(Looper::prepare(0 /* opts */)); + + // Set up the binder + sp<ProcessState> ps(ProcessState::self()); + ps->setThreadPoolMaxThreadCount(1); // everything is oneway, let it queue and save ram + ps->startThreadPool(); + ps->giveThreadPoolName(); + IPCThreadState::self()->disableBackgroundScheduling(true); + + // Create the service + sp<StatsService> service = new StatsService(looper); + if (defaultServiceManager()->addService(String16("stats"), service) != 0) { + ALOGE("Failed to add service"); + return -1; + } + + // Start the log reader thread + err = start_log_reader_thread(service); + if (err != NO_ERROR) { + return 1; + } + + // Loop forever -- the reports run on this thread in a handler, and the + // binder calls remain responsive in their pool of one thread. + while (true) { + looper->pollAll(-1 /* timeoutMillis */); + } + ALOGW("statsd escaped from its loop."); + + return 1; +} diff --git a/cmds/statsd/statsd.rc b/cmds/statsd/statsd.rc new file mode 100644 index 000000000000..faccd610e223 --- /dev/null +++ b/cmds/statsd/statsd.rc @@ -0,0 +1,16 @@ +# Copyright (C) 2017 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +service statsd /system/bin/statsd + class main diff --git a/cmds/statsd/tests/LogReader_test.cpp b/cmds/statsd/tests/LogReader_test.cpp new file mode 100644 index 000000000000..ca538b082f89 --- /dev/null +++ b/cmds/statsd/tests/LogReader_test.cpp @@ -0,0 +1,24 @@ +// Copyright (C) 2017 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#define LOG_TAG "statsd_test" + +#include <gtest/gtest.h> + +#include <stdio.h> + +TEST(LogReaderTest, TestNothingAtAll) { + printf("yay!"); +} + diff --git a/compiled-classes-phone b/config/compiled-classes-phone index d11f0baf067a..c8297286b784 100644 --- a/compiled-classes-phone +++ b/config/compiled-classes-phone @@ -26,7 +26,7 @@ # to your device.mk, e.g., # # PRODUCT_COPY_FILES += \ -# frameworks/base/compiled-classes-phone:system/etc/compiled-classes +# frameworks/base/config/compiled-classes-phone:system/etc/compiled-classes # android.R$styleable android.accessibilityservice.AccessibilityServiceInfo @@ -4183,7 +4183,7 @@ android.util.Base64 android.util.Base64$Coder android.util.Base64$Decoder android.util.Base64$Encoder -android.util.BootTimingsTraceLog +android.util.TimingsTraceLog android.util.ByteStringUtils android.util.ContainerHelpers android.util.DebugUtils diff --git a/config/copyright-header b/config/copyright-header new file mode 100644 index 000000000000..93071cd7e2ef --- /dev/null +++ b/config/copyright-header @@ -0,0 +1,15 @@ +# +# Copyright (C) 2017 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# diff --git a/dirty-image-objects b/config/dirty-image-objects index 9b4d199dc723..9b4d199dc723 100644 --- a/dirty-image-objects +++ b/config/dirty-image-objects diff --git a/config/generate-preloaded-classes.sh b/config/generate-preloaded-classes.sh new file mode 100755 index 000000000000..e36e148c7476 --- /dev/null +++ b/config/generate-preloaded-classes.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# +# Copyright (C) 2017 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +if [ "$#" -lt 2 ]; then + echo "Usage $0 <input classes file> <blacklist file> [extra classes files]" + exit 1 +fi + +# Write file headers first +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cat "$DIR/copyright-header" +echo "# Preloaded-classes filter file for phones. +# +# Classes in this file will be allocated into the boot image, and forcibly initialized in +# the zygote during initialization. This is a trade-off, using virtual address space to share +# common heap between apps. +# +# This file has been derived for mainline phone (and tablet) usage. +#" + +input=$1 +blacklist=$2 +shift 2 +extra_classes_files=("$@") + +# Disable locale to enable lexicographical sorting +LC_ALL=C sort "$input" "${extra_classes_files[@]}" | uniq | grep -f "$blacklist" -v -F -x diff --git a/preloaded-classes b/config/preloaded-classes index 96122319c8cf..1c842c79359a 100644 --- a/preloaded-classes +++ b/config/preloaded-classes @@ -13,8 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # -# -# # Preloaded-classes filter file for phones. # # Classes in this file will be allocated into the boot image, and forcibly initialized in @@ -1454,6 +1452,7 @@ android.icu.impl.UResource$Sink android.icu.impl.UResource$Table android.icu.impl.UResource$Value android.icu.impl.Utility +android.icu.impl.coll.CollationRoot android.icu.impl.locale.AsciiUtil android.icu.impl.locale.BaseLocale android.icu.impl.locale.BaseLocale$Cache @@ -2276,7 +2275,6 @@ android.util.Base64 android.util.Base64$Coder android.util.Base64$Decoder android.util.Base64$Encoder -android.util.BootTimingsTraceLog android.util.ContainerHelpers android.util.DisplayMetrics android.util.EventLog @@ -2328,6 +2326,7 @@ android.util.SparseLongArray android.util.StateSet android.util.SuperNotCalledException android.util.TimeUtils +android.util.TimingsTraceLog android.util.TypedValue android.util.Xml android.util.jar.StrictJarFile diff --git a/config/preloaded-classes-blacklist b/config/preloaded-classes-blacklist new file mode 100644 index 000000000000..48cdce852872 --- /dev/null +++ b/config/preloaded-classes-blacklist @@ -0,0 +1 @@ +placeholder diff --git a/config/preloaded-classes-extra b/config/preloaded-classes-extra new file mode 100644 index 000000000000..1934cbca27ad --- /dev/null +++ b/config/preloaded-classes-extra @@ -0,0 +1 @@ +android.icu.impl.coll.CollationRoot diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index adb3152d4ae7..4e258a3a4b47 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -16,7 +16,7 @@ package android.app; -import static android.os.Build.VERSION_CODES.O; +import static android.os.Build.VERSION_CODES.O_MR1; import static java.lang.Character.MIN_VALUE; @@ -761,6 +761,11 @@ public class Activity extends ContextThemeWrapper boolean mStartedActivity; private boolean mDestroyed; private boolean mDoReportFullyDrawn = true; + private boolean mRestoredFromBundle; + + /** {@code true} if the activity lifecycle is in a state which supports picture-in-picture. + * This only affects the client-side exception, the actual state check still happens in AMS. */ + private boolean mCanEnterPictureInPicture = false; /** true if the activity is going through a transient pause */ /*package*/ boolean mTemporaryPause = false; /** true if the activity is being destroyed in order to recreate it with a new configuration */ @@ -973,7 +978,7 @@ public class Activity extends ContextThemeWrapper protected void onCreate(@Nullable Bundle savedInstanceState) { if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState); - if (getApplicationInfo().targetSdkVersion > O && mActivityInfo.isFixedOrientation()) { + if (getApplicationInfo().targetSdkVersion >= O_MR1 && mActivityInfo.isFixedOrientation()) { final TypedArray ta = obtainStyledAttributes(com.android.internal.R.styleable.Window); final boolean isTranslucentOrFloating = ActivityInfo.isTranslucentOrFloating(ta); ta.recycle(); @@ -1012,6 +1017,7 @@ public class Activity extends ContextThemeWrapper if (mVoiceInteractor != null) { mVoiceInteractor.attachActivity(this); } + mRestoredFromBundle = savedInstanceState != null; mCalled = true; } @@ -1857,8 +1863,18 @@ public class Activity extends ContextThemeWrapper getApplication().dispatchActivityStopped(this); mTranslucentCallback = null; mCalled = true; - if (isFinishing() && mAutoFillResetNeeded) { - getAutofillManager().commit(); + + if (isFinishing()) { + if (mAutoFillResetNeeded) { + getAutofillManager().commit(); + } else if (mIntent != null + && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)) { + // Activity was launched when user tapped a link in the Autofill Save UI - since + // user launched another activity, the Save UI should not be restored when this + // activity is finished. + getAutofillManager().onPendingSaveUi(AutofillManager.PENDING_UI_OPERATION_CANCEL, + mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)); + } } } @@ -1948,7 +1964,7 @@ public class Activity extends ContextThemeWrapper if (mDoReportFullyDrawn) { mDoReportFullyDrawn = false; try { - ActivityManager.getService().reportActivityFullyDrawn(mToken); + ActivityManager.getService().reportActivityFullyDrawn(mToken, mRestoredFromBundle); } catch (RemoteException e) { } } @@ -2089,6 +2105,10 @@ public class Activity extends ContextThemeWrapper if (params == null) { throw new IllegalArgumentException("Expected non-null picture-in-picture params"); } + if (!mCanEnterPictureInPicture) { + throw new IllegalStateException("Activity must be resumed to enter" + + " picture-in-picture"); + } return ActivityManagerNative.getDefault().enterPictureInPictureMode(mToken, params); } catch (RemoteException e) { return false; @@ -3193,9 +3213,8 @@ public class Activity extends ContextThemeWrapper /** - * Moves the activity from - * {@link android.app.ActivityManager.StackId#FREEFORM_WORKSPACE_STACK_ID} to - * {@link android.app.ActivityManager.StackId#FULLSCREEN_WORKSPACE_STACK_ID} stack. + * Moves the activity from {@link WindowConfiguration#WINDOWING_MODE_FREEFORM} windowing mode to + * {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}. * * @hide */ @@ -3204,14 +3223,6 @@ public class Activity extends ContextThemeWrapper ActivityManager.getService().exitFreeformMode(mToken); } - /** Returns the current stack Id for the window. - * @hide - */ - @Override - public int getWindowStackId() throws RemoteException { - return ActivityManager.getService().getActivityStackId(mToken); - } - /** * Puts the activity in picture-in-picture mode if the activity supports. * @see android.R.attr#supportsPictureInPicture @@ -5490,6 +5501,13 @@ public class Activity extends ContextThemeWrapper } else { mParent.finishFromChild(this); } + + // Activity was launched when user tapped a link in the Autofill Save UI - Save UI must + // be restored now. + if (mIntent != null && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)) { + getAutofillManager().onPendingSaveUi(AutofillManager.PENDING_UI_OPERATION_RESTORE, + mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)); + } } /** @@ -6224,6 +6242,11 @@ public class Activity extends ContextThemeWrapper } mHandler.getLooper().dump(new PrintWriterPrinter(writer), prefix); + + final AutofillManager afm = getAutofillManager(); + if (afm != null) { + afm.dump(prefix, writer); + } } /** @@ -6955,25 +6978,29 @@ public class Activity extends ContextThemeWrapper return mParent != null ? mParent.getActivityToken() : mToken; } - final void performCreateCommon() { - mVisibleFromClient = !mWindow.getWindowStyle().getBoolean( - com.android.internal.R.styleable.Window_windowNoDisplay, false); - mFragments.dispatchActivityCreated(); - mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions()); - } - final void performCreate(Bundle icicle) { - restoreHasCurrentPermissionRequest(icicle); - onCreate(icicle); - mActivityTransitionState.readState(icicle); - performCreateCommon(); + performCreate(icicle, null); } final void performCreate(Bundle icicle, PersistableBundle persistentState) { + mCanEnterPictureInPicture = true; restoreHasCurrentPermissionRequest(icicle); - onCreate(icicle, persistentState); + if (persistentState != null) { + onCreate(icicle, persistentState); + } else { + onCreate(icicle); + } mActivityTransitionState.readState(icicle); - performCreateCommon(); + + mVisibleFromClient = !mWindow.getWindowStyle().getBoolean( + com.android.internal.R.styleable.Window_windowNoDisplay, false); + mFragments.dispatchActivityCreated(); + mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions()); + } + + final void performNewIntent(Intent intent) { + mCanEnterPictureInPicture = true; + onNewIntent(intent); } final void performStart() { @@ -7019,6 +7046,7 @@ public class Activity extends ContextThemeWrapper } final void performRestart() { + mCanEnterPictureInPicture = true; mFragments.noteStateNotSaved(); if (mToken != null && mParent == null) { @@ -7124,6 +7152,9 @@ public class Activity extends ContextThemeWrapper mDoReportFullyDrawn = false; mFragments.doLoaderStop(mChangingConfigurations /*retain*/); + // Disallow entering picture-in-picture after the activity has been stopped + mCanEnterPictureInPicture = false; + if (!mStopped) { if (mWindow != null) { mWindow.closeAllPanels(); diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index a0082e4e57bb..e76e1903a529 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -16,6 +16,16 @@ package android.app; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.WINDOWING_MODE_DOCKED; +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; + import android.Manifest; import android.annotation.IntDef; import android.annotation.NonNull; @@ -135,16 +145,6 @@ public class ActivityManager { private static final int FIRST_START_NON_FATAL_ERROR_CODE = 100; private static final int LAST_START_NON_FATAL_ERROR_CODE = 199; - /** - * System property to enable task snapshots. - * @hide - */ - public final static boolean ENABLE_TASK_SNAPSHOTS; - - static { - ENABLE_TASK_SNAPSHOTS = SystemProperties.getBoolean("persist.enable_task_snapshots", true); - } - static final class UidObserver extends IUidObserver.Stub { final OnUidImportanceListener mListener; final Context mContext; @@ -699,45 +699,21 @@ public class ActivityManager { /** Start of ID range used by stacks that are created dynamically. */ public static final int FIRST_DYNAMIC_STACK_ID = LAST_STATIC_STACK_ID + 1; + // TODO: Figure-out a way to remove this. public static boolean isStaticStack(int stackId) { return stackId >= FIRST_STATIC_STACK_ID && stackId <= LAST_STATIC_STACK_ID; } + // TODO: It seems this mostly means a stack on a secondary display now. Need to see if + // there are other meanings. If not why not just use information from the display? public static boolean isDynamicStack(int stackId) { return stackId >= FIRST_DYNAMIC_STACK_ID; } /** - * Returns true if the activities contained in the input stack display a shadow around - * their border. - */ - public static boolean hasWindowShadow(int stackId) { - return stackId == FREEFORM_WORKSPACE_STACK_ID || stackId == PINNED_STACK_ID; - } - - /** - * Returns true if the activities contained in the input stack display a decor view. - */ - public static boolean hasWindowDecor(int stackId) { - return stackId == FREEFORM_WORKSPACE_STACK_ID; - } - - /** - * Returns true if the tasks contained in the stack can be resized independently of the - * stack. - */ - public static boolean isTaskResizeAllowed(int stackId) { - return stackId == FREEFORM_WORKSPACE_STACK_ID; - } - - /** Returns true if the task bounds should persist across power cycles. */ - public static boolean persistTaskBounds(int stackId) { - return stackId == FREEFORM_WORKSPACE_STACK_ID; - } - - /** * Returns true if dynamic stacks are allowed to be visible behind the input stack. */ + // TODO: Figure-out a way to remove. public static boolean isDynamicStacksVisibleBehindAllowed(int stackId) { return stackId == PINNED_STACK_ID || stackId == ASSISTANT_STACK_ID; } @@ -746,6 +722,7 @@ public class ActivityManager { * Returns true if we try to maintain focus in the current stack when the top activity * finishes. */ + // TODO: Figure-out a way to remove. Probably isn't needed in the new world... public static boolean keepFocusInStackIfPossible(int stackId) { return stackId == FREEFORM_WORKSPACE_STACK_ID || stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID; @@ -754,6 +731,7 @@ public class ActivityManager { /** * Returns true if Stack size is affected by the docked stack changing size. */ + // TODO: Figure-out a way to remove. public static boolean isResizeableByDockedStack(int stackId) { return isStaticStack(stackId) && stackId != DOCKED_STACK_ID && stackId != PINNED_STACK_ID && stackId != ASSISTANT_STACK_ID; @@ -763,6 +741,7 @@ public class ActivityManager { * Returns true if the size of tasks in the input stack are affected by the docked stack * changing size. */ + // TODO: What is the difference between this method and the one above?? public static boolean isTaskResizeableByDockedStack(int stackId) { return isStaticStack(stackId) && stackId != FREEFORM_WORKSPACE_STACK_ID && stackId != DOCKED_STACK_ID && stackId != PINNED_STACK_ID @@ -788,16 +767,6 @@ public class ActivityManager { } /** - * Return whether a stackId is a stack containing floating windows. Floating windows - * are laid out differently as they are allowed to extend past the display bounds - * without overscan insets. - */ - public static boolean tasksAreFloating(int stackId) { - return stackId == FREEFORM_WORKSPACE_STACK_ID - || stackId == PINNED_STACK_ID; - } - - /** * Return whether a stackId is a stack that be a backdrop to a translucent activity. These * are generally fullscreen stacks. */ @@ -821,21 +790,6 @@ public class ActivityManager { } /** - * Returns true if the windows in the stack can receive input keys. - */ - public static boolean canReceiveKeys(int stackId) { - return stackId != PINNED_STACK_ID; - } - - /** - * Returns true if the stack can be visible above lockscreen. - */ - public static boolean isAllowedOverLockscreen(int stackId) { - return stackId == HOME_STACK_ID || stackId == FULLSCREEN_WORKSPACE_STACK_ID || - stackId == ASSISTANT_STACK_ID; - } - - /** * Returns true if activities from stasks in the given {@param stackId} are allowed to * enter picture-in-picture. */ @@ -844,10 +798,6 @@ public class ActivityManager { stackId != RECENTS_STACK_ID; } - public static boolean isAlwaysOnTop(int stackId) { - return stackId == PINNED_STACK_ID; - } - /** * Returns true if the top task in the task is allowed to return home when finished and * there are other tasks in the stack. @@ -865,27 +815,12 @@ public class ActivityManager { } /** - * Returns true if any visible windows belonging to apps in this stack should be kept on - * screen when the app is killed due to something like the low memory killer. - */ - public static boolean keepVisibleDeadAppWindowOnScreen(int stackId) { - return stackId != PINNED_STACK_ID; - } - - /** - * Returns true if the backdrop on the client side should match the frame of the window. - * Returns false, if the backdrop should be fullscreen. - */ - public static boolean useWindowFrameForBackdrop(int stackId) { - return stackId == FREEFORM_WORKSPACE_STACK_ID || stackId == PINNED_STACK_ID; - } - - /** * Returns true if a window from the specified stack with {@param stackId} are normally * fullscreen, i. e. they can become the top opaque fullscreen window, meaning that it * controls system bars, lockscreen occluded/dismissing state, screen rotation animation, * etc. */ + // TODO: What about the other side of docked stack if we move this to WindowConfiguration? public static boolean normallyFullscreenWindows(int stackId) { return stackId != PINNED_STACK_ID && stackId != FREEFORM_WORKSPACE_STACK_ID && stackId != DOCKED_STACK_ID; @@ -896,6 +831,7 @@ public class ActivityManager { * multi-window mode. * @see android.app.ActivityManager#supportsMultiWindow */ + // TODO: What about the other side of docked stack if we move this to WindowConfiguration? public static boolean isMultiWindowStack(int stackId) { return stackId == PINNED_STACK_ID || stackId == FREEFORM_WORKSPACE_STACK_ID || stackId == DOCKED_STACK_ID; @@ -908,21 +844,6 @@ public class ActivityManager { return stackId == HOME_STACK_ID || stackId == RECENTS_STACK_ID; } - /** - * Returns true if this stack may be scaled without resizing, and windows within may need - * to be configured as such. - */ - public static boolean windowsAreScaleable(int stackId) { - return stackId == PINNED_STACK_ID; - } - - /** - * Returns true if windows in this stack should be given move animations by default. - */ - public static boolean hasMovementAnimations(int stackId) { - return stackId != PINNED_STACK_ID; - } - /** Returns true if the input stack and its content can affect the device orientation. */ public static boolean canSpecifyOrientation(int stackId) { return stackId == HOME_STACK_ID @@ -931,6 +852,52 @@ public class ActivityManager { || stackId == ASSISTANT_STACK_ID || isDynamicStack(stackId); } + + /** Returns the windowing mode that should be used for this input stack id. */ + // TODO: To be removed once we are not using stack id for stuff... + public static int getWindowingModeForStackId(int stackId) { + final int windowingMode; + switch (stackId) { + case FULLSCREEN_WORKSPACE_STACK_ID: + case HOME_STACK_ID: + case RECENTS_STACK_ID: + case ASSISTANT_STACK_ID: + windowingMode = WINDOWING_MODE_FULLSCREEN; + break; + case PINNED_STACK_ID: + windowingMode = WINDOWING_MODE_PINNED; + break; + case DOCKED_STACK_ID: + windowingMode = WINDOWING_MODE_DOCKED; + break; + case FREEFORM_WORKSPACE_STACK_ID: + windowingMode = WINDOWING_MODE_FREEFORM; + break; + default : + windowingMode = WINDOWING_MODE_UNDEFINED; + } + return windowingMode; + } + + /** Returns the activity type that should be used for this input stack id. */ + // TODO: To be removed once we are not using stack id for stuff... + public static int getActivityTypeForStackId(int stackId) { + final int activityType; + switch (stackId) { + case HOME_STACK_ID: + activityType = ACTIVITY_TYPE_HOME; + break; + case RECENTS_STACK_ID: + activityType = ACTIVITY_TYPE_RECENTS; + break; + case ASSISTANT_STACK_ID: + activityType = ACTIVITY_TYPE_ASSISTANT; + break; + default : + activityType = ACTIVITY_TYPE_STANDARD; + } + return activityType; + } } /** @@ -2148,165 +2115,6 @@ public class ActivityManager { } /** - * Metadata related to the {@link TaskThumbnail}. - * - * @hide - */ - public static class TaskThumbnailInfo implements Parcelable { - /** @hide */ - public static final String ATTR_TASK_THUMBNAILINFO_PREFIX = "task_thumbnailinfo_"; - private static final String ATTR_TASK_WIDTH = - ATTR_TASK_THUMBNAILINFO_PREFIX + "task_width"; - private static final String ATTR_TASK_HEIGHT = - ATTR_TASK_THUMBNAILINFO_PREFIX + "task_height"; - private static final String ATTR_SCREEN_ORIENTATION = - ATTR_TASK_THUMBNAILINFO_PREFIX + "screen_orientation"; - - public int taskWidth; - public int taskHeight; - public int screenOrientation = Configuration.ORIENTATION_UNDEFINED; - - public TaskThumbnailInfo() { - // Do nothing - } - - private TaskThumbnailInfo(Parcel source) { - readFromParcel(source); - } - - /** - * Resets this info state to the initial state. - * @hide - */ - public void reset() { - taskWidth = 0; - taskHeight = 0; - screenOrientation = Configuration.ORIENTATION_UNDEFINED; - } - - /** - * Copies from another ThumbnailInfo. - */ - public void copyFrom(TaskThumbnailInfo o) { - taskWidth = o.taskWidth; - taskHeight = o.taskHeight; - screenOrientation = o.screenOrientation; - } - - /** @hide */ - public void saveToXml(XmlSerializer out) throws IOException { - out.attribute(null, ATTR_TASK_WIDTH, Integer.toString(taskWidth)); - out.attribute(null, ATTR_TASK_HEIGHT, Integer.toString(taskHeight)); - out.attribute(null, ATTR_SCREEN_ORIENTATION, Integer.toString(screenOrientation)); - } - - /** @hide */ - public void restoreFromXml(String attrName, String attrValue) { - if (ATTR_TASK_WIDTH.equals(attrName)) { - taskWidth = Integer.parseInt(attrValue); - } else if (ATTR_TASK_HEIGHT.equals(attrName)) { - taskHeight = Integer.parseInt(attrValue); - } else if (ATTR_SCREEN_ORIENTATION.equals(attrName)) { - screenOrientation = Integer.parseInt(attrValue); - } - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(taskWidth); - dest.writeInt(taskHeight); - dest.writeInt(screenOrientation); - } - - public void readFromParcel(Parcel source) { - taskWidth = source.readInt(); - taskHeight = source.readInt(); - screenOrientation = source.readInt(); - } - - public static final Creator<TaskThumbnailInfo> CREATOR = new Creator<TaskThumbnailInfo>() { - public TaskThumbnailInfo createFromParcel(Parcel source) { - return new TaskThumbnailInfo(source); - } - public TaskThumbnailInfo[] newArray(int size) { - return new TaskThumbnailInfo[size]; - } - }; - } - - /** @hide */ - public static class TaskThumbnail implements Parcelable { - public Bitmap mainThumbnail; - public ParcelFileDescriptor thumbnailFileDescriptor; - public TaskThumbnailInfo thumbnailInfo; - - public TaskThumbnail() { - } - - private TaskThumbnail(Parcel source) { - readFromParcel(source); - } - - public int describeContents() { - if (thumbnailFileDescriptor != null) { - return thumbnailFileDescriptor.describeContents(); - } - return 0; - } - - public void writeToParcel(Parcel dest, int flags) { - if (mainThumbnail != null) { - dest.writeInt(1); - mainThumbnail.writeToParcel(dest, flags); - } else { - dest.writeInt(0); - } - if (thumbnailFileDescriptor != null) { - dest.writeInt(1); - thumbnailFileDescriptor.writeToParcel(dest, flags); - } else { - dest.writeInt(0); - } - if (thumbnailInfo != null) { - dest.writeInt(1); - thumbnailInfo.writeToParcel(dest, flags); - } else { - dest.writeInt(0); - } - } - - public void readFromParcel(Parcel source) { - if (source.readInt() != 0) { - mainThumbnail = Bitmap.CREATOR.createFromParcel(source); - } else { - mainThumbnail = null; - } - if (source.readInt() != 0) { - thumbnailFileDescriptor = ParcelFileDescriptor.CREATOR.createFromParcel(source); - } else { - thumbnailFileDescriptor = null; - } - if (source.readInt() != 0) { - thumbnailInfo = TaskThumbnailInfo.CREATOR.createFromParcel(source); - } else { - thumbnailInfo = null; - } - } - - public static final Creator<TaskThumbnail> CREATOR = new Creator<TaskThumbnail>() { - public TaskThumbnail createFromParcel(Parcel source) { - return new TaskThumbnail(source); - } - public TaskThumbnail[] newArray(int size) { - return new TaskThumbnail[size]; - } - }; - } - - /** * Represents a task snapshot. * @hide */ @@ -2403,15 +2211,6 @@ public class ActivityManager { } /** @hide */ - public TaskThumbnail getTaskThumbnail(int id) throws SecurityException { - try { - return getService().getTaskThumbnail(id); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** @hide */ @IntDef(flag = true, prefix = { "MOVE_TASK_" }, value = { MOVE_TASK_WITH_HOME, MOVE_TASK_NO_USER_ACTION, @@ -2907,6 +2706,8 @@ public class ActivityManager { /** * @hide */ + @RequiresPermission(anyOf={Manifest.permission.CLEAR_APP_USER_DATA, + Manifest.permission.ACCESS_INSTANT_APPS}) public boolean clearApplicationUserData(String packageName, IPackageDataObserver observer) { try { return getService().clearApplicationUserData(packageName, @@ -2921,7 +2722,8 @@ public class ActivityManager { * the user choosing to clear the app's data from within the device settings UI. It * erases all dynamic data associated with the app -- its private data and data in its * private area on external storage -- but does not remove the installed application - * itself, nor any OBB files. + * itself, nor any OBB files. It also revokes all runtime permissions that the app has acquired, + * clears all notifications and removes all Uri grants related to this application. * * @return {@code true} if the application successfully requested that the application's * data be erased; {@code false} otherwise. @@ -4294,28 +4096,6 @@ public class ActivityManager { } /** - * @hide - */ - public void startLockTaskMode(int taskId) { - try { - getService().startLockTaskModeById(taskId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * @hide - */ - public void stopLockTaskMode() { - try { - getService().stopLockTaskMode(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** * Return whether currently in lock task mode. When in this mode * no new tasks can be created or switched to. * diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index e5fe2402dae1..9d14f616a09a 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -30,8 +30,6 @@ import android.util.SparseIntArray; import com.android.internal.app.IVoiceInteractor; -import java.io.PrintWriter; -import java.util.ArrayList; import java.util.List; /** @@ -42,12 +40,6 @@ import java.util.List; public abstract class ActivityManagerInternal { /** - * Type for {@link #notifyAppTransitionStarting}: The transition was started because we had - * the surface saved. - */ - public static final int APP_TRANSITION_SAVED_SURFACE = 0; - - /** * Type for {@link #notifyAppTransitionStarting}: The transition was started because we drew * the splash screen. */ @@ -90,11 +82,12 @@ public abstract class ActivityManagerInternal { String processName, String abiOverride, int uid, Runnable crashHandler); /** - * Acquires a sleep token with the specified tag. + * Acquires a sleep token for the specified display with the specified tag. * * @param tag A string identifying the purpose of the token (eg. "Dream"). + * @param displayId The display to apply the sleep token to. */ - public abstract SleepToken acquireSleepToken(@NonNull String tag); + public abstract SleepToken acquireSleepToken(@NonNull String tag, int displayId); /** * Sleep tokens cause the activity manager to put the top activity to sleep. @@ -263,4 +256,10 @@ public abstract class ActivityManagerInternal { * Clears the previously saved activity manager ANR state. */ public abstract void clearSavedANRState(); + + /** + * Set focus on an activity. + * @param token The IApplicationToken for the activity + */ + public abstract void setFocusedActivity(IBinder token); } diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 6dead3e6c0dc..0bffc9e6cee5 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -195,6 +195,14 @@ public class ActivityOptions { private static final String KEY_DOCK_CREATE_MODE = "android:activity.dockCreateMode"; /** + * Determines whether to disallow the outgoing activity from entering picture-in-picture as the + * result of a new activity being launched. + * @hide + */ + private static final String KEY_DISALLOW_ENTER_PICTURE_IN_PICTURE_WHILE_LAUNCHING = + "android:activity.disallowEnterPictureInPictureWhileLaunching"; + + /** * For Activity transitions, the calling Activity's TransitionListener used to * notify the called Activity when the shared element and the exit transitions * complete. @@ -267,6 +275,7 @@ public class ActivityOptions { private int mLaunchStackId = INVALID_STACK_ID; private int mLaunchTaskId = -1; private int mDockCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; + private boolean mDisallowEnterPictureInPictureWhileLaunching; private boolean mTaskOverlay; private boolean mTaskOverlayCanResume; private AppTransitionAnimationSpec mAnimSpecs[]; @@ -856,6 +865,8 @@ public class ActivityOptions { mTaskOverlay = opts.getBoolean(KEY_TASK_OVERLAY, false); mTaskOverlayCanResume = opts.getBoolean(KEY_TASK_OVERLAY_CAN_RESUME, false); mDockCreateMode = opts.getInt(KEY_DOCK_CREATE_MODE, DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT); + mDisallowEnterPictureInPictureWhileLaunching = opts.getBoolean( + KEY_DISALLOW_ENTER_PICTURE_IN_PICTURE_WHILE_LAUNCHING, false); if (opts.containsKey(KEY_ANIM_SPECS)) { Parcelable[] specs = opts.getParcelableArray(KEY_ANIM_SPECS); mAnimSpecs = new AppTransitionAnimationSpec[specs.length]; @@ -1121,6 +1132,16 @@ public class ActivityOptions { mDockCreateMode = dockCreateMode; } + /** @hide */ + public void setDisallowEnterPictureInPictureWhileLaunching(boolean disallow) { + mDisallowEnterPictureInPictureWhileLaunching = disallow; + } + + /** @hide */ + public boolean disallowEnterPictureInPictureWhileLaunching() { + return mDisallowEnterPictureInPictureWhileLaunching; + } + /** * Update the current values in this ActivityOptions from those supplied * in <var>otherOptions</var>. Any values @@ -1275,6 +1296,8 @@ public class ActivityOptions { b.putBoolean(KEY_TASK_OVERLAY, mTaskOverlay); b.putBoolean(KEY_TASK_OVERLAY_CAN_RESUME, mTaskOverlayCanResume); b.putInt(KEY_DOCK_CREATE_MODE, mDockCreateMode); + b.putBoolean(KEY_DISALLOW_ENTER_PICTURE_IN_PICTURE_WHILE_LAUNCHING, + mDisallowEnterPictureInPictureWhileLaunching); if (mAnimSpecs != null) { b.putParcelableArray(KEY_ANIM_SPECS, mAnimSpecs); } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 295423487fc7..4e8d24005da2 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -2680,14 +2680,8 @@ public final class ActivityThread { Activity activity = null; try { java.lang.ClassLoader cl = appContext.getClassLoader(); - if (appContext.getApplicationContext() instanceof Application) { - activity = ((Application) appContext.getApplicationContext()) - .instantiateActivity(cl, component.getClassName(), r.intent); - } - if (activity == null) { - activity = mInstrumentation.newActivity( - cl, component.getClassName(), r.intent); - } + activity = mInstrumentation.newActivity( + cl, component.getClassName(), r.intent); StrictMode.incrementExpectedActivityCount(activity.getClass()); r.intent.setExtrasClassLoader(cl); r.intent.prepareToEnterProcess(); @@ -3183,8 +3177,7 @@ public final class ActivityThread { data.intent.setExtrasClassLoader(cl); data.intent.prepareToEnterProcess(); data.setExtrasClassLoader(cl); - receiver = instantiate(cl, component, data.intent, app, - Application::instantiateReceiver); + receiver = (BroadcastReceiver)cl.loadClass(component).newInstance(); } catch (Exception e) { if (DEBUG_BROADCAST) Slog.i(TAG, "Finishing failed broadcast to " + data.intent.getComponent()); @@ -3272,13 +3265,12 @@ public final class ActivityThread { } else { try { if (DEBUG_BACKUP) Slog.v(TAG, "Initializing agent class " + classname); - ContextImpl context = ContextImpl.createAppContext(this, packageInfo); java.lang.ClassLoader cl = packageInfo.getClassLoader(); - agent = instantiate(cl, classname, context, - Application::instantiateBackupAgent); + agent = (BackupAgent) cl.loadClass(classname).newInstance(); // set up the agent's context + ContextImpl context = ContextImpl.createAppContext(this, packageInfo); context.setOuterContext(agent); agent.attach(context); @@ -3338,12 +3330,9 @@ public final class ActivityThread { LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, data.compatInfo); Service service = null; - Application app = null; try { - app = packageInfo.makeApplication(false, mInstrumentation); java.lang.ClassLoader cl = packageInfo.getClassLoader(); - service = instantiate(cl, data.info.name, data.intent, app, - Application::instantiateService); + service = (Service) cl.loadClass(data.info.name).newInstance(); } catch (Exception e) { if (!mInstrumentation.onException(service, e)) { throw new RuntimeException( @@ -3358,6 +3347,7 @@ public final class ActivityThread { ContextImpl context = ContextImpl.createAppContext(this, packageInfo); context.setOuterContext(service); + Application app = packageInfo.makeApplication(false, mInstrumentation); service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService()); service.onCreate(); @@ -5696,8 +5686,8 @@ public final class ActivityThread { try { final ClassLoader cl = instrContext.getClassLoader(); - mInstrumentation = instantiate(cl, data.instrumentationName.getClassName(), - instrContext, Application::instantiateInstrumentation); + mInstrumentation = (Instrumentation) + cl.loadClass(data.instrumentationName.getClassName()).newInstance(); } catch (Exception e) { throw new RuntimeException( "Unable to instantiate instrumentation " @@ -6248,8 +6238,8 @@ public final class ActivityThread { try { final java.lang.ClassLoader cl = c.getClassLoader(); - localProvider = instantiate(cl, info.name, context, - Application::instantiateProvider); + localProvider = (ContentProvider)cl. + loadClass(info.name).newInstance(); provider = localProvider.getIContentProvider(); if (provider == null) { Slog.e(TAG, "Failed to instantiate class " + @@ -6459,49 +6449,6 @@ public final class ActivityThread { } } - private <T> T instantiate(ClassLoader cl, String className, Context c, - Instantiator<T> instantiator) - throws ClassNotFoundException, IllegalAccessException, InstantiationException { - Application app = getApp(c); - if (app != null) { - T a = instantiator.instantiate(app, cl, className); - if (a != null) return a; - } - return (T) cl.loadClass(className).newInstance(); - } - - private <T> T instantiate(ClassLoader cl, String className, Intent intent, Context c, - IntentInstantiator<T> instantiator) - throws ClassNotFoundException, IllegalAccessException, InstantiationException { - Application app = getApp(c); - if (app != null) { - T a = instantiator.instantiate(app, cl, className, intent); - if (a != null) return a; - } - return (T) cl.loadClass(className).newInstance(); - } - - private Application getApp(Context c) { - // We need this shortcut to avoid actually calling getApplicationContext() on an Application - // because the Application may not return itself for getApplicationContext() because the - // API doesn't enforce it. - if (c instanceof Application) return (Application) c; - if (c.getApplicationContext() instanceof Application) { - return (Application) c.getApplicationContext(); - } - return null; - } - - private interface Instantiator<T> { - T instantiate(Application app, ClassLoader cl, String className) - throws ClassNotFoundException, IllegalAccessException, InstantiationException; - } - - private interface IntentInstantiator<T> { - T instantiate(Application app, ClassLoader cl, String className, Intent intent) - throws ClassNotFoundException, IllegalAccessException, InstantiationException; - } - private static class EventLoggingReporter implements EventLogger.Reporter { @Override public void report (int code, Object... list) { diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java index cc23ec9023b6..156df36a600c 100644 --- a/core/java/android/app/Application.java +++ b/core/java/android/app/Application.java @@ -16,20 +16,17 @@ package android.app; +import java.util.ArrayList; + import android.annotation.CallSuper; -import android.app.backup.BackupAgent; -import android.content.BroadcastReceiver; import android.content.ComponentCallbacks; import android.content.ComponentCallbacks2; -import android.content.ContentProvider; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.content.res.Configuration; import android.os.Bundle; -import java.util.ArrayList; - /** * Base class for maintaining global application state. You can provide your own * implementation by creating a subclass and specifying the fully-qualified name @@ -292,73 +289,4 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 { } } } - - /** - * Allows application to override the creation of activities. This can be used to - * perform things such as dependency injection or class loader changes to these - * classes. Return null to use the default creation flow. - * @param cl The default classloader to use for instantiation. - * @param className The class to be instantiated. - * @param intent Intent creating the class. - */ - public Activity instantiateActivity(ClassLoader cl, String className, Intent intent) { - return null; - } - - /** - * Allows application to override the creation of receivers. This can be used to - * perform things such as dependency injection or class loader changes to these - * classes. Return null to use the default creation flow. - * @param cl The default classloader to use for instantiation. - * @param className The class to be instantiated. - * @param intent Intent creating the class. - */ - public BroadcastReceiver instantiateReceiver(ClassLoader cl, String className, Intent intent) { - return null; - } - - /** - * Allows application to override the creation of services. This can be used to - * perform things such as dependency injection or class loader changes to these - * classes. Return null to use the default creation flow. - * @param cl The default classloader to use for instantiation. - * @param className The class to be instantiated. - * @param intent Intent creating the class. - */ - public Service instantiateService(ClassLoader cl, String className, Intent intent) { - return null; - } - - /** - * Allows application to override the creation of providers. This can be used to - * perform things such as dependency injection or class loader changes to these - * classes. Return null to use the default creation flow. - * @param cl The default classloader to use for instantiation. - * @param className The class to be instantiated. - */ - public ContentProvider instantiateProvider(ClassLoader cl, String className) { - return null; - } - - /** - * Allows application to override the creation of backup agents. This can be used to - * perform things such as dependency injection or class loader changes to these - * classes. Return null to use the default creation flow. - * @param cl The default classloader to use for instantiation. - * @param className The class to be instantiated. - */ - public BackupAgent instantiateBackupAgent(ClassLoader cl, String className) { - return null; - } - - /** - * Allows application to override the creation of instrumentation. This can be used to - * perform things such as dependency injection or class loader changes to these - * classes. Return null to use the default creation flow. - * @param cl The default classloader to use for instantiation. - * @param className The class to be instantiated. - */ - public Instrumentation instantiateInstrumentation(ClassLoader cl, String className) { - return null; - } }
\ No newline at end of file diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index fa9d7ca8ebc5..1e05ae2ec5d2 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -209,7 +209,6 @@ interface IActivityManager { void forceStopPackage(in String packageName, int userId); boolean killPids(in int[] pids, in String reason, boolean secure); List<ActivityManager.RunningServiceInfo> getServices(int maxNum, int flags); - ActivityManager.TaskThumbnail getTaskThumbnail(int taskId); ActivityManager.TaskDescription getTaskDescription(int taskId); // Retrieve running application processes in the system List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses(); @@ -376,7 +375,7 @@ interface IActivityManager { boolean convertFromTranslucent(in IBinder token); boolean convertToTranslucent(in IBinder token, in Bundle options); void notifyActivityDrawn(in IBinder token); - void reportActivityFullyDrawn(in IBinder token); + void reportActivityFullyDrawn(in IBinder token, boolean restoredFromBundle); void restart(); void performIdleMaintenance(); void takePersistableUriPermission(in Uri uri, int modeFlags, int userId); @@ -391,7 +390,6 @@ interface IActivityManager { // Start of L transactions String getTagForIntentSender(in IIntentSender sender, in String prefix); boolean startUserInBackground(int userid); - void startLockTaskModeById(int taskId); void startLockTaskModeByToken(in IBinder token); void stopLockTaskMode(); boolean isInLockTaskMode(); @@ -478,7 +476,6 @@ interface IActivityManager { * different stack. */ void positionTaskInStack(int taskId, int stackId, int position); - int getActivityStackId(in IBinder token); void exitFreeformMode(in IBinder token); void reportSizeConfigurations(in IBinder token, in int[] horizontalSizeConfiguration, in int[] verticalSizeConfigurations, in int[] smallestWidthConfigurations); diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index 467fc952ffee..e260967f92d0 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -48,6 +48,7 @@ import android.view.KeyEvent; import android.view.MotionEvent; import android.view.ViewConfiguration; import android.view.Window; + import com.android.internal.content.ReferrerIntent; import java.io.File; @@ -1305,7 +1306,7 @@ public class Instrumentation { * @param intent The new intent being received. */ public void callActivityOnNewIntent(Activity activity, Intent intent) { - activity.onNewIntent(intent); + activity.performNewIntent(intent); } /** diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index a218274481a0..9511f3fd7cef 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -60,7 +60,6 @@ import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextUtils; import android.text.style.AbsoluteSizeSpan; -import android.text.style.BackgroundColorSpan; import android.text.style.CharacterStyle; import android.text.style.ForegroundColorSpan; import android.text.style.RelativeSizeSpan; @@ -1164,7 +1163,8 @@ public class Notification implements Parcelable * Constant for {@link Builder#setGroupAlertBehavior(int)}, meaning that all children * notification in a group should be silenced (no sound or vibration) even if they are posted * to a {@link NotificationChannel} that has sound and/or vibration. Use this constant to - * mute this notification if this notification is a group child. + * mute this notification if this notification is a group child. This must be applied to all + * children notifications you want to mute. * * <p> For example, you might want to use this constant if you post a number of children * notifications at once (say, after a periodic sync), and only need to notify the user @@ -1179,7 +1179,8 @@ public class Notification implements Parcelable * to mute this notification if this notification is a group summary. * * <p>For example, you might want to use this constant if only the children notifications - * in your group have content and the summary is only used to visually group notifications. + * in your group have content and the summary is only used to visually group notifications + * rather than to alert the user that new information is available. */ public static final int GROUP_ALERT_CHILDREN = 2; @@ -2914,7 +2915,9 @@ public class Notification implements Parcelable * Sets the group alert behavior for this notification. Use this method to mute this * notification if alerts for this notification's group should be handled by a different * notification. This is only applicable for notifications that belong to a - * {@link #setGroup(String) group}. + * {@link #setGroup(String) group}. This must be called on all notifications you want to + * mute. For example, if you want only the summary of your group to make noise, all + * children in the group should have the group alert behavior {@link #GROUP_ALERT_SUMMARY}. * * <p> The default value is {@link #GROUP_ALERT_ALL}.</p> */ @@ -3894,7 +3897,7 @@ public class Notification implements Parcelable boolean showProgress = handleProgressBar(p.hasProgress, contentView, ex); if (p.title != null) { contentView.setViewVisibility(R.id.title, View.VISIBLE); - contentView.setTextViewText(R.id.title, p.title); + contentView.setTextViewText(R.id.title, processTextSpans(p.title)); if (!p.ambient) { setTextViewColorPrimary(contentView, R.id.title); } @@ -3905,7 +3908,7 @@ public class Notification implements Parcelable if (p.text != null) { int textId = showProgress ? com.android.internal.R.id.text_line_1 : com.android.internal.R.id.text; - contentView.setTextViewText(textId, p.text); + contentView.setTextViewText(textId, processTextSpans(p.text)); if (!p.ambient) { setTextViewColorSecondary(contentView, textId); } @@ -3917,11 +3920,22 @@ public class Notification implements Parcelable return contentView; } + private CharSequence processTextSpans(CharSequence text) { + if (hasForegroundColor()) { + return NotificationColorUtil.clearColorSpans(text); + } + return text; + } + private void setTextViewColorPrimary(RemoteViews contentView, int id) { ensureColors(); contentView.setTextColor(id, mPrimaryTextColor); } + private boolean hasForegroundColor() { + return mForegroundColor != COLOR_INVALID; + } + /** * @return the primary text color * @hide @@ -3964,7 +3978,7 @@ public class Notification implements Parcelable || mActionBarColor == COLOR_INVALID || mTextColorsAreForBackground != backgroundColor) { mTextColorsAreForBackground = backgroundColor; - if (mForegroundColor == COLOR_INVALID || !isColorized()) { + if (!hasForegroundColor() || !isColorized()) { mPrimaryTextColor = NotificationColorUtil.resolvePrimaryColor(mContext, backgroundColor); mSecondaryTextColor = NotificationColorUtil.resolveSecondaryColor(mContext, @@ -4215,7 +4229,8 @@ public class Notification implements Parcelable } if (headerText != null) { // TODO: Remove the span entirely to only have the string with propper formating. - contentView.setTextViewText(R.id.header_text, processLegacyText(headerText)); + contentView.setTextViewText(R.id.header_text, processTextSpans( + processLegacyText(headerText))); setTextViewColorSecondary(contentView, R.id.header_text); contentView.setViewVisibility(R.id.header_text, View.VISIBLE); contentView.setViewVisibility(R.id.header_text_divider, View.VISIBLE); @@ -4346,18 +4361,21 @@ public class Notification implements Parcelable if (!p.ambient && validRemoteInput && replyText != null && replyText.length > 0 && !TextUtils.isEmpty(replyText[0])) { big.setViewVisibility(R.id.notification_material_reply_container, View.VISIBLE); - big.setTextViewText(R.id.notification_material_reply_text_1, replyText[0]); + big.setTextViewText(R.id.notification_material_reply_text_1, + processTextSpans(replyText[0])); setTextViewColorSecondary(big, R.id.notification_material_reply_text_1); if (replyText.length > 1 && !TextUtils.isEmpty(replyText[1])) { big.setViewVisibility(R.id.notification_material_reply_text_2, View.VISIBLE); - big.setTextViewText(R.id.notification_material_reply_text_2, replyText[1]); + big.setTextViewText(R.id.notification_material_reply_text_2, + processTextSpans(replyText[1])); setTextViewColorSecondary(big, R.id.notification_material_reply_text_2); if (replyText.length > 2 && !TextUtils.isEmpty(replyText[2])) { big.setViewVisibility( R.id.notification_material_reply_text_3, View.VISIBLE); - big.setTextViewText(R.id.notification_material_reply_text_3, replyText[2]); + big.setTextViewText(R.id.notification_material_reply_text_3, + processTextSpans(replyText[2])); setTextViewColorSecondary(big, R.id.notification_material_reply_text_3); } } @@ -4664,12 +4682,12 @@ public class Notification implements Parcelable CharSequence title = action.title; ColorStateList[] outResultColor = null; if (isLegacy()) { - title = clearColorSpans(title); + title = NotificationColorUtil.clearColorSpans(title); } else { outResultColor = new ColorStateList[1]; title = ensureColorSpanContrast(title, bgColor, outResultColor); } - button.setTextViewText(R.id.action0, title); + button.setTextViewText(R.id.action0, processTextSpans(title)); setTextViewColorPrimary(button, R.id.action0); if (outResultColor != null && outResultColor[0] != null) { // We need to set the text color as well since changing a text to uppercase @@ -4679,7 +4697,8 @@ public class Notification implements Parcelable button.setTextColor(R.id.action0,resolveContrastColor()); } } else { - button.setTextViewText(R.id.action0, processLegacyText(action.title)); + button.setTextViewText(R.id.action0, processTextSpans( + processLegacyText(action.title))); if (isColorized() && !ambient) { setTextViewColorPrimary(button, R.id.action0); } else if (mN.color != COLOR_DEFAULT && mTintActionButtons) { @@ -4691,45 +4710,6 @@ public class Notification implements Parcelable } /** - * Clears all color spans of a text - * @param charSequence the input text - * @return the same text but without color spans - */ - private CharSequence clearColorSpans(CharSequence charSequence) { - if (charSequence instanceof Spanned) { - Spanned ss = (Spanned) charSequence; - Object[] spans = ss.getSpans(0, ss.length(), Object.class); - SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString()); - for (Object span : spans) { - Object resultSpan = span; - if (resultSpan instanceof CharacterStyle) { - resultSpan = ((CharacterStyle) span).getUnderlying(); - } - if (resultSpan instanceof TextAppearanceSpan) { - TextAppearanceSpan originalSpan = (TextAppearanceSpan) resultSpan; - if (originalSpan.getTextColor() != null) { - resultSpan = new TextAppearanceSpan( - originalSpan.getFamily(), - originalSpan.getTextStyle(), - originalSpan.getTextSize(), - null, - originalSpan.getLinkTextColor()); - } - } else if (resultSpan instanceof ForegroundColorSpan - || (resultSpan instanceof BackgroundColorSpan)) { - continue; - } else { - resultSpan = span; - } - builder.setSpan(resultSpan, ss.getSpanStart(span), ss.getSpanEnd(span), - ss.getSpanFlags(span)); - } - return builder; - } - return charSequence; - } - - /** * Ensures contrast on color spans against a background color. also returns the color of the * text if a span was found that spans over the whole text. * @@ -5182,17 +5162,22 @@ public class Notification implements Parcelable if (extras.getBoolean(EXTRA_REDUCED_IMAGES)) { return; } + boolean isLowRam = ActivityManager.isLowRamDeviceStatic(); if (mLargeIcon != null || largeIcon != null) { Resources resources = context.getResources(); Class<? extends Style> style = getNotificationStyle(); - int maxWidth = resources.getDimensionPixelSize(R.dimen.notification_right_icon_size); + int maxWidth = resources.getDimensionPixelSize(isLowRam + ? R.dimen.notification_right_icon_size_low_ram + : R.dimen.notification_right_icon_size); int maxHeight = maxWidth; if (MediaStyle.class.equals(style) || DecoratedMediaCustomViewStyle.class.equals(style)) { - maxHeight = resources.getDimensionPixelSize( - R.dimen.notification_media_image_max_height); - maxWidth = resources.getDimensionPixelSize( - R.dimen.notification_media_image_max_width); + maxHeight = resources.getDimensionPixelSize(isLowRam + ? R.dimen.notification_media_image_max_height_low_ram + : R.dimen.notification_media_image_max_height); + maxWidth = resources.getDimensionPixelSize(isLowRam + ? R.dimen.notification_media_image_max_width_low_ram + : R.dimen.notification_media_image_max_width); } if (mLargeIcon != null) { mLargeIcon.scaleDownIfNecessary(maxWidth, maxHeight); @@ -5201,19 +5186,22 @@ public class Notification implements Parcelable largeIcon = Icon.scaleDownIfNecessary(largeIcon, maxWidth, maxHeight); } } - reduceImageSizesForRemoteView(contentView, context); - reduceImageSizesForRemoteView(headsUpContentView, context); - reduceImageSizesForRemoteView(bigContentView, context); + reduceImageSizesForRemoteView(contentView, context, isLowRam); + reduceImageSizesForRemoteView(headsUpContentView, context, isLowRam); + reduceImageSizesForRemoteView(bigContentView, context, isLowRam); extras.putBoolean(EXTRA_REDUCED_IMAGES, true); } - private void reduceImageSizesForRemoteView(RemoteViews remoteView, Context context) { + private void reduceImageSizesForRemoteView(RemoteViews remoteView, Context context, + boolean isLowRam) { if (remoteView != null) { Resources resources = context.getResources(); - int maxWidth = resources.getDimensionPixelSize( - R.dimen.notification_custom_view_max_image_width); - int maxHeight = resources.getDimensionPixelSize( - R.dimen.notification_custom_view_max_image_height); + int maxWidth = resources.getDimensionPixelSize(isLowRam + ? R.dimen.notification_custom_view_max_image_width_low_ram + : R.dimen.notification_custom_view_max_image_width); + int maxHeight = resources.getDimensionPixelSize(isLowRam + ? R.dimen.notification_custom_view_max_image_height_low_ram + : R.dimen.notification_custom_view_max_image_height); remoteView.reduceImageSizes(maxWidth, maxHeight); } } @@ -5629,16 +5617,20 @@ public class Notification implements Parcelable public void reduceImageSizes(Context context) { super.reduceImageSizes(context); Resources resources = context.getResources(); + boolean isLowRam = ActivityManager.isLowRamDeviceStatic(); if (mPicture != null) { - int maxPictureWidth = resources.getDimensionPixelSize( - R.dimen.notification_big_picture_max_height); - int maxPictureHeight = resources.getDimensionPixelSize( - R.dimen.notification_big_picture_max_width); + int maxPictureWidth = resources.getDimensionPixelSize(isLowRam + ? R.dimen.notification_big_picture_max_height_low_ram + : R.dimen.notification_big_picture_max_height); + int maxPictureHeight = resources.getDimensionPixelSize(isLowRam + ? R.dimen.notification_big_picture_max_width_low_ram + : R.dimen.notification_big_picture_max_width); mPicture = Icon.scaleDownIfNecessary(mPicture, maxPictureWidth, maxPictureHeight); } if (mBigLargeIcon != null) { - int rightIconSize = resources.getDimensionPixelSize( - R.dimen.notification_right_icon_size); + int rightIconSize = resources.getDimensionPixelSize(isLowRam + ? R.dimen.notification_right_icon_size_low_ram + : R.dimen.notification_right_icon_size); mBigLargeIcon.scaleDownIfNecessary(rightIconSize, rightIconSize); } } @@ -5666,7 +5658,8 @@ public class Notification implements Parcelable RemoteViews contentView = getStandardView(mBuilder.getBigPictureLayoutResource()); if (mSummaryTextSet) { - contentView.setTextViewText(R.id.text, mBuilder.processLegacyText(mSummaryText)); + contentView.setTextViewText(R.id.text, mBuilder.processTextSpans( + mBuilder.processLegacyText(mSummaryText))); mBuilder.setTextViewColorSecondary(contentView, R.id.text); contentView.setViewVisibility(R.id.text, View.VISIBLE); } @@ -5848,7 +5841,7 @@ public class Notification implements Parcelable static void applyBigTextContentView(Builder builder, RemoteViews contentView, CharSequence bigTextText) { - contentView.setTextViewText(R.id.big_text, bigTextText); + contentView.setTextViewText(R.id.big_text, builder.processTextSpans(bigTextText)); builder.setTextViewColorSecondary(contentView, R.id.big_text); contentView.setViewVisibility(R.id.big_text, TextUtils.isEmpty(bigTextText) ? View.GONE : View.VISIBLE); @@ -6183,7 +6176,8 @@ public class Notification implements Parcelable int rowId = rowIds[i]; contentView.setViewVisibility(rowId, View.VISIBLE); - contentView.setTextViewText(rowId, makeMessageLine(m, mBuilder)); + contentView.setTextViewText(rowId, mBuilder.processTextSpans( + makeMessageLine(m, mBuilder))); mBuilder.setTextViewColorSecondary(contentView, rowId); if (contractedMessage == m) { @@ -6549,7 +6543,8 @@ public class Notification implements Parcelable CharSequence str = mTexts.get(i); if (!TextUtils.isEmpty(str)) { contentView.setViewVisibility(rowIds[i], View.VISIBLE); - contentView.setTextViewText(rowIds[i], mBuilder.processLegacyText(str)); + contentView.setTextViewText(rowIds[i], + mBuilder.processTextSpans(mBuilder.processLegacyText(str))); mBuilder.setTextViewColorSecondary(contentView, rowIds[i]); contentView.setViewPadding(rowIds[i], 0, topPadding, 0, 0); handleInboxImageMargin(contentView, rowIds[i], first); @@ -6935,6 +6930,7 @@ public class Notification implements Parcelable customContent = customContent.clone(); remoteViews.removeAllViewsExceptId(R.id.notification_main_column, R.id.progress); remoteViews.addView(R.id.notification_main_column, customContent, 0 /* index */); + remoteViews.setReapplyDisallowed(); } // also update the end margin if there is an image int endMargin = R.dimen.notification_content_margin_end; @@ -7039,8 +7035,10 @@ public class Notification implements Parcelable // Need to clone customContent before adding, because otherwise it can no longer be // parceled independently of remoteViews. customContent = customContent.clone(); + customContent.overrideTextColors(mBuilder.getPrimaryTextColor()); remoteViews.removeAllViews(id); remoteViews.addView(id, customContent); + remoteViews.setReapplyDisallowed(); } return remoteViews; } diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java index 7e8f191acdb9..18ad9cf3d8e3 100644 --- a/core/java/android/app/NotificationChannelGroup.java +++ b/core/java/android/app/NotificationChannelGroup.java @@ -15,24 +15,18 @@ */ package android.app; -import android.annotation.StringRes; import android.annotation.SystemApi; import android.content.Intent; -import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; -import android.service.notification.NotificationListenerService; import android.text.TextUtils; -import android.util.Slog; import org.json.JSONException; import org.json.JSONObject; -import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlSerializer; import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; /** @@ -115,10 +109,8 @@ public final class NotificationChannelGroup implements Parcelable { return mName; } - /* + /** * Returns the list of channels that belong to this group - * - * @hide */ public List<NotificationChannel> getChannels() { return mChannels; diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index 595ecd201e57..fb11272d7e62 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -964,7 +964,7 @@ public class ResourcesManager { // TODO(adamlesinski): Make this accept more than just overlay directories. final void applyNewResourceDirsLocked(@NonNull final String baseCodePath, - @NonNull final String[] newResourceDirs) { + @Nullable final String[] newResourceDirs) { try { Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "ResourcesManager#applyNewResourceDirsLocked"); diff --git a/core/java/android/app/SharedElementCallback.java b/core/java/android/app/SharedElementCallback.java index bac84a4fcc9d..af13e695108f 100644 --- a/core/java/android/app/SharedElementCallback.java +++ b/core/java/android/app/SharedElementCallback.java @@ -18,6 +18,7 @@ package android.app; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; +import android.graphics.GraphicBuffer; import android.graphics.Matrix; import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; @@ -44,6 +45,8 @@ import java.util.Map; public abstract class SharedElementCallback { private Matrix mTempMatrix; private static final String BUNDLE_SNAPSHOT_BITMAP = "sharedElement:snapshot:bitmap"; + private static final String BUNDLE_SNAPSHOT_GRAPHIC_BUFFER = + "sharedElement:snapshot:graphicBuffer"; private static final String BUNDLE_SNAPSHOT_IMAGE_SCALETYPE = "sharedElement:snapshot:imageScaleType"; private static final String BUNDLE_SNAPSHOT_IMAGE_MATRIX = "sharedElement:snapshot:imageMatrix"; @@ -176,7 +179,12 @@ public abstract class SharedElementCallback { Bitmap bitmap = TransitionUtils.createDrawableBitmap(d); if (bitmap != null) { Bundle bundle = new Bundle(); - bundle.putParcelable(BUNDLE_SNAPSHOT_BITMAP, bitmap); + if (bitmap.getConfig() != Bitmap.Config.HARDWARE) { + bundle.putParcelable(BUNDLE_SNAPSHOT_BITMAP, bitmap); + } else { + GraphicBuffer graphicBuffer = bitmap.createGraphicBufferHandle(); + bundle.putParcelable(BUNDLE_SNAPSHOT_GRAPHIC_BUFFER, graphicBuffer); + } bundle.putString(BUNDLE_SNAPSHOT_IMAGE_SCALETYPE, imageView.getScaleType().toString()); if (imageView.getScaleType() == ScaleType.MATRIX) { @@ -218,10 +226,14 @@ public abstract class SharedElementCallback { View view = null; if (snapshot instanceof Bundle) { Bundle bundle = (Bundle) snapshot; - Bitmap bitmap = (Bitmap) bundle.getParcelable(BUNDLE_SNAPSHOT_BITMAP); - if (bitmap == null) { + GraphicBuffer buffer = bundle.getParcelable(BUNDLE_SNAPSHOT_GRAPHIC_BUFFER); + Bitmap bitmap = bundle.getParcelable(BUNDLE_SNAPSHOT_BITMAP); + if (buffer == null && bitmap == null) { return null; } + if (bitmap == null) { + bitmap = Bitmap.createHardwareBitmap(buffer); + } ImageView imageView = new ImageView(context); view = imageView; imageView.setImageBitmap(bitmap); diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java index b40c96c6f0c8..363e20a76a1f 100644 --- a/core/java/android/app/VrManager.java +++ b/core/java/android/app/VrManager.java @@ -1,13 +1,18 @@ package android.app; - +import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; -import android.content.ComponentName; import android.content.Context; +import android.os.Handler; import android.os.RemoteException; +import android.service.vr.IPersistentVrStateCallbacks; import android.service.vr.IVrManager; +import android.service.vr.IVrStateCallbacks; +import android.util.ArrayMap; + +import java.util.Map; /** * Used to control aspects of a devices Virtual Reality (VR) capabilities. @@ -16,7 +21,33 @@ import android.service.vr.IVrManager; @SystemApi @SystemService(Context.VR_SERVICE) public class VrManager { + + private static class CallbackEntry { + final IVrStateCallbacks mStateCallback = new IVrStateCallbacks.Stub() { + @Override + public void onVrStateChanged(boolean enabled) { + mHandler.post(() -> mCallback.onVrStateChanged(enabled)); + } + + }; + final IPersistentVrStateCallbacks mPersistentStateCallback = + new IPersistentVrStateCallbacks.Stub() { + @Override + public void onPersistentVrStateChanged(boolean enabled) { + mHandler.post(() -> mCallback.onPersistentVrStateChanged(enabled)); + } + }; + final VrStateCallback mCallback; + final Handler mHandler; + + CallbackEntry(VrStateCallback callback, Handler handler) { + mCallback = callback; + mHandler = handler; + } + } + private final IVrManager mService; + private Map<VrStateCallback, CallbackEntry> mCallbackMap = new ArrayMap<>(); /** * {@hide} @@ -26,6 +57,84 @@ public class VrManager { } /** + * Registers a callback to be notified of changes to the VR Mode state. + * + * @param callback The callback to register. + * @hide + */ + @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) + public void registerVrStateCallback(VrStateCallback callback, @NonNull Handler handler) { + if (callback == null || mCallbackMap.containsKey(callback)) { + return; + } + + CallbackEntry entry = new CallbackEntry(callback, handler); + mCallbackMap.put(callback, entry); + try { + mService.registerListener(entry.mStateCallback); + mService.registerPersistentVrStateListener(entry.mPersistentStateCallback); + } catch (RemoteException e) { + try { + unregisterVrStateCallback(callback); + } catch (Exception ignore) { + e.rethrowFromSystemServer(); + } + } + } + + /** + * Deregisters VR State callbacks. + * + * @param callback The callback to deregister. + * @hide + */ + @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) + public void unregisterVrStateCallback(VrStateCallback callback) { + CallbackEntry entry = mCallbackMap.remove(callback); + if (entry != null) { + try { + mService.unregisterListener(entry.mStateCallback); + } catch (RemoteException ignore) { + // Dont rethrow exceptions from requests to unregister. + } + + try { + mService.unregisterPersistentVrStateListener(entry.mPersistentStateCallback); + } catch (RemoteException ignore) { + // Dont rethrow exceptions from requests to unregister. + } + } + } + + /** + * Returns the current VrMode state. + * @hide + */ + @RequiresPermission(android.Manifest.permission.ACCESS_VR_STATE) + public boolean getVrModeEnabled() { + try { + return mService.getVrModeState(); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + return false; + } + + /** + * Returns the current VrMode state. + * @hide + */ + @RequiresPermission(android.Manifest.permission.ACCESS_VR_STATE) + public boolean getPersistentVrModeEnabled() { + try { + return mService.getPersistentVrModeEnabled(); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + return false; + } + + /** * Sets the persistent VR mode state of a device. When a device is in persistent VR mode it will * remain in VR mode even if the foreground does not specify Vr mode being enabled. Mainly used * by VR viewers to indicate that a device is placed in a VR viewer. diff --git a/core/java/android/app/VrStateCallback.java b/core/java/android/app/VrStateCallback.java new file mode 100644 index 000000000000..742faa06fd1d --- /dev/null +++ b/core/java/android/app/VrStateCallback.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.app; + +/** + * Listens to VR Mode state changes. Use with methods in {@link VrManager}. + * + * @hide + */ +public abstract class VrStateCallback { + + /** + * Callback triggered when there is a change to Persistent VR State. + * + * @param enabled True when VR State is in persistent mode, false otherwise. + */ + public void onPersistentVrStateChanged(boolean enabled) {} + + /** + * Callback triggered when there is a change to Vr State. + * + * @param enabled True when VR State is in VR mode, false otherwise. + */ + public void onVrStateChanged(boolean enabled) {} +} diff --git a/core/java/android/app/WallpaperColors.java b/core/java/android/app/WallpaperColors.java index 2a8130f1bd5e..a2864b9d83af 100644 --- a/core/java/android/app/WallpaperColors.java +++ b/core/java/android/app/WallpaperColors.java @@ -49,7 +49,7 @@ public final class WallpaperColors implements Parcelable { * eg. A launcher may set its text color to black if this flag is specified. * @hide */ - public static final int HINT_SUPPORTS_DARK_TEXT = 0x1; + public static final int HINT_SUPPORTS_DARK_TEXT = 1 << 0; /** * Specifies that dark theme is preferred over the current wallpaper for best presentation. @@ -57,7 +57,13 @@ public final class WallpaperColors implements Parcelable { * eg. A launcher may set its drawer color to black if this flag is specified. * @hide */ - public static final int HINT_SUPPORTS_DARK_THEME = 0x2; + public static final int HINT_SUPPORTS_DARK_THEME = 1 << 1; + + /** + * Specifies that this object was generated by extracting colors from a bitmap. + * @hide + */ + public static final int HINT_FROM_BITMAP = 1 << 2; // Maximum size that a bitmap can have to keep our calculations sane private static final int MAX_BITMAP_SIZE = 112; @@ -180,13 +186,13 @@ public final class WallpaperColors implements Parcelable { } } - int hints = calculateHints(bitmap); + int hints = calculateDarkHints(bitmap); if (shouldRecycle) { bitmap.recycle(); } - return new WallpaperColors(primary, secondary, tertiary, hints); + return new WallpaperColors(primary, secondary, tertiary, HINT_FROM_BITMAP | hints); } /** @@ -348,7 +354,7 @@ public final class WallpaperColors implements Parcelable { * @param source What to read. * @return Whether image supports dark text or not. */ - private static int calculateHints(Bitmap source) { + private static int calculateDarkHints(Bitmap source) { if (source == null) { return 0; } diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 16d02149cc0d..942cc99585ed 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -59,6 +59,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; import android.os.UserHandle; +import android.service.wallpaper.WallpaperService; import android.text.TextUtils; import android.util.Log; import android.util.Pair; @@ -855,16 +856,6 @@ public class WallpaperManager { /** * Registers a listener to get notified when the wallpaper colors change. - * Callback might be called from an arbitrary background thread. - * - * @param listener A listener to register - */ - public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener) { - addOnColorsChangedListener(listener, null); - } - - /** - * Registers a listener to get notified when the wallpaper colors change * @param listener A listener to register * @param handler Where to call it from. Will be called from the main thread * if null. @@ -907,10 +898,16 @@ public class WallpaperManager { } /** - * Get the primary colors of a wallpaper - * @param which wallpaper type. Must be either {@link #FLAG_SYSTEM} or - * {@link #FLAG_LOCK} - * @return {@link WallpaperColors} or null if colors are unknown. + * Get the primary colors of a wallpaper. + * + * <p>You can expect null if: + * • Colors are still being processed by the system. + * • A live wallpaper doesn't implement {@link WallpaperService.Engine#onComputeColors()}. + * + * @param which Wallpaper type. Must be either {@link #FLAG_SYSTEM} or + * {@link #FLAG_LOCK}. + * @return Current {@link WallpaperColors} or null if colors are unknown. + * @see #addOnColorsChangedListener(OnColorsChangedListener, Handler) */ public @Nullable WallpaperColors getWallpaperColors(int which) { return getWallpaperColors(which, mContext.getUserId()); @@ -1606,11 +1603,12 @@ public class WallpaperManager { /** * Clear the wallpaper for a specific user. The caller must hold the * INTERACT_ACROSS_USERS_FULL permission to clear another user's - * wallpaper. + * wallpaper, and must hold the SET_WALLPAPER permission in all + * circumstances. * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.SET_WALLPAPER) + @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public void clearWallpaper(@SetWallpaperFlags int which, int userId) { if (sGlobals.mService == null) { Log.w(TAG, "WallpaperService not running"); diff --git a/core/java/android/app/WindowConfiguration.aidl b/core/java/android/app/WindowConfiguration.aidl new file mode 100644 index 000000000000..1a70f524b278 --- /dev/null +++ b/core/java/android/app/WindowConfiguration.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.app; + +parcelable WindowConfiguration; diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java new file mode 100644 index 000000000000..187237d240f3 --- /dev/null +++ b/core/java/android/app/WindowConfiguration.java @@ -0,0 +1,441 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.content.res.Configuration; +import android.graphics.Rect; +import android.os.Parcel; +import android.os.Parcelable; +import android.view.DisplayInfo; + +/** + * Class that contains windowing configuration/state for other objects that contain windows directly + * or indirectly. E.g. Activities, Task, Displays, ... + * The test class is {@link com.android.server.wm.WindowConfigurationTests} which must be kept + * up-to-date and ran anytime changes are made to this class. + * @hide + */ +public class WindowConfiguration implements Parcelable, Comparable<WindowConfiguration> { + + /** + * {@link android.graphics.Rect} defining app bounds. The dimensions override usages of + * {@link DisplayInfo#appHeight} and {@link DisplayInfo#appWidth} and mirrors these values at + * the display level. Lower levels can override these values to provide custom bounds to enforce + * features such as a max aspect ratio. + */ + private Rect mAppBounds; + + /** The current windowing mode of the configuration. */ + private @WindowingMode int mWindowingMode; + + /** Windowing mode is currently not defined. */ + public static final int WINDOWING_MODE_UNDEFINED = 0; + /** Occupies the full area of the screen or the parent container. */ + public static final int WINDOWING_MODE_FULLSCREEN = 1; + /** Always on-top (always visible). of other siblings in its parent container. */ + public static final int WINDOWING_MODE_PINNED = 2; + /** Occupies a dedicated region of the screen or its parent container. */ + public static final int WINDOWING_MODE_DOCKED = 3; + /** Can be freely resized within its parent container. */ + public static final int WINDOWING_MODE_FREEFORM = 4; + + @IntDef({ + WINDOWING_MODE_UNDEFINED, + WINDOWING_MODE_FULLSCREEN, + WINDOWING_MODE_PINNED, + WINDOWING_MODE_DOCKED, + WINDOWING_MODE_FREEFORM, + }) + public @interface WindowingMode {} + + /** The current activity type of the configuration. */ + private @ActivityType int mActivityType; + + /** Activity type is currently not defined. */ + public static final int ACTIVITY_TYPE_UNDEFINED = 0; + /** Standard activity type. Nothing special about the activity... */ + public static final int ACTIVITY_TYPE_STANDARD = 1; + /** Home/Launcher activity type. */ + public static final int ACTIVITY_TYPE_HOME = 2; + /** Recents/Overview activity type. */ + public static final int ACTIVITY_TYPE_RECENTS = 3; + /** Assistant activity type. */ + public static final int ACTIVITY_TYPE_ASSISTANT = 4; + + @IntDef({ + ACTIVITY_TYPE_UNDEFINED, + ACTIVITY_TYPE_STANDARD, + ACTIVITY_TYPE_HOME, + ACTIVITY_TYPE_RECENTS, + ACTIVITY_TYPE_ASSISTANT, + }) + public @interface ActivityType {} + + /** Bit that indicates that the {@link #mAppBounds} changed. */ + public static final int WINDOW_CONFIG_APP_BOUNDS = 1 << 0; + /** Bit that indicates that the {@link #mWindowingMode} changed. */ + public static final int WINDOW_CONFIG_WINDOWING_MODE = 1 << 1; + /** Bit that indicates that the {@link #mActivityType} changed. */ + public static final int WINDOW_CONFIG_ACTIVITY_TYPE = 1 << 2; + + @IntDef(flag = true, + value = { + WINDOW_CONFIG_APP_BOUNDS, + WINDOW_CONFIG_WINDOWING_MODE, + WINDOW_CONFIG_ACTIVITY_TYPE, + }) + public @interface WindowConfig {} + + public WindowConfiguration() { + unset(); + } + + public WindowConfiguration(WindowConfiguration configuration) { + setTo(configuration); + } + + private WindowConfiguration(Parcel in) { + readFromParcel(in); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(mAppBounds, flags); + dest.writeInt(mWindowingMode); + dest.writeInt(mActivityType); + } + + private void readFromParcel(Parcel source) { + mAppBounds = source.readParcelable(Rect.class.getClassLoader()); + mWindowingMode = source.readInt(); + mActivityType = source.readInt(); + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator<WindowConfiguration> CREATOR = new Creator<WindowConfiguration>() { + @Override + public WindowConfiguration createFromParcel(Parcel in) { + return new WindowConfiguration(in); + } + + @Override + public WindowConfiguration[] newArray(int size) { + return new WindowConfiguration[size]; + } + }; + + /** + * Set {@link #mAppBounds} to the input Rect. + * @param rect The rect value to set {@link #mAppBounds} to. + * @see #getAppBounds() + */ + public void setAppBounds(Rect rect) { + if (rect == null) { + mAppBounds = null; + return; + } + + setAppBounds(rect.left, rect.top, rect.right, rect.bottom); + } + + /** + * @see #setAppBounds(Rect) + * @see #getAppBounds() + */ + public void setAppBounds(int left, int top, int right, int bottom) { + if (mAppBounds == null) { + mAppBounds = new Rect(); + } + + mAppBounds.set(left, top, right, bottom); + } + + /** + * @see #setAppBounds(Rect) + */ + public Rect getAppBounds() { + return mAppBounds; + } + + public void setWindowingMode(@WindowingMode int windowingMode) { + mWindowingMode = windowingMode; + } + + @WindowingMode + public int getWindowingMode() { + return mWindowingMode; + } + + public void setActivityType(@ActivityType int activityType) { + if (mActivityType == activityType) { + return; + } + if (mActivityType != ACTIVITY_TYPE_UNDEFINED + && activityType != ACTIVITY_TYPE_UNDEFINED) { + throw new IllegalStateException("Can't change activity type once set: " + this + + " activityType=" + activityTypeToString(activityType)); + } + mActivityType = activityType; + } + + @ActivityType + public int getActivityType() { + return mActivityType; + } + + public void setTo(WindowConfiguration other) { + setAppBounds(other.mAppBounds); + setWindowingMode(other.mWindowingMode); + setActivityType(other.mActivityType); + } + + /** Set this object to completely undefined. */ + public void unset() { + setToDefaults(); + } + + public void setToDefaults() { + setAppBounds(null); + setWindowingMode(WINDOWING_MODE_UNDEFINED); + setActivityType(ACTIVITY_TYPE_UNDEFINED); + } + + /** + * Copies the fields from delta into this Configuration object, keeping + * track of which ones have changed. Any undefined fields in {@code delta} + * are ignored and not copied in to the current Configuration. + * + * @return a bit mask of the changed fields, as per {@link #diff} + */ + public @WindowConfig int updateFrom(@NonNull WindowConfiguration delta) { + int changed = 0; + if (delta.mAppBounds != null && !delta.mAppBounds.equals(mAppBounds)) { + changed |= WINDOW_CONFIG_APP_BOUNDS; + setAppBounds(delta.mAppBounds); + } + if (delta.mWindowingMode != WINDOWING_MODE_UNDEFINED + && mWindowingMode != delta.mWindowingMode) { + changed |= WINDOW_CONFIG_WINDOWING_MODE; + setWindowingMode(delta.mWindowingMode); + } + if (delta.mActivityType != ACTIVITY_TYPE_UNDEFINED + && mActivityType != delta.mActivityType) { + changed |= WINDOW_CONFIG_ACTIVITY_TYPE; + setActivityType(delta.mActivityType); + } + return changed; + } + + /** + * Return a bit mask of the differences between this Configuration object and the given one. + * Does not change the values of either. Any undefined fields in <var>other</var> are ignored. + * @param other The configuration to diff against. + * @param compareUndefined If undefined values should be compared. + * @return Returns a bit mask indicating which configuration + * values has changed, containing any combination of {@link WindowConfig} flags. + * + * @see Configuration#diff(Configuration) + */ + public @WindowConfig long diff(WindowConfiguration other, boolean compareUndefined) { + long changes = 0; + + // Make sure that one of the values is not null and that they are not equal. + if ((compareUndefined || other.mAppBounds != null) + && mAppBounds != other.mAppBounds + && (mAppBounds == null || !mAppBounds.equals(other.mAppBounds))) { + changes |= WINDOW_CONFIG_APP_BOUNDS; + } + + if ((compareUndefined || other.mWindowingMode != WINDOWING_MODE_UNDEFINED) + && mWindowingMode != other.mWindowingMode) { + changes |= WINDOW_CONFIG_WINDOWING_MODE; + } + + if ((compareUndefined || other.mActivityType != ACTIVITY_TYPE_UNDEFINED) + && mActivityType != other.mActivityType) { + changes |= WINDOW_CONFIG_ACTIVITY_TYPE; + } + + return changes; + } + + @Override + public int compareTo(WindowConfiguration that) { + int n = 0; + if (mAppBounds == null && that.mAppBounds != null) { + return 1; + } else if (mAppBounds != null && that.mAppBounds == null) { + return -1; + } else if (mAppBounds != null && that.mAppBounds != null) { + n = mAppBounds.left - that.mAppBounds.left; + if (n != 0) return n; + n = mAppBounds.top - that.mAppBounds.top; + if (n != 0) return n; + n = mAppBounds.right - that.mAppBounds.right; + if (n != 0) return n; + n = mAppBounds.bottom - that.mAppBounds.bottom; + if (n != 0) return n; + } + n = mWindowingMode - that.mWindowingMode; + if (n != 0) return n; + n = mActivityType - that.mActivityType; + if (n != 0) return n; + + // if (n != 0) return n; + return n; + } + + @Override + public boolean equals(Object that) { + if (that == null) return false; + if (that == this) return true; + if (!(that instanceof WindowConfiguration)) { + return false; + } + return this.compareTo((WindowConfiguration) that) == 0; + } + + @Override + public int hashCode() { + int result = 0; + if (mAppBounds != null) { + result = 31 * result + mAppBounds.hashCode(); + } + result = 31 * result + mWindowingMode; + result = 31 * result + mActivityType; + return result; + } + + @Override + public String toString() { + return "{mAppBounds=" + mAppBounds + + " mWindowingMode=" + windowingModeToString(mWindowingMode) + + " mActivityType=" + activityTypeToString(mActivityType) + "}"; + } + + /** + * Returns true if the activities associated with this window configuration display a shadow + * around their border. + */ + public boolean hasWindowShadow() { + return tasksAreFloating(); + } + + /** + * Returns true if the activities associated with this window configuration display a decor + * view. + */ + public boolean hasWindowDecorCaption() { + return mWindowingMode == WINDOWING_MODE_FREEFORM; + } + + /** + * Returns true if the tasks associated with this window configuration can be resized + * independently of their parent container. + */ + public boolean canResizeTask() { + return mWindowingMode == WINDOWING_MODE_FREEFORM; + } + + /** Returns true if the task bounds should persist across power cycles. */ + public boolean persistTaskBounds() { + return mWindowingMode == WINDOWING_MODE_FREEFORM; + } + + /** + * Returns true if the tasks associated with this window configuration are floating. + * Floating tasks are laid out differently as they are allowed to extend past the display bounds + * without overscan insets. + */ + public boolean tasksAreFloating() { + return mWindowingMode == WINDOWING_MODE_FREEFORM || mWindowingMode == WINDOWING_MODE_PINNED; + } + + /** + * Returns true if the windows associated with this window configuration can receive input keys. + */ + public boolean canReceiveKeys() { + return mWindowingMode != WINDOWING_MODE_PINNED; + } + + /** + * Returns true if the container associated with this window configuration is always-on-top of + * its siblings. + */ + public boolean isAlwaysOnTop() { + return mWindowingMode == WINDOWING_MODE_PINNED; + } + + /** + * Returns true if any visible windows belonging to apps with this window configuration should + * be kept on screen when the app is killed due to something like the low memory killer. + */ + public boolean keepVisibleDeadAppWindowOnScreen() { + return mWindowingMode != WINDOWING_MODE_PINNED; + } + + /** + * Returns true if the backdrop on the client side should match the frame of the window. + * Returns false, if the backdrop should be fullscreen. + */ + public boolean useWindowFrameForBackdrop() { + return mWindowingMode == WINDOWING_MODE_FREEFORM || mWindowingMode == WINDOWING_MODE_PINNED; + } + + /** + * Returns true if this container may be scaled without resizing, and windows within may need + * to be configured as such. + */ + public boolean windowsAreScaleable() { + return mWindowingMode == WINDOWING_MODE_PINNED; + } + + /** + * Returns true if windows in this container should be given move animations by default. + */ + public boolean hasMovementAnimations() { + return mWindowingMode == WINDOWING_MODE_PINNED; + } + + private static String windowingModeToString(@WindowingMode int windowingMode) { + switch (windowingMode) { + case WINDOWING_MODE_UNDEFINED: return "undefined"; + case WINDOWING_MODE_FULLSCREEN: return "fullscreen"; + case WINDOWING_MODE_PINNED: return "pinned"; + case WINDOWING_MODE_DOCKED: return "docked"; + case WINDOWING_MODE_FREEFORM: return "freeform"; + } + return String.valueOf(windowingMode); + } + + public static String activityTypeToString(@ActivityType int applicationType) { + switch (applicationType) { + case ACTIVITY_TYPE_UNDEFINED: return "undefined"; + case ACTIVITY_TYPE_STANDARD: return "standard"; + case ACTIVITY_TYPE_HOME: return "home"; + case ACTIVITY_TYPE_RECENTS: return "recents"; + case ACTIVITY_TYPE_ASSISTANT: return "assistant"; + } + return String.valueOf(applicationType); + } +} diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index b0c985010830..d6ef97b545e6 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -39,6 +39,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; +import android.content.pm.IPackageDataObserver; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ParceledListSlice; @@ -47,6 +48,7 @@ import android.graphics.Bitmap; import android.net.ProxyInfo; import android.net.Uri; import android.os.Bundle; +import android.os.Handler; import android.os.Parcelable; import android.os.PersistableBundle; import android.os.Process; @@ -2707,13 +2709,14 @@ public class DevicePolicyManager { } /** - * Flag for {@link #resetPassword}: don't allow other admins to change - * the password again until the user has entered it. + * Flag for {@link #resetPasswordWithToken} and {@link #resetPassword}: don't allow other admins + * to change the password again until the user has entered it. */ public static final int RESET_PASSWORD_REQUIRE_ENTRY = 0x0001; /** - * Flag for {@link #resetPassword}: don't ask for user credentials on device boot. + * Flag for {@link #resetPasswordWithToken} and {@link #resetPassword}: don't ask for user + * credentials on device boot. * If the flag is set, the device can be booted without asking for user password. * The absence of this flag does not change the current boot requirements. This flag * can be set by the device owner only. If the app is not the device owner, the flag @@ -2723,8 +2726,8 @@ public class DevicePolicyManager { public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 0x0002; /** - * Force a new device unlock password (the password needed to access the entire device, not for - * individual accounts) on the user. This takes effect immediately. + * Force a new password for device unlock (the password needed to access the entire device) or + * the work profile challenge on the current user. This takes effect immediately. * <p> * <em>For device owner and profile owners targeting SDK level * {@link android.os.Build.VERSION_CODES#O} or above, this API is no longer available and will @@ -2762,7 +2765,6 @@ public class DevicePolicyManager { * @throws SecurityException if the calling application does not own an active administrator * that uses {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} * @throws IllegalStateException if the calling user is locked or has a managed profile. - * @throws IllegalArgumentException if the password does not meet system requirements. */ public boolean resetPassword(String password, int flags) { throwIfParentInstance("resetPassword"); @@ -2804,8 +2806,8 @@ public class DevicePolicyManager { * @param token a secure token a least 32-byte long, which must be generated by a * cryptographically strong random number generator. * @return true if the operation is successful, false otherwise. + * @throws SecurityException if admin is not a device or profile owner. * @throws IllegalArgumentException if the supplied token is invalid. - * @throws SecurityException */ public boolean setResetPasswordToken(ComponentName admin, byte[] token) { throwIfParentInstance("setResetPasswordToken"); @@ -2824,6 +2826,7 @@ public class DevicePolicyManager { * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @return true if the operation is successful, false otherwise. + * @throws SecurityException if admin is not a device or profile owner. */ public boolean clearResetPasswordToken(ComponentName admin) { throwIfParentInstance("clearResetPasswordToken"); @@ -2842,6 +2845,7 @@ public class DevicePolicyManager { * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @return true if the token is active, false otherwise. + * @throws SecurityException if admin is not a device or profile owner. * @throws IllegalStateException if no token has been set. */ public boolean isResetPasswordTokenActive(ComponentName admin) { @@ -2867,24 +2871,23 @@ public class DevicePolicyManager { * The given password must be sufficient for the current password quality and length constraints * as returned by {@link #getPasswordQuality(ComponentName)} and * {@link #getPasswordMinimumLength(ComponentName)}; if it does not meet these constraints, then - * it will be rejected and false returned. Note that the password may be a stronger quality - * (containing alphanumeric characters when the requested quality is only numeric), in which - * case the currently active quality will be increased to match. + * it will be rejected and false returned. Note that the password may be a stronger quality, for + * example, a password containing alphanumeric characters when the requested quality is only + * numeric. * <p> - * Calling with a null or empty password will clear any existing PIN, pattern or password if the - * current password constraints allow it. + * Calling with a {@code null} or empty password will clear any existing PIN, pattern or + * password if the current password constraints allow it. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @param password The new password for the user. Null or empty clears the password. - * @param token the password reset token previously provisioned by #setResetPasswordToken. + * @param password The new password for the user. {@code null} or empty clears the password. + * @param token the password reset token previously provisioned by + * {@link #setResetPasswordToken}. * @param flags May be 0 or combination of {@link #RESET_PASSWORD_REQUIRE_ENTRY} and - * {@link #RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT}. + * {@link #RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT}. * @return Returns true if the password was applied, or false if it is not acceptable for the * current constraints. - * @throws SecurityException if the calling application does not own an active administrator - * that uses {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} + * @throws SecurityException if admin is not a device or profile owner. * @throws IllegalStateException if the provided token is not valid. - * @throws IllegalArgumentException if the password does not meet system requirements. */ public boolean resetPasswordWithToken(@NonNull ComponentName admin, String password, byte[] token, int flags) { @@ -3938,7 +3941,7 @@ public class DevicePolicyManager { * {@link android.Manifest.permission#BIND_VPN_SERVICE};</li> * <li>target {@link android.os.Build.VERSION_CODES#N API 24} or above; and</li> * <li><i>not</i> explicitly opt out of the feature through - * {@link android.net.VpnService#METADATA_SUPPORTS_ALWAYS_ON}.</li> + * {@link android.net.VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON}.</li> * </ul> * The call will fail if called with the package name of an unsupported VPN app. * @@ -8128,4 +8131,51 @@ public class DevicePolicyManager { throw re.rethrowFromSystemServer(); } } + + /** + * Called by the device owner or profile owner to clear application user data of a given + * package. The behaviour of this is equivalent to the target application calling + * {@link android.app.ActivityManager#clearApplicationUserData()}. + * + * <p><strong>Note:</strong> an application can store data outside of its application data, e.g. + * external storage or user dictionary. This data will not be wiped by calling this API. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param packageName The name of the package which will have its user data wiped. + * @param listener A callback object that will inform the caller when the clearing is done. + * @param handler The handler indicating the thread on which the listener should be invoked. + * @throws SecurityException if the caller is not the device owner/profile owner. + * @return whether the clearing succeeded. + */ + public boolean clearApplicationUserData(@NonNull ComponentName admin, + @NonNull String packageName, @NonNull OnClearApplicationUserDataListener listener, + @NonNull Handler handler) { + throwIfParentInstance("clearAppData"); + try { + return mService.clearApplicationUserData(admin, packageName, + new IPackageDataObserver.Stub() { + public void onRemoveCompleted(String pkg, boolean succeeded) { + handler.post(() -> + listener.onApplicationUserDataCleared(pkg, succeeded)); + } + }); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** + * Callback used in {@link #clearApplicationUserData} + * to indicate that the clearing of an application's user data is done. + */ + public interface OnClearApplicationUserDataListener { + /** + * Method invoked when clearing the application user data has completed. + * + * @param packageName The name of the package which had its user data cleared. + * @param succeeded Whether the clearing succeeded. Clearing fails for device administrator + * apps and protected system packages. + */ + void onApplicationUserDataCleared(String packageName, boolean succeeded); + } } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index e361d819ac2d..acfb602834ef 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -26,6 +26,7 @@ import android.app.admin.PasswordMetrics; import android.content.ComponentName; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.IPackageDataObserver; import android.content.pm.ParceledListSlice; import android.content.pm.StringParceledListSlice; import android.graphics.Bitmap; @@ -355,4 +356,6 @@ interface IDevicePolicyManager { boolean isCurrentInputMethodSetByOwner(); StringParceledListSlice getOwnerInstalledCaCerts(in UserHandle user); + + boolean clearApplicationUserData(in ComponentName admin, in String packageName, in IPackageDataObserver callback); } diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java index 3670b914ecf3..222e9a0e5e0c 100644 --- a/core/java/android/app/usage/NetworkStats.java +++ b/core/java/android/app/usage/NetworkStats.java @@ -97,12 +97,12 @@ public final class NetworkStats implements AutoCloseable { private NetworkStatsHistory.Entry mRecycledHistoryEntry = null; /** @hide */ - NetworkStats(Context context, NetworkTemplate template, long startTimestamp, + NetworkStats(Context context, NetworkTemplate template, int flags, long startTimestamp, long endTimestamp) throws RemoteException, SecurityException { final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface( ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); // Open network stats session - mSession = statsService.openSessionForUsageStats(context.getOpPackageName()); + mSession = statsService.openSessionForUsageStats(flags, context.getOpPackageName()); mCloseGuard.open("close"); mTemplate = template; mStartTimeStamp = startTimestamp; diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index ef262e046021..853b00331a4d 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -24,15 +24,14 @@ import android.app.usage.NetworkStats.Bucket; import android.content.Context; import android.net.ConnectivityManager; import android.net.DataUsageRequest; +import android.net.INetworkStatsService; import android.net.NetworkIdentity; import android.net.NetworkTemplate; -import android.net.INetworkStatsService; import android.os.Binder; -import android.os.Build; -import android.os.Message; -import android.os.Messenger; import android.os.Handler; import android.os.Looper; +import android.os.Message; +import android.os.Messenger; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; @@ -79,7 +78,7 @@ import android.util.Log; * In addition to tethering usage, usage by removed users and apps, and usage by the system * is also included in the results for callers with one of these higher levels of access. * <p /> - * <b>NOTE:</b> Prior to API level {@value Build.VERSION_CODES#N}, all calls to these APIs required + * <b>NOTE:</b> Prior to API level {@value android.os.Build.VERSION_CODES#N}, all calls to these APIs required * the above permission, even to access an app's own data usage, and carrier-privileged apps were * not included. */ @@ -96,6 +95,13 @@ public class NetworkStatsManager { private final Context mContext; private final INetworkStatsService mService; + /** @hide */ + public static final int FLAG_POLL_ON_OPEN = 1 << 0; + /** @hide */ + public static final int FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN = 1 << 1; + + private int mFlags; + /** * {@hide} */ @@ -103,6 +109,25 @@ public class NetworkStatsManager { mContext = context; mService = INetworkStatsService.Stub.asInterface( ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE)); + setPollOnOpen(true); + } + + /** @hide */ + public void setPollOnOpen(boolean pollOnOpen) { + if (pollOnOpen) { + mFlags |= FLAG_POLL_ON_OPEN; + } else { + mFlags &= ~FLAG_POLL_ON_OPEN; + } + } + + /** @hide */ + public void setAugmentWithSubscriptionPlan(boolean augmentWithSubscriptionPlan) { + if (augmentWithSubscriptionPlan) { + mFlags |= FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN; + } else { + mFlags &= ~FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN; + } } /** @@ -136,7 +161,7 @@ public class NetworkStatsManager { } Bucket bucket = null; - NetworkStats stats = new NetworkStats(mContext, template, startTime, endTime); + NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime); bucket = stats.getDeviceSummaryForNetwork(); stats.close(); @@ -174,7 +199,7 @@ public class NetworkStatsManager { } NetworkStats stats; - stats = new NetworkStats(mContext, template, startTime, endTime); + stats = new NetworkStats(mContext, template, mFlags, startTime, endTime); stats.startSummaryEnumeration(); stats.close(); @@ -211,7 +236,7 @@ public class NetworkStatsManager { } NetworkStats result; - result = new NetworkStats(mContext, template, startTime, endTime); + result = new NetworkStats(mContext, template, mFlags, startTime, endTime); result.startSummaryEnumeration(); return result; @@ -260,7 +285,7 @@ public class NetworkStatsManager { NetworkStats result; try { - result = new NetworkStats(mContext, template, startTime, endTime); + result = new NetworkStats(mContext, template, mFlags, startTime, endTime); result.startHistoryEnumeration(uid, tag); } catch (RemoteException e) { Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag, e); @@ -305,7 +330,7 @@ public class NetworkStatsManager { } NetworkStats result; - result = new NetworkStats(mContext, template, startTime, endTime); + result = new NetworkStats(mContext, template, mFlags, startTime, endTime); result.startUserUidEnumeration(); return result; } diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java index 1242cb0fbdfa..8a1eae2da976 100644 --- a/core/java/android/appwidget/AppWidgetHostView.java +++ b/core/java/android/appwidget/AppWidgetHostView.java @@ -40,7 +40,6 @@ import android.util.SparseArray; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.Adapter; import android.widget.AdapterView; @@ -469,7 +468,9 @@ public class AppWidgetHostView extends FrameLayout { // We've already done this -- nothing to do. return ; } - Log.w(TAG, "updateAppWidget couldn't find any view, using error view", exception); + if (exception != null) { + Log.w(TAG, "Error inflating RemoteViews : " + exception.toString()); + } content = getErrorView(); mViewMode = VIEW_MODE_ERROR; } diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java index c58eaa14ed82..7841b83cf92c 100644 --- a/core/java/android/bluetooth/BluetoothA2dp.java +++ b/core/java/android/bluetooth/BluetoothA2dp.java @@ -42,7 +42,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; * This class provides the public APIs to control the Bluetooth A2DP * profile. * - *<p>BluetoothA2dp is a proxy object for controlling the Bluetooth A2DP + * <p>BluetoothA2dp is a proxy object for controlling the Bluetooth A2DP * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get * the BluetoothA2dp proxy object. * @@ -60,9 +60,9 @@ public final class BluetoothA2dp implements BluetoothProfile { * * <p>This intent will have 3 extras: * <ul> - * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> - * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> * </ul> * * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of @@ -74,7 +74,7 @@ public final class BluetoothA2dp implements BluetoothProfile { */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CONNECTION_STATE_CHANGED = - "android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED"; + "android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED"; /** * Intent used to broadcast the change in the Playing state of the A2DP @@ -82,9 +82,9 @@ public final class BluetoothA2dp implements BluetoothProfile { * * <p>This intent will have 3 extras: * <ul> - * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> - * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> * </ul> * * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of @@ -95,12 +95,12 @@ public final class BluetoothA2dp implements BluetoothProfile { */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PLAYING_STATE_CHANGED = - "android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED"; + "android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED"; /** @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_AVRCP_CONNECTION_STATE_CHANGED = - "android.bluetooth.a2dp.profile.action.AVRCP_CONNECTION_STATE_CHANGED"; + "android.bluetooth.a2dp.profile.action.AVRCP_CONNECTION_STATE_CHANGED"; /** * Intent used to broadcast the change in the Audio Codec state of the @@ -108,9 +108,9 @@ public final class BluetoothA2dp implements BluetoothProfile { * * <p>This intent will have 2 extras: * <ul> - * <li> {@link BluetoothCodecStatus#EXTRA_CODEC_STATUS} - The codec status. </li> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device if the device is currently - * connected, otherwise it is not included.</li> + * <li> {@link BluetoothCodecStatus#EXTRA_CODEC_STATUS} - The codec status. </li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device if the device is currently + * connected, otherwise it is not included.</li> * </ul> * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to @@ -120,61 +120,74 @@ public final class BluetoothA2dp implements BluetoothProfile { */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CODEC_CONFIG_CHANGED = - "android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED"; + "android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED"; /** * A2DP sink device is streaming music. This state can be one of * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of * {@link #ACTION_PLAYING_STATE_CHANGED} intent. */ - public static final int STATE_PLAYING = 10; + public static final int STATE_PLAYING = 10; /** * A2DP sink device is NOT streaming music. This state can be one of * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of * {@link #ACTION_PLAYING_STATE_CHANGED} intent. */ - public static final int STATE_NOT_PLAYING = 11; + public static final int STATE_NOT_PLAYING = 11; /** * We don't have a stored preference for whether or not the given A2DP sink device supports * optional codecs. - * @hide */ + * + * @hide + */ public static final int OPTIONAL_CODECS_SUPPORT_UNKNOWN = -1; /** * The given A2DP sink device does not support optional codecs. - * @hide */ + * + * @hide + */ public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0; /** * The given A2DP sink device does support optional codecs. - * @hide */ + * + * @hide + */ public static final int OPTIONAL_CODECS_SUPPORTED = 1; /** * We don't have a stored preference for whether optional codecs should be enabled or disabled * for the given A2DP device. - * @hide */ + * + * @hide + */ public static final int OPTIONAL_CODECS_PREF_UNKNOWN = -1; /** * Optional codecs should be disabled for the given A2DP device. - * @hide */ + * + * @hide + */ public static final int OPTIONAL_CODECS_PREF_DISABLED = 0; /** - * Optional codecs should be enabled for the given A2DP device. - * @hide */ + * Optional codecs should be enabled for the given A2DP device. + * + * @hide + */ public static final int OPTIONAL_CODECS_PREF_ENABLED = 1; private Context mContext; private ServiceListener mServiceListener; private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock(); - @GuardedBy("mServiceLock") private IBluetoothA2dp mService; + @GuardedBy("mServiceLock") + private IBluetoothA2dp mService; private BluetoothAdapter mAdapter; - final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { public void onBluetoothStateChange(boolean up) { if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); @@ -193,21 +206,21 @@ public final class BluetoothA2dp implements BluetoothProfile { try { mServiceLock.readLock().lock(); if (mService == null) { - if (VDBG) Log.d(TAG,"Binding service..."); + if (VDBG) Log.d(TAG, "Binding service..."); doBind(); } } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } finally { mServiceLock.readLock().unlock(); } } } - }; + }; + /** * Create a BluetoothA2dp proxy object for interacting with the local * Bluetooth A2DP service. - * */ /*package*/ BluetoothA2dp(Context context, ServiceListener l) { mContext = context; @@ -218,7 +231,7 @@ public final class BluetoothA2dp implements BluetoothProfile { try { mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -244,7 +257,7 @@ public final class BluetoothA2dp implements BluetoothProfile { try { mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); } catch (Exception e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -261,10 +274,12 @@ public final class BluetoothA2dp implements BluetoothProfile { } } + @Override public void finalize() { // The empty finalize needs to be kept or the // cts signature tests would fail. } + /** * Initiate connection to a profile of the remote bluetooth device. * @@ -283,16 +298,14 @@ public final class BluetoothA2dp implements BluetoothProfile { * permission. * * @param device Remote Bluetooth Device - * @return false on immediate error, - * true otherwise + * @return false on immediate error, true otherwise * @hide */ public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); try { mServiceLock.readLock().lock(); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { return mService.connect(device); } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -327,16 +340,14 @@ public final class BluetoothA2dp implements BluetoothProfile { * permission. * * @param device Remote Bluetooth Device - * @return false on immediate error, - * true otherwise + * @return false on immediate error, true otherwise * @hide */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); try { mServiceLock.readLock().lock(); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { return mService.disconnect(device); } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -352,6 +363,7 @@ public final class BluetoothA2dp implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); try { @@ -372,6 +384,7 @@ public final class BluetoothA2dp implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); try { @@ -392,12 +405,13 @@ public final class BluetoothA2dp implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getState(" + device + ")"); try { mServiceLock.readLock().lock(); if (mService != null && isEnabled() - && isValidDevice(device)) { + && isValidDevice(device)) { return mService.getConnectionState(device); } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -414,7 +428,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * Set priority of the profile * * <p> The device should already be paired. - * Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager + * Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager * {@link #PRIORITY_OFF}, * * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} @@ -430,9 +444,9 @@ public final class BluetoothA2dp implements BluetoothProfile { try { mServiceLock.readLock().lock(); if (mService != null && isEnabled() - && isValidDevice(device)) { - if (priority != BluetoothProfile.PRIORITY_OFF && - priority != BluetoothProfile.PRIORITY_ON) { + && isValidDevice(device)) { + if (priority != BluetoothProfile.PRIORITY_OFF + && priority != BluetoothProfile.PRIORITY_ON) { return false; } return mService.setPriority(device, priority); @@ -464,7 +478,7 @@ public final class BluetoothA2dp implements BluetoothProfile { try { mServiceLock.readLock().lock(); if (mService != null && isEnabled() - && isValidDevice(device)) { + && isValidDevice(device)) { return mService.getPriority(device); } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -560,7 +574,7 @@ public final class BluetoothA2dp implements BluetoothProfile { try { mServiceLock.readLock().lock(); if (mService != null && isEnabled() - && isValidDevice(device)) { + && isValidDevice(device)) { return mService.isA2dpPlaying(device); } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -577,6 +591,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * This function checks if the remote device is an AVCRP * target and thus whether we should send volume keys * changes or not. + * * @hide */ public boolean shouldSendVolumeKeys(BluetoothDevice device) { @@ -584,7 +599,7 @@ public final class BluetoothA2dp implements BluetoothProfile { ParcelUuid[] uuids = device.getUuids(); if (uuids == null) return false; - for (ParcelUuid uuid: uuids) { + for (ParcelUuid uuid : uuids) { if (BluetoothUuid.isAvrcpTarget(uuid)) { return true; } @@ -691,8 +706,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * * @param device The device to check * @return one of OPTIONAL_CODECS_SUPPORT_UNKNOWN, OPTIONAL_CODECS_NOT_SUPPORTED, or - * OPTIONAL_CODECS_SUPPORTED. - * + * OPTIONAL_CODECS_SUPPORTED. * @hide */ public int supportsOptionalCodecs(BluetoothDevice device) { @@ -716,8 +730,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * * @param device The device in question. * @return one of OPTIONAL_CODECS_PREF_UNKNOWN, OPTIONAL_CODECS_PREF_ENABLED, or - * OPTIONAL_CODECS_PREF_DISABLED. - * + * OPTIONAL_CODECS_PREF_DISABLED. * @hide */ public int getOptionalCodecsEnabled(BluetoothDevice device) { @@ -741,15 +754,15 @@ public final class BluetoothA2dp implements BluetoothProfile { * * @param device The device to set this preference for. * @param value Whether the optional codecs should be enabled for this device. This should be - * one of OPTIONAL_CODECS_PREF_UNKNOWN, OPTIONAL_CODECS_PREF_ENABLED, or - * OPTIONAL_CODECS_PREF_DISABLED. + * one of OPTIONAL_CODECS_PREF_UNKNOWN, OPTIONAL_CODECS_PREF_ENABLED, or + * OPTIONAL_CODECS_PREF_DISABLED. * @hide */ public void setOptionalCodecsEnabled(BluetoothDevice device, int value) { try { - if (value != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN && - value != BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED && - value != BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED) { + if (value != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN + && value != BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED + && value != BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED) { Log.e(TAG, "Invalid value passed to setOptionalCodecsEnabled: " + value); return; } @@ -772,24 +785,25 @@ public final class BluetoothA2dp implements BluetoothProfile { * Helper for converting a state to a string. * * For debug use only - strings are not internationalized. + * * @hide */ public static String stateToString(int state) { switch (state) { - case STATE_DISCONNECTED: - return "disconnected"; - case STATE_CONNECTING: - return "connecting"; - case STATE_CONNECTED: - return "connected"; - case STATE_DISCONNECTING: - return "disconnecting"; - case STATE_PLAYING: - return "playing"; - case STATE_NOT_PLAYING: - return "not playing"; - default: - return "<unknown state " + state + ">"; + case STATE_DISCONNECTED: + return "disconnected"; + case STATE_CONNECTING: + return "connecting"; + case STATE_CONNECTED: + return "connected"; + case STATE_DISCONNECTING: + return "disconnecting"; + case STATE_PLAYING: + return "playing"; + case STATE_NOT_PLAYING: + return "not playing"; + default: + return "<unknown state " + state + ">"; } } @@ -807,6 +821,7 @@ public final class BluetoothA2dp implements BluetoothProfile { mServiceListener.onServiceConnected(BluetoothProfile.A2DP, BluetoothA2dp.this); } } + public void onServiceDisconnected(ComponentName className) { if (DBG) Log.d(TAG, "Proxy object disconnected"); try { @@ -822,18 +837,18 @@ public final class BluetoothA2dp implements BluetoothProfile { }; private boolean isEnabled() { - if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; - return false; + if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; + return false; } private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; + if (device == null) return false; - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; + return false; } private static void log(String msg) { - Log.d(TAG, msg); + Log.d(TAG, msg); } } diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java index 9dfc4b442fa4..611531c4f7c4 100755 --- a/core/java/android/bluetooth/BluetoothA2dpSink.java +++ b/core/java/android/bluetooth/BluetoothA2dpSink.java @@ -32,7 +32,7 @@ import java.util.List; * This class provides the public APIs to control the Bluetooth A2DP Sink * profile. * - *<p>BluetoothA2dpSink is a proxy object for controlling the Bluetooth A2DP Sink + * <p>BluetoothA2dpSink is a proxy object for controlling the Bluetooth A2DP Sink * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get * the BluetoothA2dpSink proxy object. * @@ -49,9 +49,9 @@ public final class BluetoothA2dpSink implements BluetoothProfile { * * <p>This intent will have 3 extras: * <ul> - * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> - * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> * </ul> * * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of @@ -62,7 +62,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile { * receive. */ public static final String ACTION_CONNECTION_STATE_CHANGED = - "android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED"; + "android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED"; /** * Intent used to broadcast the change in the Playing state of the A2DP Sink @@ -70,9 +70,9 @@ public final class BluetoothA2dpSink implements BluetoothProfile { * * <p>This intent will have 3 extras: * <ul> - * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> - * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> * </ul> * * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of @@ -82,21 +82,21 @@ public final class BluetoothA2dpSink implements BluetoothProfile { * receive. */ public static final String ACTION_PLAYING_STATE_CHANGED = - "android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED"; + "android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED"; /** * A2DP sink device is streaming music. This state can be one of * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of * {@link #ACTION_PLAYING_STATE_CHANGED} intent. */ - public static final int STATE_PLAYING = 10; + public static final int STATE_PLAYING = 10; /** * A2DP sink device is NOT streaming music. This state can be one of * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of * {@link #ACTION_PLAYING_STATE_CHANGED} intent. */ - public static final int STATE_NOT_PLAYING = 11; + public static final int STATE_NOT_PLAYING = 11; /** * Intent used to broadcast the change in the Playing state of the A2DP Sink @@ -104,15 +104,15 @@ public final class BluetoothA2dpSink implements BluetoothProfile { * * <p>This intent will have 3 extras: * <ul> - * <li> {@link #EXTRA_AUDIO_CONFIG} - The audio configuration for the remote device. </li> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * <li> {@link #EXTRA_AUDIO_CONFIG} - The audio configuration for the remote device. </li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> * </ul> * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to * receive. */ public static final String ACTION_AUDIO_CONFIG_CHANGED = - "android.bluetooth.a2dp-sink.profile.action.AUDIO_CONFIG_CHANGED"; + "android.bluetooth.a2dp-sink.profile.action.AUDIO_CONFIG_CHANGED"; /** * Extra for the {@link #ACTION_AUDIO_CONFIG_CHANGED} intent. @@ -120,46 +120,46 @@ public final class BluetoothA2dpSink implements BluetoothProfile { * This extra represents the current audio configuration of the A2DP source device. * {@see BluetoothAudioConfig} */ - public static final String EXTRA_AUDIO_CONFIG - = "android.bluetooth.a2dp-sink.profile.extra.AUDIO_CONFIG"; + public static final String EXTRA_AUDIO_CONFIG = + "android.bluetooth.a2dp-sink.profile.extra.AUDIO_CONFIG"; private Context mContext; private ServiceListener mServiceListener; private IBluetoothA2dpSink mService; private BluetoothAdapter mAdapter; - final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { public void onBluetoothStateChange(boolean up) { if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); if (!up) { - if (VDBG) Log.d(TAG,"Unbinding service..."); + if (VDBG) Log.d(TAG, "Unbinding service..."); synchronized (mConnection) { try { mService = null; mContext.unbindService(mConnection); } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } else { synchronized (mConnection) { try { if (mService == null) { - if (VDBG) Log.d(TAG,"Binding service..."); + if (VDBG) Log.d(TAG, "Binding service..."); doBind(); } } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } } - }; + }; + /** * Create a BluetoothA2dp proxy object for interacting with the local * Bluetooth A2DP service. - * */ /*package*/ BluetoothA2dpSink(Context context, ServiceListener l) { mContext = context; @@ -170,7 +170,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile { try { mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -196,7 +196,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile { try { mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); } catch (Exception e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -206,15 +206,17 @@ public final class BluetoothA2dpSink implements BluetoothProfile { mService = null; mContext.unbindService(mConnection); } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } } + @Override public void finalize() { close(); } + /** * Initiate connection to a profile of the remote bluetooth device. * @@ -233,14 +235,12 @@ public final class BluetoothA2dpSink implements BluetoothProfile { * permission. * * @param device Remote Bluetooth Device - * @return false on immediate error, - * true otherwise + * @return false on immediate error, true otherwise * @hide */ public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.connect(device); } catch (RemoteException e) { @@ -274,14 +274,12 @@ public final class BluetoothA2dpSink implements BluetoothProfile { * permission. * * @param device Remote Bluetooth Device - * @return false on immediate error, - * true otherwise + * @return false on immediate error, true otherwise * @hide */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.disconnect(device); } catch (RemoteException e) { @@ -296,6 +294,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); if (mService != null && isEnabled()) { @@ -313,6 +312,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); if (mService != null && isEnabled()) { @@ -330,10 +330,11 @@ public final class BluetoothA2dpSink implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getState(" + device + ")"); if (mService != null && isEnabled() - && isValidDevice(device)) { + && isValidDevice(device)) { try { return mService.getConnectionState(device); } catch (RemoteException e) { @@ -356,10 +357,10 @@ public final class BluetoothA2dpSink implements BluetoothProfile { * * {@see BluetoothAudioConfig} */ - public BluetoothAudioConfig getAudioConfig(BluetoothDevice device) { + public BluetoothAudioConfig getAudioConfig(BluetoothDevice device) { if (VDBG) log("getAudioConfig(" + device + ")"); if (mService != null && isEnabled() - && isValidDevice(device)) { + && isValidDevice(device)) { try { return mService.getAudioConfig(device); } catch (RemoteException e) { @@ -375,7 +376,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile { * Set priority of the profile * * <p> The device should already be paired. - * Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager + * Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager * {@link #PRIORITY_OFF}, * * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} @@ -389,20 +390,20 @@ public final class BluetoothA2dpSink implements BluetoothProfile { public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); if (mService != null && isEnabled() - && isValidDevice(device)) { - if (priority != BluetoothProfile.PRIORITY_OFF && - priority != BluetoothProfile.PRIORITY_ON){ + && isValidDevice(device)) { + if (priority != BluetoothProfile.PRIORITY_OFF + && priority != BluetoothProfile.PRIORITY_ON) { return false; } try { return mService.setPriority(device, priority); } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return false; } /** @@ -421,7 +422,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile { public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); if (mService != null && isEnabled() - && isValidDevice(device)) { + && isValidDevice(device)) { try { return mService.getPriority(device); } catch (RemoteException e) { @@ -442,7 +443,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile { */ public boolean isA2dpPlaying(BluetoothDevice device) { if (mService != null && isEnabled() - && isValidDevice(device)) { + && isValidDevice(device)) { try { return mService.isA2dpPlaying(device); } catch (RemoteException e) { @@ -458,24 +459,25 @@ public final class BluetoothA2dpSink implements BluetoothProfile { * Helper for converting a state to a string. * * For debug use only - strings are not internationalized. + * * @hide */ public static String stateToString(int state) { switch (state) { - case STATE_DISCONNECTED: - return "disconnected"; - case STATE_CONNECTING: - return "connecting"; - case STATE_CONNECTED: - return "connected"; - case STATE_DISCONNECTING: - return "disconnecting"; - case STATE_PLAYING: - return "playing"; - case STATE_NOT_PLAYING: - return "not playing"; - default: - return "<unknown state " + state + ">"; + case STATE_DISCONNECTED: + return "disconnected"; + case STATE_CONNECTING: + return "connecting"; + case STATE_CONNECTED: + return "connected"; + case STATE_DISCONNECTING: + return "disconnecting"; + case STATE_PLAYING: + return "playing"; + case STATE_NOT_PLAYING: + return "not playing"; + default: + return "<unknown state " + state + ">"; } } @@ -489,6 +491,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile { BluetoothA2dpSink.this); } } + public void onServiceDisconnected(ComponentName className) { if (DBG) Log.d(TAG, "Proxy object disconnected"); mService = null; @@ -499,18 +502,18 @@ public final class BluetoothA2dpSink implements BluetoothProfile { }; private boolean isEnabled() { - if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; - return false; + if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; + return false; } private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; + if (device == null) return false; - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; + return false; } private static void log(String msg) { - Log.d(TAG, msg); + Log.d(TAG, msg); } } diff --git a/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java b/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java index 84f6060d3aed..43b79db6f355 100644 --- a/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java +++ b/core/java/android/bluetooth/BluetoothActivityEnergyInfo.java @@ -25,6 +25,7 @@ import java.util.Arrays; * Record of energy and activity information from controller and * underlying bt stack state.Timestamp the record with system * time + * * @hide */ public final class BluetoothActivityEnergyInfo implements Parcelable { @@ -42,7 +43,7 @@ public final class BluetoothActivityEnergyInfo implements Parcelable { public static final int BT_STACK_STATE_STATE_IDLE = 3; public BluetoothActivityEnergyInfo(long timestamp, int stackState, - long txTime, long rxTime, long idleTime, long energyUsed) { + long txTime, long rxTime, long idleTime, long energyUsed) { mTimestamp = timestamp; mBluetoothStackState = stackState; mControllerTxTimeMs = txTime; @@ -65,27 +66,29 @@ public final class BluetoothActivityEnergyInfo implements Parcelable { @Override public String toString() { return "BluetoothActivityEnergyInfo{" - + " mTimestamp=" + mTimestamp - + " mBluetoothStackState=" + mBluetoothStackState - + " mControllerTxTimeMs=" + mControllerTxTimeMs - + " mControllerRxTimeMs=" + mControllerRxTimeMs - + " mControllerIdleTimeMs=" + mControllerIdleTimeMs - + " mControllerEnergyUsed=" + mControllerEnergyUsed - + " mUidTraffic=" + Arrays.toString(mUidTraffic) - + " }"; + + " mTimestamp=" + mTimestamp + + " mBluetoothStackState=" + mBluetoothStackState + + " mControllerTxTimeMs=" + mControllerTxTimeMs + + " mControllerRxTimeMs=" + mControllerRxTimeMs + + " mControllerIdleTimeMs=" + mControllerIdleTimeMs + + " mControllerEnergyUsed=" + mControllerEnergyUsed + + " mUidTraffic=" + Arrays.toString(mUidTraffic) + + " }"; } public static final Parcelable.Creator<BluetoothActivityEnergyInfo> CREATOR = new Parcelable.Creator<BluetoothActivityEnergyInfo>() { - public BluetoothActivityEnergyInfo createFromParcel(Parcel in) { - return new BluetoothActivityEnergyInfo(in); - } + public BluetoothActivityEnergyInfo createFromParcel(Parcel in) { + return new BluetoothActivityEnergyInfo(in); + } + + public BluetoothActivityEnergyInfo[] newArray(int size) { + return new BluetoothActivityEnergyInfo[size]; + } + }; - public BluetoothActivityEnergyInfo[] newArray(int size) { - return new BluetoothActivityEnergyInfo[size]; - } - }; + @Override @SuppressWarnings("unchecked") public void writeToParcel(Parcel out, int flags) { out.writeLong(mTimestamp); @@ -97,6 +100,7 @@ public final class BluetoothActivityEnergyInfo implements Parcelable { out.writeTypedArray(mUidTraffic, flags); } + @Override public int describeContents() { return 0; } @@ -131,6 +135,7 @@ public final class BluetoothActivityEnergyInfo implements Parcelable { /** * product of current(mA), voltage(V) and time(ms) + * * @return energy used */ public long getControllerEnergyUsed() { @@ -156,8 +161,7 @@ public final class BluetoothActivityEnergyInfo implements Parcelable { * @return if the record is valid */ public boolean isValid() { - return ((mControllerTxTimeMs >=0) && - (mControllerRxTimeMs >=0) && - (mControllerIdleTimeMs >=0)); + return ((mControllerTxTimeMs >= 0) && (mControllerRxTimeMs >= 0) + && (mControllerIdleTimeMs >= 0)); } } diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index fc3a72482a79..70591d4d0587 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -80,7 +80,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; * {@link #getBondedDevices()}; start device discovery with * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to * listen for incoming connection requests with - * {@link #listenUsingRfcommWithServiceRecord(String,UUID)}; or start a scan for + * {@link #listenUsingRfcommWithServiceRecord(String, UUID)}; or start a scan for * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}. * </p> * <p>This class is thread safe.</p> @@ -92,7 +92,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; * <div class="special reference"> * <h3>Developer Guides</h3> * <p> - * For more information about using Bluetooth, read the <a href= + * For more information about using Bluetooth, read the <a href= * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer * guide. * </p> @@ -161,7 +161,8 @@ public final class BluetoothAdapter { @IntDef({STATE_OFF, STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF, STATE_BLE_TURNING_ON, STATE_BLE_ON, STATE_BLE_TURNING_OFF}) @Retention(RetentionPolicy.SOURCE) - public @interface AdapterState {} + public @interface AdapterState { + } /** * Indicates the local Bluetooth adapter is off. @@ -185,36 +186,48 @@ public final class BluetoothAdapter { /** * Indicates the local Bluetooth adapter is turning Bluetooth LE mode on. + * * @hide */ public static final int STATE_BLE_TURNING_ON = 14; /** * Indicates the local Bluetooth adapter is in LE only mode. + * * @hide */ public static final int STATE_BLE_ON = 15; /** * Indicates the local Bluetooth adapter is turning off LE only mode. + * * @hide */ public static final int STATE_BLE_TURNING_OFF = 16; /** * Human-readable string helper for AdapterState + * * @hide */ public static String nameForState(@AdapterState int state) { - switch(state) { - case STATE_OFF: return "OFF"; - case STATE_TURNING_ON: return "TURNING_ON"; - case STATE_ON: return "ON"; - case STATE_TURNING_OFF: return "TURNING_OFF"; - case STATE_BLE_TURNING_ON: return "BLE_TURNING_ON"; - case STATE_BLE_ON: return "BLE_ON"; - case STATE_BLE_TURNING_OFF: return "BLE_TURNING_OFF"; - default: return "?!?!? (" + state + ")"; + switch (state) { + case STATE_OFF: + return "OFF"; + case STATE_TURNING_ON: + return "TURNING_ON"; + case STATE_ON: + return "ON"; + case STATE_TURNING_OFF: + return "TURNING_OFF"; + case STATE_BLE_TURNING_ON: + return "BLE_TURNING_ON"; + case STATE_BLE_ON: + return "BLE_ON"; + case STATE_BLE_TURNING_OFF: + return "BLE_TURNING_OFF"; + default: + return "?!?!? (" + state + ")"; } } @@ -346,7 +359,8 @@ public final class BluetoothAdapter { /** @hide */ @IntDef({SCAN_MODE_NONE, SCAN_MODE_CONNECTABLE, SCAN_MODE_CONNECTABLE_DISCOVERABLE}) @Retention(RetentionPolicy.SOURCE) - public @interface ScanMode {} + public @interface ScanMode { + } /** * Indicates that both inquiry scan and page scan are disabled on the local @@ -439,7 +453,7 @@ public final class BluetoothAdapter { */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CONNECTION_STATE_CHANGED = - "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED"; + "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED"; /** * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED} @@ -447,7 +461,7 @@ public final class BluetoothAdapter { * This extra represents the current connection state. */ public static final String EXTRA_CONNECTION_STATE = - "android.bluetooth.adapter.extra.CONNECTION_STATE"; + "android.bluetooth.adapter.extra.CONNECTION_STATE"; /** * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED} @@ -455,15 +469,16 @@ public final class BluetoothAdapter { * This extra represents the previous connection state. */ public static final String EXTRA_PREVIOUS_CONNECTION_STATE = - "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE"; + "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE"; /** * Broadcast Action: The Bluetooth adapter state has changed in LE only mode. + * * @hide */ @SystemApi public static final String ACTION_BLE_STATE_CHANGED = - "android.bluetooth.adapter.action.BLE_STATE_CHANGED"; + "android.bluetooth.adapter.action.BLE_STATE_CHANGED"; /** * Intent used to broadcast the change in the Bluetooth address @@ -477,7 +492,7 @@ public final class BluetoothAdapter { * @hide */ public static final String ACTION_BLUETOOTH_ADDRESS_CHANGED = - "android.bluetooth.adapter.action.BLUETOOTH_ADDRESS_CHANGED"; + "android.bluetooth.adapter.action.BLUETOOTH_ADDRESS_CHANGED"; /** * Used as a String extra field in {@link @@ -487,7 +502,7 @@ public final class BluetoothAdapter { * @hide */ public static final String EXTRA_BLUETOOTH_ADDRESS = - "android.bluetooth.adapter.extra.BLUETOOTH_ADDRESS"; + "android.bluetooth.adapter.extra.BLUETOOTH_ADDRESS"; /** * Broadcast Action: The notifys Bluetooth ACL connected event. This will be @@ -497,10 +512,11 @@ public final class BluetoothAdapter { * * This is counterpart of {@link BluetoothDevice#ACTION_ACL_CONNECTED} which * works in Bluetooth state STATE_ON + * * @hide */ public static final String ACTION_BLE_ACL_CONNECTED = - "android.bluetooth.adapter.action.BLE_ACL_CONNECTED"; + "android.bluetooth.adapter.action.BLE_ACL_CONNECTED"; /** * Broadcast Action: The notifys Bluetooth ACL connected event. This will be @@ -510,17 +526,18 @@ public final class BluetoothAdapter { * * This is counterpart of {@link BluetoothDevice#ACTION_ACL_DISCONNECTED} which * works in Bluetooth state STATE_ON + * * @hide */ public static final String ACTION_BLE_ACL_DISCONNECTED = - "android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED"; + "android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED"; /** The profile is in disconnected state */ - public static final int STATE_DISCONNECTED = 0; + public static final int STATE_DISCONNECTED = 0; /** The profile is in connecting state */ - public static final int STATE_CONNECTING = 1; + public static final int STATE_CONNECTING = 1; /** The profile is in connected state */ - public static final int STATE_CONNECTED = 2; + public static final int STATE_CONNECTED = 2; /** The profile is in disconnecting state */ public static final int STATE_DISCONNECTING = 3; @@ -529,14 +546,17 @@ public final class BluetoothAdapter { private final IBinder mToken; - /** When creating a ServerSocket using listenUsingRfcommOn() or - * listenUsingL2capOn() use SOCKET_CHANNEL_AUTO_STATIC to create - * a ServerSocket that auto assigns a channel number to the first - * bluetooth socket. - * The channel number assigned to this first Bluetooth Socket will - * be stored in the ServerSocket, and reused for subsequent Bluetooth - * sockets. - * @hide */ + /** + * When creating a ServerSocket using listenUsingRfcommOn() or + * listenUsingL2capOn() use SOCKET_CHANNEL_AUTO_STATIC to create + * a ServerSocket that auto assigns a channel number to the first + * bluetooth socket. + * The channel number assigned to this first Bluetooth Socket will + * be stored in the ServerSocket, and reused for subsequent Bluetooth + * sockets. + * + * @hide + */ public static final int SOCKET_CHANNEL_AUTO_STATIC_NO_SDP = -2; @@ -555,7 +575,7 @@ public final class BluetoothAdapter { private final IBluetoothManager mManagerService; private IBluetooth mService; private final ReentrantReadWriteLock mServiceLock = - new ReentrantReadWriteLock(); + new ReentrantReadWriteLock(); private final Object mLock = new Object(); private final Map<LeScanCallback, ScanCallback> mLeScanClients; @@ -566,8 +586,9 @@ public final class BluetoothAdapter { * could be extended to support more. This will always return the default * adapter. * </p> - * @return the default local adapter, or null if Bluetooth is not supported - * on this hardware platform + * + * @return the default local adapter, or null if Bluetooth is not supported on this hardware + * platform */ public static synchronized BluetoothAdapter getDefaultAdapter() { if (sAdapter == null) { @@ -648,7 +669,7 @@ public final class BluetoothAdapter { */ public BluetoothLeAdvertiser getBluetoothLeAdvertiser() { if (!getLeAccess()) return null; - synchronized(mLock) { + synchronized (mLock) { if (sBluetoothLeAdvertiser == null) { sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService); } @@ -663,22 +684,25 @@ public final class BluetoothAdapter { * <p> * Use {@link #isLePeriodicAdvertisingSupported()} to check whether LE Periodic Advertising is * supported on this device before calling this method. + * * @hide */ public PeriodicAdvertisingManager getPeriodicAdvertisingManager() { - if (!getLeAccess()) - return null; + if (!getLeAccess()) { + return null; + } - if (!isLePeriodicAdvertisingSupported()) - return null; + if (!isLePeriodicAdvertisingSupported()) { + return null; + } - synchronized (mLock) { - if (sPeriodicAdvertisingManager == null) { - sPeriodicAdvertisingManager = - new PeriodicAdvertisingManager(mManagerService); + synchronized (mLock) { + if (sPeriodicAdvertisingManager == null) { + sPeriodicAdvertisingManager = + new PeriodicAdvertisingManager(mManagerService); + } } - } - return sPeriodicAdvertisingManager; + return sPeriodicAdvertisingManager; } /** @@ -686,7 +710,7 @@ public final class BluetoothAdapter { */ public BluetoothLeScanner getBluetoothLeScanner() { if (!getLeAccess()) return null; - synchronized(mLock) { + synchronized (mLock) { if (sBluetoothLeScanner == null) { sBluetoothLeScanner = new BluetoothLeScanner(mManagerService); } @@ -725,9 +749,9 @@ public final class BluetoothAdapter { */ @SystemApi public boolean isLeEnabled() { - final int state = getLeState(); - if (DBG) Log.d(TAG, "isLeEnabled(): " + BluetoothAdapter.nameForState(state)); - return (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON); + final int state = getLeState(); + if (DBG) Log.d(TAG, "isLeEnabled(): " + BluetoothAdapter.nameForState(state)); + return (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON); } /** @@ -752,8 +776,7 @@ public final class BluetoothAdapter { * immediate problem that will prevent the QAdapter from being turned off - * such as the QAadapter already being turned off. * - * @return true to indicate success, or false on - * immediate error + * @return true to indicate success, or false on immediate error * @hide */ @SystemApi @@ -763,7 +786,7 @@ public final class BluetoothAdapter { int state = getLeState(); if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON) { String packageName = ActivityThread.currentPackageName(); - if (DBG) Log.d (TAG, "disableBLE(): de-registering " + packageName); + if (DBG) Log.d(TAG, "disableBLE(): de-registering " + packageName); try { mManagerService.updateBleAppCount(mToken, false, packageName); } catch (RemoteException e) { @@ -772,7 +795,7 @@ public final class BluetoothAdapter { return true; } - if (DBG) Log.d (TAG, "disableBLE(): Already disabled"); + if (DBG) Log.d(TAG, "disableBLE(): Already disabled"); return false; } @@ -804,8 +827,7 @@ public final class BluetoothAdapter { * states, It includes all the classic Bluetooth Adapter states along with * internal BLE only states * - * @return true to indicate Bluetooth LE will be available, or false on - * immediate error + * @return true to indicate Bluetooth LE will be available, or false on immediate error * @hide */ @SystemApi @@ -856,12 +878,19 @@ public final class BluetoothAdapter { // Consider all internal states as OFF if (state == BluetoothAdapter.STATE_BLE_ON - || state == BluetoothAdapter.STATE_BLE_TURNING_ON - || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) { - if (VDBG) Log.d(TAG, "Consider " + BluetoothAdapter.nameForState(state) + " state as OFF"); + || state == BluetoothAdapter.STATE_BLE_TURNING_ON + || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) { + if (VDBG) { + Log.d(TAG, + "Consider " + BluetoothAdapter.nameForState(state) + " state as OFF"); + } state = BluetoothAdapter.STATE_OFF; } - if (VDBG) Log.d(TAG, "" + hashCode() + ": getState(). Returning " + BluetoothAdapter.nameForState(state)); + if (VDBG) { + Log.d(TAG, + "" + hashCode() + ": getState(). Returning " + BluetoothAdapter.nameForState( + state)); + } return state; } @@ -897,16 +926,16 @@ public final class BluetoothAdapter { mServiceLock.readLock().unlock(); } - if (VDBG) Log.d(TAG,"getLeState() returning " + BluetoothAdapter.nameForState(state)); + if (VDBG) Log.d(TAG, "getLeState() returning " + BluetoothAdapter.nameForState(state)); return state; } boolean getLeAccess() { - if (getLeState() == STATE_ON) + if (getLeState() == STATE_ON) { return true; - - else if (getLeState() == STATE_BLE_ON) + } else if (getLeState() == STATE_BLE_ON) { return true; // TODO: FILTER SYSTEM APPS HERE <-- + } return false; } @@ -933,8 +962,7 @@ public final class BluetoothAdapter { * immediate problem that will prevent the adapter from being turned on - * such as Airplane mode, or the adapter is already turned on. * - * @return true to indicate adapter startup has begun, or false on - * immediate error + * @return true to indicate adapter startup has begun, or false on immediate error */ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) public boolean enable() { @@ -944,7 +972,9 @@ public final class BluetoothAdapter { } try { return mManagerService.enable(ActivityThread.currentPackageName()); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return false; } @@ -967,14 +997,15 @@ public final class BluetoothAdapter { * immediate problem that will prevent the adapter from being turned off - * such as the adapter already being turned off. * - * @return true to indicate adapter shutdown has begun, or false on - * immediate error + * @return true to indicate adapter shutdown has begun, or false on immediate error */ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) public boolean disable() { try { return mManagerService.disable(ActivityThread.currentPackageName(), true); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return false; } @@ -984,15 +1015,16 @@ public final class BluetoothAdapter { * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN} * permission * - * @return true to indicate adapter shutdown has begun, or false on - * immediate error + * @return true to indicate adapter shutdown has begun, or false on immediate error * @hide */ public boolean disable(boolean persist) { try { return mManagerService.disable(ActivityThread.currentPackageName(), persist); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return false; } @@ -1006,7 +1038,9 @@ public final class BluetoothAdapter { public String getAddress() { try { return mManagerService.getAddress(); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return null; } @@ -1020,7 +1054,9 @@ public final class BluetoothAdapter { public String getName() { try { return mManagerService.getName(); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return null; } @@ -1031,7 +1067,6 @@ public final class BluetoothAdapter { * permission * * @return true to indicate that the config file was successfully cleared - * * @hide */ public boolean factoryReset() { @@ -1082,7 +1117,7 @@ public final class BluetoothAdapter { * to get the updated value. * * @param name a valid Bluetooth name - * @return true if the name was set, false otherwise + * @return true if the name was set, false otherwise */ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) public boolean setName(String name) { @@ -1151,9 +1186,9 @@ public final class BluetoothAdapter { * </code>instead. * * @param mode valid scan mode - * @param duration time in seconds to apply scan mode, only used for - * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE} - * @return true if the scan mode was set, false otherwise + * @param duration time in seconds to apply scan mode, only used for {@link + * #SCAN_MODE_CONNECTABLE_DISCOVERABLE} + * @return true if the scan mode was set, false otherwise * @hide */ public boolean setScanMode(@ScanMode int mode, int duration) { @@ -1205,9 +1240,10 @@ public final class BluetoothAdapter { /** * Get the end time of the latest remote device discovery process. - * @return the latest time that the bluetooth adapter was/will be in discovery mode, - * in milliseconds since the epoch. - * This time can be in the future if {@link #startDiscovery()} has been called recently. + * + * @return the latest time that the bluetooth adapter was/will be in discovery mode, in + * milliseconds since the epoch. This time can be in the future if {@link #startDiscovery()} has + * been called recently. * @hide */ public long getDiscoveryEndMillis() { @@ -1517,13 +1553,13 @@ public final class BluetoothAdapter { * Return the record of {@link BluetoothActivityEnergyInfo} object that * has the activity and energy info. This can be used to ascertain what * the controller has been up to, since the last sample. - * @param updateType Type of info, cached vs refreshed. * - * @return a record with {@link BluetoothActivityEnergyInfo} or null if - * report is unavailable or unsupported - * @deprecated use the asynchronous - * {@link #requestControllerActivityEnergyInfo(ResultReceiver)} instead. + * @param updateType Type of info, cached vs refreshed. + * @return a record with {@link BluetoothActivityEnergyInfo} or null if report is unavailable or + * unsupported * @hide + * @deprecated use the asynchronous {@link #requestControllerActivityEnergyInfo(ResultReceiver)} + * instead. */ @Deprecated public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) { @@ -1599,11 +1635,11 @@ public final class BluetoothAdapter { /** * Gets the currently supported profiles by the adapter. * - *<p> This can be used to check whether a profile is supported before attempting + * <p> This can be used to check whether a profile is supported before attempting * to connect to its respective proxy. * - * @return a list of integers indicating the ids of supported profiles as defined in - * {@link BluetoothProfile}. + * @return a list of integers indicating the ids of supported profiles as defined in {@link + * BluetoothProfile}. * @hide */ public List<Integer> getSupportedProfiles() { @@ -1622,7 +1658,7 @@ public final class BluetoothAdapter { } } } catch (RemoteException e) { - Log.e(TAG, "getSupportedProfiles:", e); + Log.e(TAG, "getSupportedProfiles:", e); } return supportedProfiles; } @@ -1635,9 +1671,8 @@ public final class BluetoothAdapter { * <p> Use this function along with {@link #ACTION_CONNECTION_STATE_CHANGED} * intent to get the connection state of the adapter. * - * @return One of {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTED}, - * {@link #STATE_CONNECTING} or {@link #STATE_DISCONNECTED} - * + * @return One of {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTED}, {@link + * #STATE_CONNECTING} or {@link #STATE_DISCONNECTED} * @hide */ public int getConnectionState() { @@ -1688,10 +1723,11 @@ public final class BluetoothAdapter { * connections from a listening {@link BluetoothServerSocket}. * <p>Valid RFCOMM channels are in range 1 to 30. * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} + * * @param channel RFCOMM channel to listen on * @return a listening RFCOMM BluetoothServerSocket - * @throws IOException on error, for example Bluetooth not available, or - * insufficient permissions, or channel in use. + * @throws IOException on error, for example Bluetooth not available, or insufficient + * permissions, or channel in use. * @hide */ public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException { @@ -1708,12 +1744,14 @@ public final class BluetoothAdapter { * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} * <p>To auto assign a channel without creating a SDP record use * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as channel number. + * * @param channel RFCOMM channel to listen on - * @param mitm enforce man-in-the-middle protection for authentication. - * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2 connections. + * @param mitm enforce man-in-the-middle protection for authentication. + * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2 + * connections. * @return a listening RFCOMM BluetoothServerSocket - * @throws IOException on error, for example Bluetooth not available, or - * insufficient permissions, or channel in use. + * @throws IOException on error, for example Bluetooth not available, or insufficient + * permissions, or channel in use. * @hide */ public BluetoothServerSocket listenUsingRfcommOn(int channel, boolean mitm, @@ -1749,11 +1787,12 @@ public final class BluetoothAdapter { * closed, or if this application closes unexpectedly. * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to * connect to this socket from another device using the same {@link UUID}. + * * @param name service name for SDP record * @param uuid uuid for SDP record * @return a listening RFCOMM BluetoothServerSocket - * @throws IOException on error, for example Bluetooth not available, or - * insufficient permissions, or channel in use. + * @throws IOException on error, for example Bluetooth not available, or insufficient + * permissions, or channel in use. */ @RequiresPermission(Manifest.permission.BLUETOOTH) public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid) @@ -1780,11 +1819,12 @@ public final class BluetoothAdapter { * closed, or if this application closes unexpectedly. * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to * connect to this socket from another device using the same {@link UUID}. + * * @param name service name for SDP record * @param uuid uuid for SDP record * @return a listening RFCOMM BluetoothServerSocket - * @throws IOException on error, for example Bluetooth not available, or - * insufficient permissions, or channel in use. + * @throws IOException on error, for example Bluetooth not available, or insufficient + * permissions, or channel in use. */ @RequiresPermission(Manifest.permission.BLUETOOTH) public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid) @@ -1792,7 +1832,7 @@ public final class BluetoothAdapter { return createNewRfcommSocketAndRecord(name, uuid, false, false); } - /** + /** * Create a listening, encrypted, * RFCOMM Bluetooth socket with Service Record. * <p>The link will be encrypted, but the link key is not required to be authenticated @@ -1818,11 +1858,12 @@ public final class BluetoothAdapter { * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to * connect to this socket from another device using the same {@link UUID}. * <p>Requires {@link android.Manifest.permission#BLUETOOTH} + * * @param name service name for SDP record * @param uuid uuid for SDP record * @return a listening RFCOMM BluetoothServerSocket - * @throws IOException on error, for example Bluetooth not available, or - * insufficient permissions, or channel in use. + * @throws IOException on error, for example Bluetooth not available, or insufficient + * permissions, or channel in use. * @hide */ public BluetoothServerSocket listenUsingEncryptedRfcommWithServiceRecord( @@ -1835,7 +1876,7 @@ public final class BluetoothAdapter { boolean auth, boolean encrypt) throws IOException { BluetoothServerSocket socket; socket = new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, auth, - encrypt, new ParcelUuid(uuid)); + encrypt, new ParcelUuid(uuid)); socket.setServiceName(name); int errno = socket.mSocket.bindListen(); if (errno != 0) { @@ -1850,16 +1891,17 @@ public final class BluetoothAdapter { /** * Construct an unencrypted, unauthenticated, RFCOMM server socket. * Call #accept to retrieve connections to this socket. + * * @return An RFCOMM BluetoothServerSocket - * @throws IOException On error, for example Bluetooth not available, or - * insufficient permissions. + * @throws IOException On error, for example Bluetooth not available, or insufficient + * permissions. * @hide */ public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException { BluetoothServerSocket socket = new BluetoothServerSocket( BluetoothSocket.TYPE_RFCOMM, false, false, port); int errno = socket.mSocket.bindListen(); - if(port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { + if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { socket.setChannel(socket.mSocket.getPort()); } if (errno != 0) { @@ -1871,12 +1913,13 @@ public final class BluetoothAdapter { return socket; } - /** + /** * Construct an encrypted, RFCOMM server socket. * Call #accept to retrieve connections to this socket. + * * @return An RFCOMM BluetoothServerSocket - * @throws IOException On error, for example Bluetooth not available, or - * insufficient permissions. + * @throws IOException On error, for example Bluetooth not available, or insufficient + * permissions. * @hide */ public BluetoothServerSocket listenUsingEncryptedRfcommOn(int port) @@ -1884,7 +1927,7 @@ public final class BluetoothAdapter { BluetoothServerSocket socket = new BluetoothServerSocket( BluetoothSocket.TYPE_RFCOMM, false, true, port); int errno = socket.mSocket.bindListen(); - if(port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { + if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { socket.setChannel(socket.mSocket.getPort()); } if (errno < 0) { @@ -1899,9 +1942,10 @@ public final class BluetoothAdapter { /** * Construct a SCO server socket. * Call #accept to retrieve connections to this socket. + * * @return A SCO BluetoothServerSocket - * @throws IOException On error, for example Bluetooth not available, or - * insufficient permissions. + * @throws IOException On error, for example Bluetooth not available, or insufficient + * permissions. * @hide */ public static BluetoothServerSocket listenUsingScoOn() throws IOException { @@ -1921,12 +1965,14 @@ public final class BluetoothAdapter { * Call #accept to retrieve connections to this socket. * <p>To auto assign a port without creating a SDP record use * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number. - * @param port the PSM to listen on - * @param mitm enforce man-in-the-middle protection for authentication. - * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2 connections. + * + * @param port the PSM to listen on + * @param mitm enforce man-in-the-middle protection for authentication. + * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2 + * connections. * @return An L2CAP BluetoothServerSocket - * @throws IOException On error, for example Bluetooth not available, or - * insufficient permissions. + * @throws IOException On error, for example Bluetooth not available, or insufficient + * permissions. * @hide */ public BluetoothServerSocket listenUsingL2capOn(int port, boolean mitm, boolean min16DigitPin) @@ -1934,7 +1980,7 @@ public final class BluetoothAdapter { BluetoothServerSocket socket = new BluetoothServerSocket( BluetoothSocket.TYPE_L2CAP, true, true, port, mitm, min16DigitPin); int errno = socket.mSocket.bindListen(); - if(port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { + if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { socket.setChannel(socket.mSocket.getPort()); } if (errno != 0) { @@ -1951,10 +1997,11 @@ public final class BluetoothAdapter { * Call #accept to retrieve connections to this socket. * <p>To auto assign a port without creating a SDP record use * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number. - * @param port the PSM to listen on + * + * @param port the PSM to listen on * @return An L2CAP BluetoothServerSocket - * @throws IOException On error, for example Bluetooth not available, or - * insufficient permissions. + * @throws IOException On error, for example Bluetooth not available, or insufficient + * permissions. * @hide */ public BluetoothServerSocket listenUsingL2capOn(int port) throws IOException { @@ -1967,17 +2014,18 @@ public final class BluetoothAdapter { * Call #accept to retrieve connections to this socket. * <p>To auto assign a port without creating a SDP record use * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number. - * @param port the PSM to listen on + * + * @param port the PSM to listen on * @return An L2CAP BluetoothServerSocket - * @throws IOException On error, for example Bluetooth not available, or - * insufficient permissions. + * @throws IOException On error, for example Bluetooth not available, or insufficient + * permissions. * @hide */ public BluetoothServerSocket listenUsingInsecureL2capOn(int port) throws IOException { BluetoothServerSocket socket = new BluetoothServerSocket( BluetoothSocket.TYPE_L2CAP, false, false, port, false, false); int errno = socket.mSocket.bindListen(); - if(port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { + if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { socket.setChannel(socket.mSocket.getPort()); } if (errno != 0) { @@ -1995,7 +2043,6 @@ public final class BluetoothAdapter { * <p>Requires {@link android.Manifest.permission#BLUETOOTH} * * @return Pair<byte[], byte[]> of Hash and Randomizer - * * @hide */ public Pair<byte[], byte[]> readOutOfBandData() { @@ -2013,13 +2060,13 @@ public final class BluetoothAdapter { * * @param context Context of the application * @param listener The service Listener for connection callbacks. - * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEALTH}, - * {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}. - * {@link BluetoothProfile#GATT} or {@link BluetoothProfile#GATT_SERVER}. + * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEALTH}, {@link + * BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}. {@link BluetoothProfile#GATT} or + * {@link BluetoothProfile#GATT_SERVER}. * @return true on success, false on error */ public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener, - int profile) { + int profile) { if (context == null || listener == null) return false; if (profile == BluetoothProfile.HEADSET) { @@ -2082,59 +2129,59 @@ public final class BluetoothAdapter { switch (profile) { case BluetoothProfile.HEADSET: - BluetoothHeadset headset = (BluetoothHeadset)proxy; + BluetoothHeadset headset = (BluetoothHeadset) proxy; headset.close(); break; case BluetoothProfile.A2DP: - BluetoothA2dp a2dp = (BluetoothA2dp)proxy; + BluetoothA2dp a2dp = (BluetoothA2dp) proxy; a2dp.close(); break; case BluetoothProfile.A2DP_SINK: - BluetoothA2dpSink a2dpSink = (BluetoothA2dpSink)proxy; + BluetoothA2dpSink a2dpSink = (BluetoothA2dpSink) proxy; a2dpSink.close(); break; case BluetoothProfile.AVRCP_CONTROLLER: - BluetoothAvrcpController avrcp = (BluetoothAvrcpController)proxy; + BluetoothAvrcpController avrcp = (BluetoothAvrcpController) proxy; avrcp.close(); break; case BluetoothProfile.INPUT_DEVICE: - BluetoothInputDevice iDev = (BluetoothInputDevice)proxy; + BluetoothInputDevice iDev = (BluetoothInputDevice) proxy; iDev.close(); break; case BluetoothProfile.PAN: - BluetoothPan pan = (BluetoothPan)proxy; + BluetoothPan pan = (BluetoothPan) proxy; pan.close(); break; case BluetoothProfile.HEALTH: - BluetoothHealth health = (BluetoothHealth)proxy; + BluetoothHealth health = (BluetoothHealth) proxy; health.close(); break; - case BluetoothProfile.GATT: - BluetoothGatt gatt = (BluetoothGatt)proxy; + case BluetoothProfile.GATT: + BluetoothGatt gatt = (BluetoothGatt) proxy; gatt.close(); break; case BluetoothProfile.GATT_SERVER: - BluetoothGattServer gattServer = (BluetoothGattServer)proxy; + BluetoothGattServer gattServer = (BluetoothGattServer) proxy; gattServer.close(); break; case BluetoothProfile.MAP: - BluetoothMap map = (BluetoothMap)proxy; + BluetoothMap map = (BluetoothMap) proxy; map.close(); break; case BluetoothProfile.HEADSET_CLIENT: - BluetoothHeadsetClient headsetClient = (BluetoothHeadsetClient)proxy; + BluetoothHeadsetClient headsetClient = (BluetoothHeadsetClient) proxy; headsetClient.close(); break; case BluetoothProfile.SAP: - BluetoothSap sap = (BluetoothSap)proxy; + BluetoothSap sap = (BluetoothSap) proxy; sap.close(); break; case BluetoothProfile.PBAP_CLIENT: - BluetoothPbapClient pbapClient = (BluetoothPbapClient)proxy; + BluetoothPbapClient pbapClient = (BluetoothPbapClient) proxy; pbapClient.close(); break; case BluetoothProfile.MAP_CLIENT: - BluetoothMapClient mapClient = (BluetoothMapClient)proxy; + BluetoothMapClient mapClient = (BluetoothMapClient) proxy; mapClient.close(); break; case BluetoothProfile.INPUT_HOST: @@ -2144,76 +2191,79 @@ public final class BluetoothAdapter { } } - final private IBluetoothManagerCallback mManagerCallback = - new IBluetoothManagerCallback.Stub() { - public void onBluetoothServiceUp(IBluetooth bluetoothService) { - if (DBG) Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService); + private final IBluetoothManagerCallback mManagerCallback = + new IBluetoothManagerCallback.Stub() { + public void onBluetoothServiceUp(IBluetooth bluetoothService) { + if (DBG) Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService); - mServiceLock.writeLock().lock(); - mService = bluetoothService; - mServiceLock.writeLock().unlock(); + mServiceLock.writeLock().lock(); + mService = bluetoothService; + mServiceLock.writeLock().unlock(); - synchronized (mProxyServiceStateCallbacks) { - for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ) { - try { - if (cb != null) { - cb.onBluetoothServiceUp(bluetoothService); - } else { - Log.d(TAG, "onBluetoothServiceUp: cb is null!"); + synchronized (mProxyServiceStateCallbacks) { + for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks) { + try { + if (cb != null) { + cb.onBluetoothServiceUp(bluetoothService); + } else { + Log.d(TAG, "onBluetoothServiceUp: cb is null!"); + } + } catch (Exception e) { + Log.e(TAG, "", e); } - } catch (Exception e) { - Log.e(TAG,"",e); } } } - } - public void onBluetoothServiceDown() { - if (DBG) Log.d(TAG, "onBluetoothServiceDown: " + mService); - - try { - mServiceLock.writeLock().lock(); - mService = null; - if (mLeScanClients != null) mLeScanClients.clear(); - if (sBluetoothLeAdvertiser != null) sBluetoothLeAdvertiser.cleanup(); - if (sBluetoothLeScanner != null) sBluetoothLeScanner.cleanup(); - } finally { - mServiceLock.writeLock().unlock(); - } + public void onBluetoothServiceDown() { + if (DBG) Log.d(TAG, "onBluetoothServiceDown: " + mService); + + try { + mServiceLock.writeLock().lock(); + mService = null; + if (mLeScanClients != null) mLeScanClients.clear(); + if (sBluetoothLeAdvertiser != null) sBluetoothLeAdvertiser.cleanup(); + if (sBluetoothLeScanner != null) sBluetoothLeScanner.cleanup(); + } finally { + mServiceLock.writeLock().unlock(); + } - synchronized (mProxyServiceStateCallbacks) { - for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){ - try { - if (cb != null) { - cb.onBluetoothServiceDown(); - } else { - Log.d(TAG, "onBluetoothServiceDown: cb is null!"); + synchronized (mProxyServiceStateCallbacks) { + for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks) { + try { + if (cb != null) { + cb.onBluetoothServiceDown(); + } else { + Log.d(TAG, "onBluetoothServiceDown: cb is null!"); + } + } catch (Exception e) { + Log.e(TAG, "", e); } - } catch (Exception e) { - Log.e(TAG,"",e); } } } - } - public void onBrEdrDown() { - if (VDBG) Log.i(TAG, "onBrEdrDown: " + mService); - } - }; + public void onBrEdrDown() { + if (VDBG) Log.i(TAG, "onBrEdrDown: " + mService); + } + }; /** * Enable the Bluetooth Adapter, but don't auto-connect devices * and don't persist state. Only for use by system applications. + * * @hide */ public boolean enableNoAutoConnect() { - if (isEnabled() == true){ + if (isEnabled()) { if (DBG) Log.d(TAG, "enableNoAutoConnect(): BT already enabled!"); return true; } try { return mManagerService.enableNoAutoConnect(ActivityThread.currentPackageName()); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return false; } @@ -2247,7 +2297,7 @@ public final class BluetoothAdapter { * @hide */ public boolean changeApplicationBluetoothState(boolean on, - BluetoothStateChangeCallback callback) { + BluetoothStateChangeCallback callback) { return false; } @@ -2305,28 +2355,29 @@ public final class BluetoothAdapter { for (int i = 0; i < ADDRESS_LENGTH; i++) { char c = address.charAt(i); switch (i % 3) { - case 0: - case 1: - if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) { - // hex character, OK - break; - } - return false; - case 2: - if (c == ':') { - break; // OK - } - return false; + case 0: + case 1: + if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) { + // hex character, OK + break; + } + return false; + case 2: + if (c == ':') { + break; // OK + } + return false; } } return true; } /*package*/ IBluetoothManager getBluetoothManager() { - return mManagerService; + return mManagerService; } - final private ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks = new ArrayList<IBluetoothManagerCallback>(); + private final ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks = + new ArrayList<IBluetoothManagerCallback>(); /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) { synchronized (mProxyServiceStateCallbacks) { @@ -2357,10 +2408,9 @@ public final class BluetoothAdapter { * by the {@link BluetoothAdapter#startLeScan} function. * * @param device Identifies the remote device - * @param rssi The RSSI value for the remote device as reported by the - * Bluetooth hardware. 0 if no RSSI value is available. - * @param scanRecord The content of the advertisement record offered by - * the remote device. + * @param rssi The RSSI value for the remote device as reported by the Bluetooth hardware. 0 + * if no RSSI value is available. + * @param scanRecord The content of the advertisement record offered by the remote device. */ public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord); } @@ -2374,7 +2424,7 @@ public final class BluetoothAdapter { * @param callback the callback LE scan results are delivered * @return true, if the scan was started successfully * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)} - * instead. + * instead. */ @Deprecated @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) @@ -2393,7 +2443,7 @@ public final class BluetoothAdapter { * @param callback the callback LE scan results are delivered * @return true, if the scan was started successfully * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)} - * instead. + * instead. */ @Deprecated @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) @@ -2409,7 +2459,7 @@ public final class BluetoothAdapter { return false; } - synchronized(mLeScanClients) { + synchronized (mLeScanClients) { if (mLeScanClients.containsKey(callback)) { if (DBG) Log.e(TAG, "LE Scan has already started"); return false; @@ -2450,8 +2500,8 @@ public final class BluetoothAdapter { } }; ScanSettings settings = new ScanSettings.Builder() - .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) - .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(); + .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) + .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(); List<ScanFilter> filters = new ArrayList<ScanFilter>(); if (serviceUuids != null && serviceUuids.length > 0) { @@ -2467,7 +2517,7 @@ public final class BluetoothAdapter { return true; } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } return false; @@ -2476,8 +2526,8 @@ public final class BluetoothAdapter { /** * Stops an ongoing Bluetooth LE device scan. * - * @param callback used to identify which scan to stop - * must be the same handle used to start the scan + * @param callback used to identify which scan to stop must be the same handle used to start the + * scan * @deprecated Use {@link BluetoothLeScanner#stopScan(ScanCallback)} instead. */ @Deprecated diff --git a/core/java/android/bluetooth/BluetoothAssignedNumbers.java b/core/java/android/bluetooth/BluetoothAssignedNumbers.java index 124bdc118d4f..41a34e061845 100644 --- a/core/java/android/bluetooth/BluetoothAssignedNumbers.java +++ b/core/java/android/bluetooth/BluetoothAssignedNumbers.java @@ -20,9 +20,9 @@ package android.bluetooth; * Bluetooth Assigned Numbers. * <p> * For now we only include Company ID values. - * @see <a href="https://www.bluetooth.org/technical/assignednumbers/identifiers.htm"> - * The Official Bluetooth SIG Member Website | Company Identifiers</a> * + * @see <a href="https://www.bluetooth.org/technical/assignednumbers/identifiers.htm"> The Official + * Bluetooth SIG Member Website | Company Identifiers</a> */ public class BluetoothAssignedNumbers { diff --git a/core/java/android/bluetooth/BluetoothAudioConfig.java b/core/java/android/bluetooth/BluetoothAudioConfig.java index 03176b9e0739..a4410563c991 100644 --- a/core/java/android/bluetooth/BluetoothAudioConfig.java +++ b/core/java/android/bluetooth/BluetoothAudioConfig.java @@ -41,10 +41,9 @@ public final class BluetoothAudioConfig implements Parcelable { @Override public boolean equals(Object o) { if (o instanceof BluetoothAudioConfig) { - BluetoothAudioConfig bac = (BluetoothAudioConfig)o; - return (bac.mSampleRate == mSampleRate && - bac.mChannelConfig == mChannelConfig && - bac.mAudioFormat == mAudioFormat); + BluetoothAudioConfig bac = (BluetoothAudioConfig) o; + return (bac.mSampleRate == mSampleRate && bac.mChannelConfig == mChannelConfig + && bac.mAudioFormat == mAudioFormat); } return false; } @@ -60,23 +59,26 @@ public final class BluetoothAudioConfig implements Parcelable { + ",mAudioFormat:" + mAudioFormat + "}"; } + @Override public int describeContents() { return 0; } public static final Parcelable.Creator<BluetoothAudioConfig> CREATOR = new Parcelable.Creator<BluetoothAudioConfig>() { - public BluetoothAudioConfig createFromParcel(Parcel in) { - int sampleRate = in.readInt(); - int channelConfig = in.readInt(); - int audioFormat = in.readInt(); - return new BluetoothAudioConfig(sampleRate, channelConfig, audioFormat); - } - public BluetoothAudioConfig[] newArray(int size) { - return new BluetoothAudioConfig[size]; - } - }; + public BluetoothAudioConfig createFromParcel(Parcel in) { + int sampleRate = in.readInt(); + int channelConfig = in.readInt(); + int audioFormat = in.readInt(); + return new BluetoothAudioConfig(sampleRate, channelConfig, audioFormat); + } + public BluetoothAudioConfig[] newArray(int size) { + return new BluetoothAudioConfig[size]; + } + }; + + @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(mSampleRate); out.writeInt(mChannelConfig); @@ -85,6 +87,7 @@ public final class BluetoothAudioConfig implements Parcelable { /** * Returns the sample rate in samples per second + * * @return sample rate */ public int getSampleRate() { @@ -94,6 +97,7 @@ public final class BluetoothAudioConfig implements Parcelable { /** * Returns the channel configuration (either {@link android.media.AudioFormat#CHANNEL_IN_MONO} * or {@link android.media.AudioFormat#CHANNEL_IN_STEREO}) + * * @return channel configuration */ public int getChannelConfig() { @@ -103,6 +107,7 @@ public final class BluetoothAudioConfig implements Parcelable { /** * Returns the channel audio format (either {@link android.media.AudioFormat#ENCODING_PCM_16BIT} * or {@link android.media.AudioFormat#ENCODING_PCM_8BIT} + * * @return audio format */ public int getAudioFormat() { diff --git a/core/java/android/bluetooth/BluetoothAvrcp.java b/core/java/android/bluetooth/BluetoothAvrcp.java index 44fe1b737129..1a4c75906482 100644 --- a/core/java/android/bluetooth/BluetoothAvrcp.java +++ b/core/java/android/bluetooth/BluetoothAvrcp.java @@ -26,68 +26,68 @@ public final class BluetoothAvrcp { /* * State flags for Passthrough commands */ - public static final int PASSTHROUGH_STATE_PRESS = 0; - public static final int PASSTHROUGH_STATE_RELEASE = 1; + public static final int PASSTHROUGH_STATE_PRESS = 0; + public static final int PASSTHROUGH_STATE_RELEASE = 1; /* * Operation IDs for Passthrough commands */ - public static final int PASSTHROUGH_ID_SELECT = 0x00; /* select */ - public static final int PASSTHROUGH_ID_UP = 0x01; /* up */ - public static final int PASSTHROUGH_ID_DOWN = 0x02; /* down */ - public static final int PASSTHROUGH_ID_LEFT = 0x03; /* left */ - public static final int PASSTHROUGH_ID_RIGHT = 0x04; /* right */ - public static final int PASSTHROUGH_ID_RIGHT_UP = 0x05; /* right-up */ - public static final int PASSTHROUGH_ID_RIGHT_DOWN = 0x06; /* right-down */ - public static final int PASSTHROUGH_ID_LEFT_UP = 0x07; /* left-up */ - public static final int PASSTHROUGH_ID_LEFT_DOWN = 0x08; /* left-down */ - public static final int PASSTHROUGH_ID_ROOT_MENU = 0x09; /* root menu */ - public static final int PASSTHROUGH_ID_SETUP_MENU = 0x0A; /* setup menu */ - public static final int PASSTHROUGH_ID_CONT_MENU = 0x0B; /* contents menu */ - public static final int PASSTHROUGH_ID_FAV_MENU = 0x0C; /* favorite menu */ - public static final int PASSTHROUGH_ID_EXIT = 0x0D; /* exit */ - public static final int PASSTHROUGH_ID_0 = 0x20; /* 0 */ - public static final int PASSTHROUGH_ID_1 = 0x21; /* 1 */ - public static final int PASSTHROUGH_ID_2 = 0x22; /* 2 */ - public static final int PASSTHROUGH_ID_3 = 0x23; /* 3 */ - public static final int PASSTHROUGH_ID_4 = 0x24; /* 4 */ - public static final int PASSTHROUGH_ID_5 = 0x25; /* 5 */ - public static final int PASSTHROUGH_ID_6 = 0x26; /* 6 */ - public static final int PASSTHROUGH_ID_7 = 0x27; /* 7 */ - public static final int PASSTHROUGH_ID_8 = 0x28; /* 8 */ - public static final int PASSTHROUGH_ID_9 = 0x29; /* 9 */ - public static final int PASSTHROUGH_ID_DOT = 0x2A; /* dot */ - public static final int PASSTHROUGH_ID_ENTER = 0x2B; /* enter */ - public static final int PASSTHROUGH_ID_CLEAR = 0x2C; /* clear */ - public static final int PASSTHROUGH_ID_CHAN_UP = 0x30; /* channel up */ - public static final int PASSTHROUGH_ID_CHAN_DOWN = 0x31; /* channel down */ - public static final int PASSTHROUGH_ID_PREV_CHAN = 0x32; /* previous channel */ - public static final int PASSTHROUGH_ID_SOUND_SEL = 0x33; /* sound select */ - public static final int PASSTHROUGH_ID_INPUT_SEL = 0x34; /* input select */ - public static final int PASSTHROUGH_ID_DISP_INFO = 0x35; /* display information */ - public static final int PASSTHROUGH_ID_HELP = 0x36; /* help */ - public static final int PASSTHROUGH_ID_PAGE_UP = 0x37; /* page up */ - public static final int PASSTHROUGH_ID_PAGE_DOWN = 0x38; /* page down */ - public static final int PASSTHROUGH_ID_POWER = 0x40; /* power */ - public static final int PASSTHROUGH_ID_VOL_UP = 0x41; /* volume up */ - public static final int PASSTHROUGH_ID_VOL_DOWN = 0x42; /* volume down */ - public static final int PASSTHROUGH_ID_MUTE = 0x43; /* mute */ - public static final int PASSTHROUGH_ID_PLAY = 0x44; /* play */ - public static final int PASSTHROUGH_ID_STOP = 0x45; /* stop */ - public static final int PASSTHROUGH_ID_PAUSE = 0x46; /* pause */ - public static final int PASSTHROUGH_ID_RECORD = 0x47; /* record */ - public static final int PASSTHROUGH_ID_REWIND = 0x48; /* rewind */ - public static final int PASSTHROUGH_ID_FAST_FOR = 0x49; /* fast forward */ - public static final int PASSTHROUGH_ID_EJECT = 0x4A; /* eject */ - public static final int PASSTHROUGH_ID_FORWARD = 0x4B; /* forward */ - public static final int PASSTHROUGH_ID_BACKWARD = 0x4C; /* backward */ - public static final int PASSTHROUGH_ID_ANGLE = 0x50; /* angle */ - public static final int PASSTHROUGH_ID_SUBPICT = 0x51; /* subpicture */ - public static final int PASSTHROUGH_ID_F1 = 0x71; /* F1 */ - public static final int PASSTHROUGH_ID_F2 = 0x72; /* F2 */ - public static final int PASSTHROUGH_ID_F3 = 0x73; /* F3 */ - public static final int PASSTHROUGH_ID_F4 = 0x74; /* F4 */ - public static final int PASSTHROUGH_ID_F5 = 0x75; /* F5 */ - public static final int PASSTHROUGH_ID_VENDOR = 0x7E; /* vendor unique */ + public static final int PASSTHROUGH_ID_SELECT = 0x00; /* select */ + public static final int PASSTHROUGH_ID_UP = 0x01; /* up */ + public static final int PASSTHROUGH_ID_DOWN = 0x02; /* down */ + public static final int PASSTHROUGH_ID_LEFT = 0x03; /* left */ + public static final int PASSTHROUGH_ID_RIGHT = 0x04; /* right */ + public static final int PASSTHROUGH_ID_RIGHT_UP = 0x05; /* right-up */ + public static final int PASSTHROUGH_ID_RIGHT_DOWN = 0x06; /* right-down */ + public static final int PASSTHROUGH_ID_LEFT_UP = 0x07; /* left-up */ + public static final int PASSTHROUGH_ID_LEFT_DOWN = 0x08; /* left-down */ + public static final int PASSTHROUGH_ID_ROOT_MENU = 0x09; /* root menu */ + public static final int PASSTHROUGH_ID_SETUP_MENU = 0x0A; /* setup menu */ + public static final int PASSTHROUGH_ID_CONT_MENU = 0x0B; /* contents menu */ + public static final int PASSTHROUGH_ID_FAV_MENU = 0x0C; /* favorite menu */ + public static final int PASSTHROUGH_ID_EXIT = 0x0D; /* exit */ + public static final int PASSTHROUGH_ID_0 = 0x20; /* 0 */ + public static final int PASSTHROUGH_ID_1 = 0x21; /* 1 */ + public static final int PASSTHROUGH_ID_2 = 0x22; /* 2 */ + public static final int PASSTHROUGH_ID_3 = 0x23; /* 3 */ + public static final int PASSTHROUGH_ID_4 = 0x24; /* 4 */ + public static final int PASSTHROUGH_ID_5 = 0x25; /* 5 */ + public static final int PASSTHROUGH_ID_6 = 0x26; /* 6 */ + public static final int PASSTHROUGH_ID_7 = 0x27; /* 7 */ + public static final int PASSTHROUGH_ID_8 = 0x28; /* 8 */ + public static final int PASSTHROUGH_ID_9 = 0x29; /* 9 */ + public static final int PASSTHROUGH_ID_DOT = 0x2A; /* dot */ + public static final int PASSTHROUGH_ID_ENTER = 0x2B; /* enter */ + public static final int PASSTHROUGH_ID_CLEAR = 0x2C; /* clear */ + public static final int PASSTHROUGH_ID_CHAN_UP = 0x30; /* channel up */ + public static final int PASSTHROUGH_ID_CHAN_DOWN = 0x31; /* channel down */ + public static final int PASSTHROUGH_ID_PREV_CHAN = 0x32; /* previous channel */ + public static final int PASSTHROUGH_ID_SOUND_SEL = 0x33; /* sound select */ + public static final int PASSTHROUGH_ID_INPUT_SEL = 0x34; /* input select */ + public static final int PASSTHROUGH_ID_DISP_INFO = 0x35; /* display information */ + public static final int PASSTHROUGH_ID_HELP = 0x36; /* help */ + public static final int PASSTHROUGH_ID_PAGE_UP = 0x37; /* page up */ + public static final int PASSTHROUGH_ID_PAGE_DOWN = 0x38; /* page down */ + public static final int PASSTHROUGH_ID_POWER = 0x40; /* power */ + public static final int PASSTHROUGH_ID_VOL_UP = 0x41; /* volume up */ + public static final int PASSTHROUGH_ID_VOL_DOWN = 0x42; /* volume down */ + public static final int PASSTHROUGH_ID_MUTE = 0x43; /* mute */ + public static final int PASSTHROUGH_ID_PLAY = 0x44; /* play */ + public static final int PASSTHROUGH_ID_STOP = 0x45; /* stop */ + public static final int PASSTHROUGH_ID_PAUSE = 0x46; /* pause */ + public static final int PASSTHROUGH_ID_RECORD = 0x47; /* record */ + public static final int PASSTHROUGH_ID_REWIND = 0x48; /* rewind */ + public static final int PASSTHROUGH_ID_FAST_FOR = 0x49; /* fast forward */ + public static final int PASSTHROUGH_ID_EJECT = 0x4A; /* eject */ + public static final int PASSTHROUGH_ID_FORWARD = 0x4B; /* forward */ + public static final int PASSTHROUGH_ID_BACKWARD = 0x4C; /* backward */ + public static final int PASSTHROUGH_ID_ANGLE = 0x50; /* angle */ + public static final int PASSTHROUGH_ID_SUBPICT = 0x51; /* subpicture */ + public static final int PASSTHROUGH_ID_F1 = 0x71; /* F1 */ + public static final int PASSTHROUGH_ID_F2 = 0x72; /* F2 */ + public static final int PASSTHROUGH_ID_F3 = 0x73; /* F3 */ + public static final int PASSTHROUGH_ID_F4 = 0x74; /* F4 */ + public static final int PASSTHROUGH_ID_F5 = 0x75; /* F5 */ + public static final int PASSTHROUGH_ID_VENDOR = 0x7E; /* vendor unique */ public static final int PASSTHROUGH_KEYPRESSED_RELEASE = 0x80; } diff --git a/core/java/android/bluetooth/BluetoothAvrcpController.java b/core/java/android/bluetooth/BluetoothAvrcpController.java index 0261b1b35e2d..7528aa972109 100644 --- a/core/java/android/bluetooth/BluetoothAvrcpController.java +++ b/core/java/android/bluetooth/BluetoothAvrcpController.java @@ -20,8 +20,6 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.media.MediaMetadata; -import android.media.session.PlaybackState; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; @@ -34,7 +32,7 @@ import java.util.List; * This class provides the public APIs to control the Bluetooth AVRCP Controller. It currently * supports player information, playback support and track metadata. * - *<p>BluetoothAvrcpController is a proxy object for controlling the Bluetooth AVRCP + * <p>BluetoothAvrcpController is a proxy object for controlling the Bluetooth AVRCP * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get * the BluetoothAvrcpController proxy object. * @@ -51,9 +49,9 @@ public final class BluetoothAvrcpController implements BluetoothProfile { * * <p>This intent will have 3 extras: * <ul> - * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> - * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> * </ul> * * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of @@ -64,19 +62,19 @@ public final class BluetoothAvrcpController implements BluetoothProfile { * receive. */ public static final String ACTION_CONNECTION_STATE_CHANGED = - "android.bluetooth.avrcp-controller.profile.action.CONNECTION_STATE_CHANGED"; + "android.bluetooth.avrcp-controller.profile.action.CONNECTION_STATE_CHANGED"; /** * Intent used to broadcast the change in player application setting state on AVRCP AG. * * <p>This intent will have the following extras: * <ul> - * <li> {@link #EXTRA_PLAYER_SETTING} - {@link BluetoothAvrcpPlayerSettings} containing the - * most recent player setting. </li> + * <li> {@link #EXTRA_PLAYER_SETTING} - {@link BluetoothAvrcpPlayerSettings} containing the + * most recent player setting. </li> * </ul> */ public static final String ACTION_PLAYER_SETTING = - "android.bluetooth.avrcp-controller.profile.action.PLAYER_SETTING"; + "android.bluetooth.avrcp-controller.profile.action.PLAYER_SETTING"; public static final String EXTRA_PLAYER_SETTING = "android.bluetooth.avrcp-controller.profile.extra.PLAYER_SETTING"; @@ -86,39 +84,38 @@ public final class BluetoothAvrcpController implements BluetoothProfile { private IBluetoothAvrcpController mService; private BluetoothAdapter mAdapter; - final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = - new IBluetoothStateChangeCallback.Stub() { - public void onBluetoothStateChange(boolean up) { - if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); - if (!up) { - if (VDBG) Log.d(TAG,"Unbinding service..."); - synchronized (mConnection) { - try { - mService = null; - mContext.unbindService(mConnection); - } catch (Exception re) { - Log.e(TAG,"",re); + private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + new IBluetoothStateChangeCallback.Stub() { + public void onBluetoothStateChange(boolean up) { + if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); + if (!up) { + if (VDBG) Log.d(TAG, "Unbinding service..."); + synchronized (mConnection) { + try { + mService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG, "", re); + } } - } - } else { - synchronized (mConnection) { - try { - if (mService == null) { - if (VDBG) Log.d(TAG,"Binding service..."); - doBind(); + } else { + synchronized (mConnection) { + try { + if (mService == null) { + if (VDBG) Log.d(TAG, "Binding service..."); + doBind(); + } + } catch (Exception re) { + Log.e(TAG, "", re); } - } catch (Exception re) { - Log.e(TAG,"",re); } } } - } - }; + }; /** * Create a BluetoothAvrcpController proxy object for interacting with the local * Bluetooth AVRCP service. - * */ /*package*/ BluetoothAvrcpController(Context context, ServiceListener l) { mContext = context; @@ -129,7 +126,7 @@ public final class BluetoothAvrcpController implements BluetoothProfile { try { mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -155,7 +152,7 @@ public final class BluetoothAvrcpController implements BluetoothProfile { try { mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); } catch (Exception e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -165,12 +162,13 @@ public final class BluetoothAvrcpController implements BluetoothProfile { mService = null; mContext.unbindService(mConnection); } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } } + @Override public void finalize() { close(); } @@ -178,6 +176,7 @@ public final class BluetoothAvrcpController implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); if (mService != null && isEnabled()) { @@ -195,6 +194,7 @@ public final class BluetoothAvrcpController implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); if (mService != null && isEnabled()) { @@ -212,10 +212,11 @@ public final class BluetoothAvrcpController implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getState(" + device + ")"); if (mService != null && isEnabled() - && isValidDevice(device)) { + && isValidDevice(device)) { try { return mService.getConnectionState(device); } catch (RemoteException e) { @@ -264,12 +265,13 @@ public final class BluetoothAvrcpController implements BluetoothProfile { return false; } - /* + /** * Send Group Navigation Command to Remote. * possible keycode values: next_grp, previous_grp defined above */ public void sendGroupNavigationCmd(BluetoothDevice device, int keyCode, int keyState) { - Log.d(TAG, "sendGroupNavigationCmd dev = " + device + " key " + keyCode + " State = " + keyState); + Log.d(TAG, "sendGroupNavigationCmd dev = " + device + " key " + keyCode + " State = " + + keyState); if (mService != null && isEnabled()) { try { mService.sendGroupNavigationCmd(device, keyCode, keyState); @@ -292,6 +294,7 @@ public final class BluetoothAvrcpController implements BluetoothProfile { BluetoothAvrcpController.this); } } + public void onServiceDisconnected(ComponentName className) { if (DBG) Log.d(TAG, "Proxy object disconnected"); mService = null; @@ -302,18 +305,18 @@ public final class BluetoothAvrcpController implements BluetoothProfile { }; private boolean isEnabled() { - if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; - return false; + if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; + return false; } private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; + if (device == null) return false; - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; + return false; } private static void log(String msg) { - Log.d(TAG, msg); + Log.d(TAG, msg); } } diff --git a/core/java/android/bluetooth/BluetoothAvrcpPlayerSettings.java b/core/java/android/bluetooth/BluetoothAvrcpPlayerSettings.java index 927cb5666515..3d3d80e2b4dd 100644 --- a/core/java/android/bluetooth/BluetoothAvrcpPlayerSettings.java +++ b/core/java/android/bluetooth/BluetoothAvrcpPlayerSettings.java @@ -34,22 +34,22 @@ public final class BluetoothAvrcpPlayerSettings implements Parcelable { /** * Equalizer setting. */ - public static final int SETTING_EQUALIZER = 0x01; + public static final int SETTING_EQUALIZER = 0x01; /** * Repeat setting. */ - public static final int SETTING_REPEAT = 0x02; + public static final int SETTING_REPEAT = 0x02; /** * Shuffle setting. */ - public static final int SETTING_SHUFFLE = 0x04; + public static final int SETTING_SHUFFLE = 0x04; /** * Scan mode setting. */ - public static final int SETTING_SCAN = 0x08; + public static final int SETTING_SCAN = 0x08; /** * Invalid state. @@ -82,16 +82,16 @@ public final class BluetoothAvrcpPlayerSettings implements Parcelable { /** * All track repeat/shuffle. * - * Applies to {@link SETTING_REPEAT}, {@link SETTING_SHUFFLE} and {@link SETTING_SCAN}. + * Applies to {@link #SETTING_REPEAT}, {@link #SETTING_SHUFFLE} and {@link #SETTING_SCAN}. */ - public static final int STATE_ALL_TRACK = 0x03; + public static final int STATE_ALL_TRACK = 0x03; /** * Group repeat/shuffle. * - * Applies to {@link SETTING_REPEAT}, {@link SETTING_SHUFFLE} and {@link SETTING_SCAN}. + * Applies to {@link #SETTING_REPEAT}, {@link #SETTING_SHUFFLE} and {@link #SETTING_SCAN}. */ - public static final int STATE_GROUP = 0x04; + public static final int STATE_GROUP = 0x04; /** * List of supported settings ORed. @@ -103,10 +103,12 @@ public final class BluetoothAvrcpPlayerSettings implements Parcelable { */ private Map<Integer, Integer> mSettingsValue = new HashMap<Integer, Integer>(); + @Override public int describeContents() { return 0; } + @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(mSettings); out.writeInt(mSettingsValue.size()); @@ -116,8 +118,8 @@ public final class BluetoothAvrcpPlayerSettings implements Parcelable { } } - public static final Parcelable.Creator<BluetoothAvrcpPlayerSettings> CREATOR - = new Parcelable.Creator<BluetoothAvrcpPlayerSettings>() { + public static final Parcelable.Creator<BluetoothAvrcpPlayerSettings> CREATOR = + new Parcelable.Creator<BluetoothAvrcpPlayerSettings>() { public BluetoothAvrcpPlayerSettings createFromParcel(Parcel in) { return new BluetoothAvrcpPlayerSettings(in); } @@ -157,6 +159,7 @@ public final class BluetoothAvrcpPlayerSettings implements Parcelable { * Add a setting value. * * The setting must be part of possible settings in {@link getSettings()}. + * * @param setting setting config. * @param value value for the setting. * @throws IllegalStateException if the setting is not supported. @@ -173,6 +176,7 @@ public final class BluetoothAvrcpPlayerSettings implements Parcelable { * Get a setting value. * * The setting must be part of possible settings in {@link getSettings()}. + * * @param setting setting config. * @return value value for the setting. * @throws IllegalStateException if the setting is not supported. diff --git a/core/java/android/bluetooth/BluetoothClass.java b/core/java/android/bluetooth/BluetoothClass.java index 4a38287e7ca9..57e4abb12987 100755 --- a/core/java/android/bluetooth/BluetoothClass.java +++ b/core/java/android/bluetooth/BluetoothClass.java @@ -51,6 +51,7 @@ import android.os.Parcelable; public final class BluetoothClass implements Parcelable { /** * Legacy error value. Applications should use null instead. + * * @hide */ public static final int ERROR = 0xFF000000; @@ -65,7 +66,7 @@ public final class BluetoothClass implements Parcelable { @Override public boolean equals(Object o) { if (o instanceof BluetoothClass) { - return mClass == ((BluetoothClass)o).mClass; + return mClass == ((BluetoothClass) o).mClass; } return false; } @@ -80,20 +81,23 @@ public final class BluetoothClass implements Parcelable { return Integer.toHexString(mClass); } + @Override public int describeContents() { return 0; } public static final Parcelable.Creator<BluetoothClass> CREATOR = new Parcelable.Creator<BluetoothClass>() { - public BluetoothClass createFromParcel(Parcel in) { - return new BluetoothClass(in.readInt()); - } - public BluetoothClass[] newArray(int size) { - return new BluetoothClass[size]; - } - }; + public BluetoothClass createFromParcel(Parcel in) { + return new BluetoothClass(in.readInt()); + } + public BluetoothClass[] newArray(int size) { + return new BluetoothClass[size]; + } + }; + + @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(mClass); } @@ -103,17 +107,17 @@ public final class BluetoothClass implements Parcelable { * <p>Each {@link BluetoothClass} encodes zero or more service classes. */ public static final class Service { - private static final int BITMASK = 0xFFE000; + private static final int BITMASK = 0xFFE000; public static final int LIMITED_DISCOVERABILITY = 0x002000; - public static final int POSITIONING = 0x010000; - public static final int NETWORKING = 0x020000; - public static final int RENDER = 0x040000; - public static final int CAPTURE = 0x080000; - public static final int OBJECT_TRANSFER = 0x100000; - public static final int AUDIO = 0x200000; - public static final int TELEPHONY = 0x400000; - public static final int INFORMATION = 0x800000; + public static final int POSITIONING = 0x010000; + public static final int NETWORKING = 0x020000; + public static final int RENDER = 0x040000; + public static final int CAPTURE = 0x080000; + public static final int OBJECT_TRANSFER = 0x100000; + public static final int AUDIO = 0x200000; + public static final int TELEPHONY = 0x400000; + public static final int INFORMATION = 0x800000; } /** @@ -141,91 +145,91 @@ public final class BluetoothClass implements Parcelable { * <p>See {@link BluetoothClass.Service} for service class constants. */ public static class Device { - private static final int BITMASK = 0x1FFC; + private static final int BITMASK = 0x1FFC; /** * Defines all major device class constants. * <p>See {@link BluetoothClass.Device} for minor classes. */ public static class Major { - private static final int BITMASK = 0x1F00; + private static final int BITMASK = 0x1F00; - public static final int MISC = 0x0000; - public static final int COMPUTER = 0x0100; - public static final int PHONE = 0x0200; - public static final int NETWORKING = 0x0300; - public static final int AUDIO_VIDEO = 0x0400; - public static final int PERIPHERAL = 0x0500; - public static final int IMAGING = 0x0600; - public static final int WEARABLE = 0x0700; - public static final int TOY = 0x0800; - public static final int HEALTH = 0x0900; - public static final int UNCATEGORIZED = 0x1F00; + public static final int MISC = 0x0000; + public static final int COMPUTER = 0x0100; + public static final int PHONE = 0x0200; + public static final int NETWORKING = 0x0300; + public static final int AUDIO_VIDEO = 0x0400; + public static final int PERIPHERAL = 0x0500; + public static final int IMAGING = 0x0600; + public static final int WEARABLE = 0x0700; + public static final int TOY = 0x0800; + public static final int HEALTH = 0x0900; + public static final int UNCATEGORIZED = 0x1F00; } // Devices in the COMPUTER major class - public static final int COMPUTER_UNCATEGORIZED = 0x0100; - public static final int COMPUTER_DESKTOP = 0x0104; - public static final int COMPUTER_SERVER = 0x0108; - public static final int COMPUTER_LAPTOP = 0x010C; - public static final int COMPUTER_HANDHELD_PC_PDA = 0x0110; - public static final int COMPUTER_PALM_SIZE_PC_PDA = 0x0114; - public static final int COMPUTER_WEARABLE = 0x0118; + public static final int COMPUTER_UNCATEGORIZED = 0x0100; + public static final int COMPUTER_DESKTOP = 0x0104; + public static final int COMPUTER_SERVER = 0x0108; + public static final int COMPUTER_LAPTOP = 0x010C; + public static final int COMPUTER_HANDHELD_PC_PDA = 0x0110; + public static final int COMPUTER_PALM_SIZE_PC_PDA = 0x0114; + public static final int COMPUTER_WEARABLE = 0x0118; // Devices in the PHONE major class - public static final int PHONE_UNCATEGORIZED = 0x0200; - public static final int PHONE_CELLULAR = 0x0204; - public static final int PHONE_CORDLESS = 0x0208; - public static final int PHONE_SMART = 0x020C; - public static final int PHONE_MODEM_OR_GATEWAY = 0x0210; - public static final int PHONE_ISDN = 0x0214; + public static final int PHONE_UNCATEGORIZED = 0x0200; + public static final int PHONE_CELLULAR = 0x0204; + public static final int PHONE_CORDLESS = 0x0208; + public static final int PHONE_SMART = 0x020C; + public static final int PHONE_MODEM_OR_GATEWAY = 0x0210; + public static final int PHONE_ISDN = 0x0214; // Minor classes for the AUDIO_VIDEO major class - public static final int AUDIO_VIDEO_UNCATEGORIZED = 0x0400; - public static final int AUDIO_VIDEO_WEARABLE_HEADSET = 0x0404; - public static final int AUDIO_VIDEO_HANDSFREE = 0x0408; + public static final int AUDIO_VIDEO_UNCATEGORIZED = 0x0400; + public static final int AUDIO_VIDEO_WEARABLE_HEADSET = 0x0404; + public static final int AUDIO_VIDEO_HANDSFREE = 0x0408; //public static final int AUDIO_VIDEO_RESERVED = 0x040C; - public static final int AUDIO_VIDEO_MICROPHONE = 0x0410; - public static final int AUDIO_VIDEO_LOUDSPEAKER = 0x0414; - public static final int AUDIO_VIDEO_HEADPHONES = 0x0418; - public static final int AUDIO_VIDEO_PORTABLE_AUDIO = 0x041C; - public static final int AUDIO_VIDEO_CAR_AUDIO = 0x0420; - public static final int AUDIO_VIDEO_SET_TOP_BOX = 0x0424; - public static final int AUDIO_VIDEO_HIFI_AUDIO = 0x0428; - public static final int AUDIO_VIDEO_VCR = 0x042C; - public static final int AUDIO_VIDEO_VIDEO_CAMERA = 0x0430; - public static final int AUDIO_VIDEO_CAMCORDER = 0x0434; - public static final int AUDIO_VIDEO_VIDEO_MONITOR = 0x0438; + public static final int AUDIO_VIDEO_MICROPHONE = 0x0410; + public static final int AUDIO_VIDEO_LOUDSPEAKER = 0x0414; + public static final int AUDIO_VIDEO_HEADPHONES = 0x0418; + public static final int AUDIO_VIDEO_PORTABLE_AUDIO = 0x041C; + public static final int AUDIO_VIDEO_CAR_AUDIO = 0x0420; + public static final int AUDIO_VIDEO_SET_TOP_BOX = 0x0424; + public static final int AUDIO_VIDEO_HIFI_AUDIO = 0x0428; + public static final int AUDIO_VIDEO_VCR = 0x042C; + public static final int AUDIO_VIDEO_VIDEO_CAMERA = 0x0430; + public static final int AUDIO_VIDEO_CAMCORDER = 0x0434; + public static final int AUDIO_VIDEO_VIDEO_MONITOR = 0x0438; public static final int AUDIO_VIDEO_VIDEO_DISPLAY_AND_LOUDSPEAKER = 0x043C; - public static final int AUDIO_VIDEO_VIDEO_CONFERENCING = 0x0440; + public static final int AUDIO_VIDEO_VIDEO_CONFERENCING = 0x0440; //public static final int AUDIO_VIDEO_RESERVED = 0x0444; - public static final int AUDIO_VIDEO_VIDEO_GAMING_TOY = 0x0448; + public static final int AUDIO_VIDEO_VIDEO_GAMING_TOY = 0x0448; // Devices in the WEARABLE major class - public static final int WEARABLE_UNCATEGORIZED = 0x0700; - public static final int WEARABLE_WRIST_WATCH = 0x0704; - public static final int WEARABLE_PAGER = 0x0708; - public static final int WEARABLE_JACKET = 0x070C; - public static final int WEARABLE_HELMET = 0x0710; - public static final int WEARABLE_GLASSES = 0x0714; + public static final int WEARABLE_UNCATEGORIZED = 0x0700; + public static final int WEARABLE_WRIST_WATCH = 0x0704; + public static final int WEARABLE_PAGER = 0x0708; + public static final int WEARABLE_JACKET = 0x070C; + public static final int WEARABLE_HELMET = 0x0710; + public static final int WEARABLE_GLASSES = 0x0714; // Devices in the TOY major class - public static final int TOY_UNCATEGORIZED = 0x0800; - public static final int TOY_ROBOT = 0x0804; - public static final int TOY_VEHICLE = 0x0808; - public static final int TOY_DOLL_ACTION_FIGURE = 0x080C; - public static final int TOY_CONTROLLER = 0x0810; - public static final int TOY_GAME = 0x0814; + public static final int TOY_UNCATEGORIZED = 0x0800; + public static final int TOY_ROBOT = 0x0804; + public static final int TOY_VEHICLE = 0x0808; + public static final int TOY_DOLL_ACTION_FIGURE = 0x080C; + public static final int TOY_CONTROLLER = 0x0810; + public static final int TOY_GAME = 0x0814; // Devices in the HEALTH major class - public static final int HEALTH_UNCATEGORIZED = 0x0900; - public static final int HEALTH_BLOOD_PRESSURE = 0x0904; - public static final int HEALTH_THERMOMETER = 0x0908; - public static final int HEALTH_WEIGHING = 0x090C; - public static final int HEALTH_GLUCOSE = 0x0910; - public static final int HEALTH_PULSE_OXIMETER = 0x0914; - public static final int HEALTH_PULSE_RATE = 0x0918; - public static final int HEALTH_DATA_DISPLAY = 0x091C; + public static final int HEALTH_UNCATEGORIZED = 0x0900; + public static final int HEALTH_BLOOD_PRESSURE = 0x0904; + public static final int HEALTH_THERMOMETER = 0x0908; + public static final int HEALTH_WEIGHING = 0x090C; + public static final int HEALTH_GLUCOSE = 0x0910; + public static final int HEALTH_PULSE_OXIMETER = 0x0914; + public static final int HEALTH_PULSE_RATE = 0x0918; + public static final int HEALTH_DATA_DISPLAY = 0x091C; // Devices in PERIPHERAL major class /** @@ -235,15 +239,15 @@ public final class BluetoothClass implements Parcelable { /** * @hide */ - public static final int PERIPHERAL_KEYBOARD = 0x0540; + public static final int PERIPHERAL_KEYBOARD = 0x0540; /** * @hide */ - public static final int PERIPHERAL_POINTING = 0x0580; + public static final int PERIPHERAL_POINTING = 0x0580; /** * @hide */ - public static final int PERIPHERAL_KEYBOARD_POINTING = 0x05C0; + public static final int PERIPHERAL_KEYBOARD_POINTING = 0x05C0; } /** @@ -291,6 +295,7 @@ public final class BluetoothClass implements Parcelable { * This is a simple heuristic that tries to guess if a device with the * given class bits might support specified profile. It is not accurate for all * devices. It tries to err on the side of false positives. + * * @param profile The profile to be checked * @return True if this device might support specified profile. * @hide @@ -322,7 +327,7 @@ public final class BluetoothClass implements Parcelable { switch (getDeviceClass()) { case Device.AUDIO_VIDEO_HIFI_AUDIO: case Device.AUDIO_VIDEO_SET_TOP_BOX: - case Device.AUDIO_VIDEO_VCR : + case Device.AUDIO_VIDEO_VCR: return true; default: return false; @@ -367,7 +372,7 @@ public final class BluetoothClass implements Parcelable { } } else if (profile == PROFILE_HID) { return (getDeviceClass() & Device.Major.PERIPHERAL) == Device.Major.PERIPHERAL; - } else if (profile == PROFILE_PANU || profile == PROFILE_NAP){ + } else if (profile == PROFILE_PANU || profile == PROFILE_NAP) { // No good way to distinguish between the two, based on class bits. if (hasService(Service.NETWORKING)) { return true; diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java index d5e142981013..e3a6e064725e 100644 --- a/core/java/android/bluetooth/BluetoothCodecConfig.java +++ b/core/java/android/bluetooth/BluetoothCodecConfig.java @@ -32,12 +32,12 @@ public final class BluetoothCodecConfig implements Parcelable { // Add an entry for each source codec here. // NOTE: The values should be same as those listed in the following file: // hardware/libhardware/include/hardware/bt_av.h - public static final int SOURCE_CODEC_TYPE_SBC = 0; - public static final int SOURCE_CODEC_TYPE_AAC = 1; - public static final int SOURCE_CODEC_TYPE_APTX = 2; + public static final int SOURCE_CODEC_TYPE_SBC = 0; + public static final int SOURCE_CODEC_TYPE_AAC = 1; + public static final int SOURCE_CODEC_TYPE_APTX = 2; public static final int SOURCE_CODEC_TYPE_APTX_HD = 3; - public static final int SOURCE_CODEC_TYPE_LDAC = 4; - public static final int SOURCE_CODEC_TYPE_MAX = 5; + public static final int SOURCE_CODEC_TYPE_LDAC = 4; + public static final int SOURCE_CODEC_TYPE_MAX = 5; public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000; @@ -45,21 +45,21 @@ public final class BluetoothCodecConfig implements Parcelable { public static final int CODEC_PRIORITY_DEFAULT = 0; public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000; - public static final int SAMPLE_RATE_NONE = 0; - public static final int SAMPLE_RATE_44100 = 0x1 << 0; - public static final int SAMPLE_RATE_48000 = 0x1 << 1; - public static final int SAMPLE_RATE_88200 = 0x1 << 2; - public static final int SAMPLE_RATE_96000 = 0x1 << 3; + public static final int SAMPLE_RATE_NONE = 0; + public static final int SAMPLE_RATE_44100 = 0x1 << 0; + public static final int SAMPLE_RATE_48000 = 0x1 << 1; + public static final int SAMPLE_RATE_88200 = 0x1 << 2; + public static final int SAMPLE_RATE_96000 = 0x1 << 3; public static final int SAMPLE_RATE_176400 = 0x1 << 4; public static final int SAMPLE_RATE_192000 = 0x1 << 5; public static final int BITS_PER_SAMPLE_NONE = 0; - public static final int BITS_PER_SAMPLE_16 = 0x1 << 0; - public static final int BITS_PER_SAMPLE_24 = 0x1 << 1; - public static final int BITS_PER_SAMPLE_32 = 0x1 << 2; + public static final int BITS_PER_SAMPLE_16 = 0x1 << 0; + public static final int BITS_PER_SAMPLE_24 = 0x1 << 1; + public static final int BITS_PER_SAMPLE_32 = 0x1 << 2; - public static final int CHANNEL_MODE_NONE = 0; - public static final int CHANNEL_MODE_MONO = 0x1 << 0; + public static final int CHANNEL_MODE_NONE = 0; + public static final int CHANNEL_MODE_MONO = 0x1 << 0; public static final int CHANNEL_MODE_STEREO = 0x1 << 1; private final int mCodecType; @@ -73,10 +73,10 @@ public final class BluetoothCodecConfig implements Parcelable { private final long mCodecSpecific4; public BluetoothCodecConfig(int codecType, int codecPriority, - int sampleRate, int bitsPerSample, - int channelMode, long codecSpecific1, - long codecSpecific2, long codecSpecific3, - long codecSpecific4) { + int sampleRate, int bitsPerSample, + int channelMode, long codecSpecific1, + long codecSpecific2, long codecSpecific3, + long codecSpecific4) { mCodecType = codecType; mCodecPriority = codecPriority; mSampleRate = sampleRate; @@ -91,16 +91,16 @@ public final class BluetoothCodecConfig implements Parcelable { @Override public boolean equals(Object o) { if (o instanceof BluetoothCodecConfig) { - BluetoothCodecConfig other = (BluetoothCodecConfig)o; - return (other.mCodecType == mCodecType && - other.mCodecPriority == mCodecPriority && - other.mSampleRate == mSampleRate && - other.mBitsPerSample == mBitsPerSample && - other.mChannelMode == mChannelMode && - other.mCodecSpecific1 == mCodecSpecific1 && - other.mCodecSpecific2 == mCodecSpecific2 && - other.mCodecSpecific3 == mCodecSpecific3 && - other.mCodecSpecific4 == mCodecSpecific4); + BluetoothCodecConfig other = (BluetoothCodecConfig) o; + return (other.mCodecType == mCodecType + && other.mCodecPriority == mCodecPriority + && other.mSampleRate == mSampleRate + && other.mBitsPerSample == mBitsPerSample + && other.mChannelMode == mChannelMode + && other.mCodecSpecific1 == mCodecSpecific1 + && other.mCodecSpecific2 == mCodecSpecific2 + && other.mCodecSpecific3 == mCodecSpecific3 + && other.mCodecSpecific4 == mCodecSpecific4); } return false; } @@ -108,32 +108,30 @@ public final class BluetoothCodecConfig implements Parcelable { @Override public int hashCode() { return Objects.hash(mCodecType, mCodecPriority, mSampleRate, - mBitsPerSample, mChannelMode, mCodecSpecific1, - mCodecSpecific2, mCodecSpecific3, mCodecSpecific4); + mBitsPerSample, mChannelMode, mCodecSpecific1, + mCodecSpecific2, mCodecSpecific3, mCodecSpecific4); } /** * Checks whether the object contains valid codec configuration. * - * @return true if the object contains valid codec configuration, - * otherwise false. + * @return true if the object contains valid codec configuration, otherwise false. */ public boolean isValid() { - return (mSampleRate != SAMPLE_RATE_NONE) && - (mBitsPerSample != BITS_PER_SAMPLE_NONE) && - (mChannelMode != CHANNEL_MODE_NONE); + return (mSampleRate != SAMPLE_RATE_NONE) + && (mBitsPerSample != BITS_PER_SAMPLE_NONE) + && (mChannelMode != CHANNEL_MODE_NONE); } /** * Adds capability string to an existing string. * - * @param prevStr the previous string with the capabilities. Can be - * a null pointer. + * @param prevStr the previous string with the capabilities. Can be a null pointer. * @param capStr the capability string to append to prevStr argument. * @return the result string in the form "prevStr|capStr". */ private static String appendCapabilityToString(String prevStr, - String capStr) { + String capStr) { if (prevStr == null) { return capStr; } @@ -190,48 +188,51 @@ public final class BluetoothCodecConfig implements Parcelable { channelModeStr = appendCapabilityToString(channelModeStr, "STEREO"); } - return "{codecName:" + getCodecName() + - ",mCodecType:" + mCodecType + - ",mCodecPriority:" + mCodecPriority + - ",mSampleRate:" + String.format("0x%x", mSampleRate) + - "(" + sampleRateStr + ")" + - ",mBitsPerSample:" + String.format("0x%x", mBitsPerSample) + - "(" + bitsPerSampleStr + ")" + - ",mChannelMode:" + String.format("0x%x", mChannelMode) + - "(" + channelModeStr + ")" + - ",mCodecSpecific1:" + mCodecSpecific1 + - ",mCodecSpecific2:" + mCodecSpecific2 + - ",mCodecSpecific3:" + mCodecSpecific3 + - ",mCodecSpecific4:" + mCodecSpecific4 + "}"; + return "{codecName:" + getCodecName() + + ",mCodecType:" + mCodecType + + ",mCodecPriority:" + mCodecPriority + + ",mSampleRate:" + String.format("0x%x", mSampleRate) + + "(" + sampleRateStr + ")" + + ",mBitsPerSample:" + String.format("0x%x", mBitsPerSample) + + "(" + bitsPerSampleStr + ")" + + ",mChannelMode:" + String.format("0x%x", mChannelMode) + + "(" + channelModeStr + ")" + + ",mCodecSpecific1:" + mCodecSpecific1 + + ",mCodecSpecific2:" + mCodecSpecific2 + + ",mCodecSpecific3:" + mCodecSpecific3 + + ",mCodecSpecific4:" + mCodecSpecific4 + "}"; } + @Override public int describeContents() { return 0; } public static final Parcelable.Creator<BluetoothCodecConfig> CREATOR = new Parcelable.Creator<BluetoothCodecConfig>() { - public BluetoothCodecConfig createFromParcel(Parcel in) { - final int codecType = in.readInt(); - final int codecPriority = in.readInt(); - final int sampleRate = in.readInt(); - final int bitsPerSample = in.readInt(); - final int channelMode = in.readInt(); - final long codecSpecific1 = in.readLong(); - final long codecSpecific2 = in.readLong(); - final long codecSpecific3 = in.readLong(); - final long codecSpecific4 = in.readLong(); - return new BluetoothCodecConfig(codecType, codecPriority, - sampleRate, bitsPerSample, - channelMode, codecSpecific1, - codecSpecific2, codecSpecific3, - codecSpecific4); - } - public BluetoothCodecConfig[] newArray(int size) { - return new BluetoothCodecConfig[size]; - } - }; + public BluetoothCodecConfig createFromParcel(Parcel in) { + final int codecType = in.readInt(); + final int codecPriority = in.readInt(); + final int sampleRate = in.readInt(); + final int bitsPerSample = in.readInt(); + final int channelMode = in.readInt(); + final long codecSpecific1 = in.readLong(); + final long codecSpecific2 = in.readLong(); + final long codecSpecific3 = in.readLong(); + final long codecSpecific4 = in.readLong(); + return new BluetoothCodecConfig(codecType, codecPriority, + sampleRate, bitsPerSample, + channelMode, codecSpecific1, + codecSpecific2, codecSpecific3, + codecSpecific4); + } + + public BluetoothCodecConfig[] newArray(int size) { + return new BluetoothCodecConfig[size]; + } + }; + @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(mCodecType); out.writeInt(mCodecPriority); @@ -251,20 +252,20 @@ public final class BluetoothCodecConfig implements Parcelable { */ public String getCodecName() { switch (mCodecType) { - case SOURCE_CODEC_TYPE_SBC: - return "SBC"; - case SOURCE_CODEC_TYPE_AAC: - return "AAC"; - case SOURCE_CODEC_TYPE_APTX: - return "aptX"; - case SOURCE_CODEC_TYPE_APTX_HD: - return "aptX HD"; - case SOURCE_CODEC_TYPE_LDAC: - return "LDAC"; - case SOURCE_CODEC_TYPE_INVALID: - return "INVALID CODEC"; - default: - break; + case SOURCE_CODEC_TYPE_SBC: + return "SBC"; + case SOURCE_CODEC_TYPE_AAC: + return "AAC"; + case SOURCE_CODEC_TYPE_APTX: + return "aptX"; + case SOURCE_CODEC_TYPE_APTX_HD: + return "aptX HD"; + case SOURCE_CODEC_TYPE_LDAC: + return "LDAC"; + case SOURCE_CODEC_TYPE_INVALID: + return "INVALID CODEC"; + default: + break; } return "UNKNOWN CODEC(" + mCodecType + ")"; } @@ -397,8 +398,8 @@ public final class BluetoothCodecConfig implements Parcelable { * @return true if the audio feeding parameters are same, otherwise false */ public boolean sameAudioFeedingParameters(BluetoothCodecConfig other) { - return (other != null && other.mSampleRate == mSampleRate && - other.mBitsPerSample == mBitsPerSample && - other.mChannelMode == mChannelMode); + return (other != null && other.mSampleRate == mSampleRate + && other.mBitsPerSample == mBitsPerSample + && other.mChannelMode == mChannelMode); } } diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.java b/core/java/android/bluetooth/BluetoothCodecStatus.java index c8cd8d17ce36..7ae4cb706233 100644 --- a/core/java/android/bluetooth/BluetoothCodecStatus.java +++ b/core/java/android/bluetooth/BluetoothCodecStatus.java @@ -38,15 +38,15 @@ public final class BluetoothCodecStatus implements Parcelable { * profile. */ public static final String EXTRA_CODEC_STATUS = - "android.bluetooth.codec.extra.CODEC_STATUS"; + "android.bluetooth.codec.extra.CODEC_STATUS"; private final BluetoothCodecConfig mCodecConfig; private final BluetoothCodecConfig[] mCodecsLocalCapabilities; private final BluetoothCodecConfig[] mCodecsSelectableCapabilities; public BluetoothCodecStatus(BluetoothCodecConfig codecConfig, - BluetoothCodecConfig[] codecsLocalCapabilities, - BluetoothCodecConfig[] codecsSelectableCapabilities) { + BluetoothCodecConfig[] codecsLocalCapabilities, + BluetoothCodecConfig[] codecsSelectableCapabilities) { mCodecConfig = codecConfig; mCodecsLocalCapabilities = codecsLocalCapabilities; mCodecsSelectableCapabilities = codecsSelectableCapabilities; @@ -55,12 +55,11 @@ public final class BluetoothCodecStatus implements Parcelable { @Override public boolean equals(Object o) { if (o instanceof BluetoothCodecStatus) { - BluetoothCodecStatus other = (BluetoothCodecStatus)o; - return (Objects.equals(other.mCodecConfig, mCodecConfig) && - Objects.equals(other.mCodecsLocalCapabilities, - mCodecsLocalCapabilities) && - Objects.equals(other.mCodecsSelectableCapabilities, - mCodecsSelectableCapabilities)); + BluetoothCodecStatus other = (BluetoothCodecStatus) o; + return (Objects.equals(other.mCodecConfig, mCodecConfig) + && Objects.equals(other.mCodecsLocalCapabilities, mCodecsLocalCapabilities) + && Objects.equals(other.mCodecsSelectableCapabilities, + mCodecsSelectableCapabilities)); } return false; } @@ -68,37 +67,43 @@ public final class BluetoothCodecStatus implements Parcelable { @Override public int hashCode() { return Objects.hash(mCodecConfig, mCodecsLocalCapabilities, - mCodecsLocalCapabilities); + mCodecsLocalCapabilities); } @Override public String toString() { - return "{mCodecConfig:" + mCodecConfig + - ",mCodecsLocalCapabilities:" + Arrays.toString(mCodecsLocalCapabilities) + - ",mCodecsSelectableCapabilities:" + Arrays.toString(mCodecsSelectableCapabilities) + - "}"; + return "{mCodecConfig:" + mCodecConfig + + ",mCodecsLocalCapabilities:" + Arrays.toString(mCodecsLocalCapabilities) + + ",mCodecsSelectableCapabilities:" + Arrays.toString(mCodecsSelectableCapabilities) + + "}"; } + @Override public int describeContents() { return 0; } public static final Parcelable.Creator<BluetoothCodecStatus> CREATOR = new Parcelable.Creator<BluetoothCodecStatus>() { - public BluetoothCodecStatus createFromParcel(Parcel in) { - final BluetoothCodecConfig codecConfig = in.readTypedObject(BluetoothCodecConfig.CREATOR); - final BluetoothCodecConfig[] codecsLocalCapabilities = in.createTypedArray(BluetoothCodecConfig.CREATOR); - final BluetoothCodecConfig[] codecsSelectableCapabilities = in.createTypedArray(BluetoothCodecConfig.CREATOR); - - return new BluetoothCodecStatus(codecConfig, - codecsLocalCapabilities, - codecsSelectableCapabilities); - } - public BluetoothCodecStatus[] newArray(int size) { - return new BluetoothCodecStatus[size]; - } - }; + public BluetoothCodecStatus createFromParcel(Parcel in) { + final BluetoothCodecConfig codecConfig = in.readTypedObject( + BluetoothCodecConfig.CREATOR); + final BluetoothCodecConfig[] codecsLocalCapabilities = in.createTypedArray( + BluetoothCodecConfig.CREATOR); + final BluetoothCodecConfig[] codecsSelectableCapabilities = in.createTypedArray( + BluetoothCodecConfig.CREATOR); + + return new BluetoothCodecStatus(codecConfig, + codecsLocalCapabilities, + codecsSelectableCapabilities); + } + + public BluetoothCodecStatus[] newArray(int size) { + return new BluetoothCodecStatus[size]; + } + }; + @Override public void writeToParcel(Parcel out, int flags) { out.writeTypedObject(mCodecConfig, 0); out.writeTypedArray(mCodecsLocalCapabilities, 0); diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index a206b53b5360..3ab2c4a8f44d 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -23,10 +23,9 @@ import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.content.Context; import android.os.Handler; -import android.os.Looper; import android.os.Parcel; -import android.os.Parcelable; import android.os.ParcelUuid; +import android.os.Parcelable; import android.os.Process; import android.os.RemoteException; import android.util.Log; @@ -101,7 +100,7 @@ public final class BluetoothDevice implements Parcelable { * <p>Requires {@link android.Manifest.permission#BLUETOOTH} and * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} to receive. */ - // TODO: Change API to not broadcast RSSI if not available (incoming connection) + // TODO: Change API to not broadcast RSSI if not available (incoming connection) @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_FOUND = "android.bluetooth.device.action.FOUND"; @@ -112,6 +111,7 @@ public final class BluetoothDevice implements Parcelable { * found in the current discovery. * <p>Always contains the extra field {@link #EXTRA_DEVICE}. * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. + * * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @@ -208,6 +208,7 @@ public final class BluetoothDevice implements Parcelable { * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link * #EXTRA_BATTERY_LEVEL}. * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. + * * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @@ -219,6 +220,7 @@ public final class BluetoothDevice implements Parcelable { * intent. It contains the most recently retrieved battery level information * ranging from 0% to 100% for a remote device, {@link #BATTERY_LEVEL_UNKNOWN} * when the valid is unknown or there is an error + * * @hide */ public static final String EXTRA_BATTERY_LEVEL = @@ -226,6 +228,7 @@ public final class BluetoothDevice implements Parcelable { /** * Used as the unknown value for {@link #EXTRA_BATTERY_LEVEL} and {@link #getBatteryLevel()} + * * @hide */ public static final int BATTERY_LEVEL_UNKNOWN = -1; @@ -300,6 +303,7 @@ public final class BluetoothDevice implements Parcelable { /** * Used as an int extra field in {@link #ACTION_PAIRING_REQUEST} * intents for unbond reason. + * * @hide */ public static final String EXTRA_REASON = "android.bluetooth.device.extra.REASON"; @@ -368,6 +372,7 @@ public final class BluetoothDevice implements Parcelable { * device. * <p>Always contains the extra field {@link #EXTRA_DEVICE}. * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. + * * @hide */ //TODO: is this actually useful? @@ -405,26 +410,28 @@ public final class BluetoothDevice implements Parcelable { /** * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intent. + * * @hide */ public static final String EXTRA_ACCESS_REQUEST_TYPE = - "android.bluetooth.device.extra.ACCESS_REQUEST_TYPE"; + "android.bluetooth.device.extra.ACCESS_REQUEST_TYPE"; - /**@hide*/ + /** @hide */ public static final int REQUEST_TYPE_PROFILE_CONNECTION = 1; - /**@hide*/ + /** @hide */ public static final int REQUEST_TYPE_PHONEBOOK_ACCESS = 2; - /**@hide*/ + /** @hide */ public static final int REQUEST_TYPE_MESSAGE_ACCESS = 3; - /**@hide*/ + /** @hide */ public static final int REQUEST_TYPE_SIM_ACCESS = 4; /** * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intents, * Contains package name to return reply intent to. + * * @hide */ public static final String EXTRA_PACKAGE_NAME = "android.bluetooth.device.extra.PACKAGE_NAME"; @@ -432,34 +439,38 @@ public final class BluetoothDevice implements Parcelable { /** * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intents, * Contains class name to return reply intent to. + * * @hide */ public static final String EXTRA_CLASS_NAME = "android.bluetooth.device.extra.CLASS_NAME"; /** * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REPLY} intent. + * * @hide */ public static final String EXTRA_CONNECTION_ACCESS_RESULT = - "android.bluetooth.device.extra.CONNECTION_ACCESS_RESULT"; + "android.bluetooth.device.extra.CONNECTION_ACCESS_RESULT"; - /**@hide*/ + /** @hide */ public static final int CONNECTION_ACCESS_YES = 1; - /**@hide*/ + /** @hide */ public static final int CONNECTION_ACCESS_NO = 2; /** * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REPLY} intents, * Contains boolean to indicate if the allowed response is once-for-all so that * next request will be granted without asking user again. + * * @hide */ public static final String EXTRA_ALWAYS_ALLOWED = - "android.bluetooth.device.extra.ALWAYS_ALLOWED"; + "android.bluetooth.device.extra.ALWAYS_ALLOWED"; /** * A bond attempt succeeded + * * @hide */ public static final int BOND_SUCCESS = 0; @@ -467,6 +478,7 @@ public final class BluetoothDevice implements Parcelable { /** * A bond attempt failed because pins did not match, or remote device did * not respond to pin request in time + * * @hide */ public static final int UNBOND_REASON_AUTH_FAILED = 1; @@ -474,36 +486,42 @@ public final class BluetoothDevice implements Parcelable { /** * A bond attempt failed because the other side explicitly rejected * bonding + * * @hide */ public static final int UNBOND_REASON_AUTH_REJECTED = 2; /** * A bond attempt failed because we canceled the bonding process + * * @hide */ public static final int UNBOND_REASON_AUTH_CANCELED = 3; /** * A bond attempt failed because we could not contact the remote device + * * @hide */ public static final int UNBOND_REASON_REMOTE_DEVICE_DOWN = 4; /** * A bond attempt failed because a discovery is in progress + * * @hide */ public static final int UNBOND_REASON_DISCOVERY_IN_PROGRESS = 5; /** * A bond attempt failed because of authentication timeout + * * @hide */ public static final int UNBOND_REASON_AUTH_TIMEOUT = 6; /** * A bond attempt failed because of repeated attempts + * * @hide */ public static final int UNBOND_REASON_REPEATED_ATTEMPTS = 7; @@ -511,12 +529,14 @@ public final class BluetoothDevice implements Parcelable { /** * A bond attempt failed because we received an Authentication Cancel * by remote end + * * @hide */ public static final int UNBOND_REASON_REMOTE_AUTH_CANCELED = 8; /** * An existing bond was explicitly revoked + * * @hide */ public static final int UNBOND_REASON_REMOVED = 9; @@ -529,6 +549,7 @@ public final class BluetoothDevice implements Parcelable { /** * The user will be prompted to enter a passkey + * * @hide */ public static final int PAIRING_VARIANT_PASSKEY = 1; @@ -541,6 +562,7 @@ public final class BluetoothDevice implements Parcelable { /** * The user will be prompted to accept or deny the incoming pairing request + * * @hide */ public static final int PAIRING_VARIANT_CONSENT = 3; @@ -548,6 +570,7 @@ public final class BluetoothDevice implements Parcelable { /** * The user will be prompted to enter the passkey displayed on remote device * This is used for Bluetooth 2.1 pairing. + * * @hide */ public static final int PAIRING_VARIANT_DISPLAY_PASSKEY = 4; @@ -555,12 +578,14 @@ public final class BluetoothDevice implements Parcelable { /** * The user will be prompted to enter the PIN displayed on remote device. * This is used for Bluetooth 2.0 pairing. + * * @hide */ public static final int PAIRING_VARIANT_DISPLAY_PIN = 5; /** * The user will be prompted to accept or deny the OOB pairing request + * * @hide */ public static final int PAIRING_VARIANT_OOB_CONSENT = 6; @@ -568,6 +593,7 @@ public final class BluetoothDevice implements Parcelable { /** * The user will be prompted to enter a 16 digit pin or * an app will enter a 16 digit pin for user. + * * @hide */ public static final int PAIRING_VARIANT_PIN_16_DIGITS = 7; @@ -581,7 +607,7 @@ public final class BluetoothDevice implements Parcelable { /** @hide */ public static final String EXTRA_SDP_RECORD = - "android.bluetooth.device.extra.SDP_RECORD"; + "android.bluetooth.device.extra.SDP_RECORD"; /** @hide */ public static final String EXTRA_SDP_SEARCH_STATUS = @@ -589,6 +615,7 @@ public final class BluetoothDevice implements Parcelable { /** * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission}, * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}. + * * @hide */ public static final int ACCESS_UNKNOWN = 0; @@ -596,6 +623,7 @@ public final class BluetoothDevice implements Parcelable { /** * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission}, * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}. + * * @hide */ public static final int ACCESS_ALLOWED = 1; @@ -603,13 +631,14 @@ public final class BluetoothDevice implements Parcelable { /** * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission}, * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}. + * * @hide */ public static final int ACCESS_REJECTED = 2; - /** - * No preferrence of physical transport for GATT connections to remote dual-mode devices - */ + /** + * No preferrence of physical transport for GATT connections to remote dual-mode devices + */ public static final int TRANSPORT_AUTO = 0; /** @@ -676,7 +705,7 @@ public final class BluetoothDevice implements Parcelable { /** @hide */ public static final String EXTRA_MAS_INSTANCE = - "android.bluetooth.device.extra.MAS_INSTANCE"; + "android.bluetooth.device.extra.MAS_INSTANCE"; /** * Lazy initialization. Guaranteed final after first object constructed, or @@ -687,17 +716,18 @@ public final class BluetoothDevice implements Parcelable { private final String mAddress; - /*package*/ static IBluetooth getService() { + /*package*/ + static IBluetooth getService() { synchronized (BluetoothDevice.class) { if (sService == null) { BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - sService = adapter.getBluetoothService(mStateChangeCallback); + sService = adapter.getBluetoothService(sStateChangeCallback); } } return sService; } - static IBluetoothManagerCallback mStateChangeCallback = new IBluetoothManagerCallback.Stub() { + static IBluetoothManagerCallback sStateChangeCallback = new IBluetoothManagerCallback.Stub() { public void onBluetoothServiceUp(IBluetooth bluetoothService) throws RemoteException { @@ -709,21 +739,22 @@ public final class BluetoothDevice implements Parcelable { } public void onBluetoothServiceDown() - throws RemoteException { + throws RemoteException { synchronized (BluetoothDevice.class) { sService = null; } } - public void onBrEdrDown() - { + public void onBrEdrDown() { if (DBG) Log.d(TAG, "onBrEdrDown: reached BLE ON state"); } }; + /** * Create a new BluetoothDevice * Bluetooth MAC address must be upper case, such as "00:11:22:33:AA:BB", * and is validated in this constructor. + * * @param address valid Bluetooth MAC address * @throws RuntimeException Bluetooth is not available on this platform * @throws IllegalArgumentException address is invalid @@ -741,7 +772,7 @@ public final class BluetoothDevice implements Parcelable { @Override public boolean equals(Object o) { if (o instanceof BluetoothDevice) { - return mAddress.equals(((BluetoothDevice)o).getAddress()); + return mAddress.equals(((BluetoothDevice) o).getAddress()); } return false; } @@ -757,6 +788,7 @@ public final class BluetoothDevice implements Parcelable { * "00:11:22:AA:BB:CC". However, you should always use {@link #getAddress} * if you explicitly require the Bluetooth hardware address in case the * {@link #toString} representation changes in the future. + * * @return string representation of this BluetoothDevice */ @Override @@ -764,20 +796,23 @@ public final class BluetoothDevice implements Parcelable { return mAddress; } + @Override public int describeContents() { return 0; } public static final Parcelable.Creator<BluetoothDevice> CREATOR = new Parcelable.Creator<BluetoothDevice>() { - public BluetoothDevice createFromParcel(Parcel in) { - return new BluetoothDevice(in.readString()); - } - public BluetoothDevice[] newArray(int size) { - return new BluetoothDevice[size]; - } - }; + public BluetoothDevice createFromParcel(Parcel in) { + return new BluetoothDevice(in.readString()); + } + + public BluetoothDevice[] newArray(int size) { + return new BluetoothDevice[size]; + } + }; + @Override public void writeToParcel(Parcel out, int flags) { out.writeString(mAddress); } @@ -785,6 +820,7 @@ public final class BluetoothDevice implements Parcelable { /** * Returns the hardware address of this BluetoothDevice. * <p> For example, "00:11:22:AA:BB:CC". + * * @return Bluetooth hardware address as string */ public String getAddress() { @@ -809,16 +845,17 @@ public final class BluetoothDevice implements Parcelable { } try { return sService.getRemoteName(this); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return null; } /** * Get the Bluetooth device type of the remote device. * - * @return the device type {@link #DEVICE_TYPE_CLASSIC}, {@link #DEVICE_TYPE_LE} - * {@link #DEVICE_TYPE_DUAL}. - * {@link #DEVICE_TYPE_UNKNOWN} if it's not available + * @return the device type {@link #DEVICE_TYPE_CLASSIC}, {@link #DEVICE_TYPE_LE} {@link + * #DEVICE_TYPE_DUAL}. {@link #DEVICE_TYPE_UNKNOWN} if it's not available */ @RequiresPermission(Manifest.permission.BLUETOOTH) public int getType() { @@ -828,7 +865,9 @@ public final class BluetoothDevice implements Parcelable { } try { return sService.getRemoteType(this); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return DEVICE_TYPE_UNKNOWN; } @@ -846,7 +885,9 @@ public final class BluetoothDevice implements Parcelable { } try { return sService.getRemoteAlias(this); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return null; } @@ -867,18 +908,20 @@ public final class BluetoothDevice implements Parcelable { } try { return sService.setRemoteAlias(this, alias); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return false; } /** * Get the Bluetooth alias of the remote device. * If Alias is null, get the Bluetooth name instead. - * @see #getAlias() - * @see #getName() * * @return the Bluetooth alias, or null if no alias or there was a problem * @hide + * @see #getAlias() + * @see #getName() */ public String getAliasName() { String name = getAlias(); @@ -893,8 +936,8 @@ public final class BluetoothDevice implements Parcelable { * <p>Requires {@link android.Manifest.permission#BLUETOOTH} * * @return Battery level in percents from 0 to 100, or {@link #BATTERY_LEVEL_UNKNOWN} if - * Bluetooth is disabled, or device is disconnected, or does not have any battery - * reporting service, or return value is invalid + * Bluetooth is disabled, or device is disconnected, or does not have any battery reporting + * service, or return value is invalid * @hide */ @RequiresPermission(Manifest.permission.BLUETOOTH) @@ -905,7 +948,9 @@ public final class BluetoothDevice implements Parcelable { } try { return sService.getBatteryLevel(this); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return BATTERY_LEVEL_UNKNOWN; } @@ -926,11 +971,13 @@ public final class BluetoothDevice implements Parcelable { return false; } try { - Log.i(TAG, "createBond() for device " + getAddress() + - " called by pid: " + Process.myPid() + - " tid: " + Process.myTid()); + Log.i(TAG, "createBond() for device " + getAddress() + + " called by pid: " + Process.myPid() + + " tid: " + Process.myTid()); return sService.createBond(this, TRANSPORT_AUTO); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return false; } @@ -955,16 +1002,17 @@ public final class BluetoothDevice implements Parcelable { Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device"); return false; } - if (TRANSPORT_AUTO > transport || transport > TRANSPORT_LE) - { + if (TRANSPORT_AUTO > transport || transport > TRANSPORT_LE) { throw new IllegalArgumentException(transport + " is not a valid Bluetooth transport"); } try { - Log.i(TAG, "createBond() for device " + getAddress() + - " called by pid: " + Process.myPid() + - " tid: " + Process.myTid()); + Log.i(TAG, "createBond() for device " + getAddress() + + " called by pid: " + Process.myPid() + + " tid: " + Process.myTid()); return sService.createBond(this, transport); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return false; } @@ -984,13 +1032,14 @@ public final class BluetoothDevice implements Parcelable { * @param transport - Transport to use * @param oobData - Out Of Band data * @return false on immediate error, true if bonding will begin - * * @hide */ public boolean createBondOutOfBand(int transport, OobData oobData) { try { return sService.createBondOutOfBand(this, transport, oobData); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return false; } @@ -998,7 +1047,9 @@ public final class BluetoothDevice implements Parcelable { public boolean isBondingInitiatedLocally() { try { return sService.isBondingInitiatedLocally(this); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return false; } @@ -1012,16 +1063,15 @@ public final class BluetoothDevice implements Parcelable { * @param hash Simple Secure pairing hash * @param randomizer The random key obtained using OOB * @return false on error; true otherwise - * * @hide */ public boolean setDeviceOutOfBandData(byte[] hash, byte[] randomizer) { - //TODO(BT) + //TODO(BT) /* try { return sService.setDeviceOutOfBandData(this, hash, randomizer); } catch (RemoteException e) {Log.e(TAG, "", e);} */ - return false; + return false; } /** @@ -1037,11 +1087,13 @@ public final class BluetoothDevice implements Parcelable { return false; } try { - Log.i(TAG, "cancelBondProcess() for device " + getAddress() + - " called by pid: " + Process.myPid() + - " tid: " + Process.myTid()); + Log.i(TAG, "cancelBondProcess() for device " + getAddress() + + " called by pid: " + Process.myPid() + + " tid: " + Process.myTid()); return sService.cancelBondProcess(this); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return false; } @@ -1061,11 +1113,13 @@ public final class BluetoothDevice implements Parcelable { return false; } try { - Log.i(TAG, "removeBond() for device " + getAddress() + - " called by pid: " + Process.myPid() + - " tid: " + Process.myTid()); + Log.i(TAG, "removeBond() for device " + getAddress() + + " called by pid: " + Process.myPid() + + " tid: " + Process.myTid()); return sService.removeBond(this); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return false; } @@ -1086,12 +1140,13 @@ public final class BluetoothDevice implements Parcelable { } try { return sService.getBondState(this); - } catch (RemoteException e) {Log.e(TAG, "", e);} - catch (NullPointerException npe) { + } catch (RemoteException e) { + Log.e(TAG, "", e); + } catch (NullPointerException npe) { // Handle case where bluetooth service proxy // is already null. - Log.e(TAG, "NullPointerException for getBondState() of device ("+ - getAddress()+")", npe); + Log.e(TAG, "NullPointerException for getBondState() of device (" + + getAddress() + ")", npe); } return BOND_NONE; } @@ -1154,7 +1209,9 @@ public final class BluetoothDevice implements Parcelable { int classInt = sService.getRemoteClass(this); if (classInt == BluetoothClass.ERROR) return null; return new BluetoothClass(classInt); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return null; } @@ -1166,86 +1223,89 @@ public final class BluetoothDevice implements Parcelable { * UUIDs are returned. * <p>Use {@link #fetchUuidsWithSdp} if fresh UUIDs are desired. * - * @return the supported features (UUIDs) of the remote device, - * or null on error + * @return the supported features (UUIDs) of the remote device, or null on error */ @RequiresPermission(Manifest.permission.BLUETOOTH) - public ParcelUuid[] getUuids() { - if (sService == null || isBluetoothEnabled() == false) { + public ParcelUuid[] getUuids() { + if (sService == null || !isBluetoothEnabled()) { Log.e(TAG, "BT not enabled. Cannot get remote device Uuids"); - return null; - } + return null; + } try { return sService.getRemoteUuids(this); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return null; } - /** - * Perform a service discovery on the remote device to get the UUIDs supported. - * - * <p>This API is asynchronous and {@link #ACTION_UUID} intent is sent, - * with the UUIDs supported by the remote end. If there is an error - * in getting the SDP records or if the process takes a long time, - * {@link #ACTION_UUID} intent is sent with the UUIDs that is currently - * present in the cache. Clients should use the {@link #getUuids} to get UUIDs - * if service discovery is not to be performed. - * - * @return False if the sanity check fails, True if the process - * of initiating an ACL connection to the remote device - * was started. - */ - @RequiresPermission(Manifest.permission.BLUETOOTH) - public boolean fetchUuidsWithSdp() { + /** + * Perform a service discovery on the remote device to get the UUIDs supported. + * + * <p>This API is asynchronous and {@link #ACTION_UUID} intent is sent, + * with the UUIDs supported by the remote end. If there is an error + * in getting the SDP records or if the process takes a long time, + * {@link #ACTION_UUID} intent is sent with the UUIDs that is currently + * present in the cache. Clients should use the {@link #getUuids} to get UUIDs + * if service discovery is not to be performed. + * + * @return False if the sanity check fails, True if the process of initiating an ACL connection + * to the remote device was started. + */ + @RequiresPermission(Manifest.permission.BLUETOOTH) + public boolean fetchUuidsWithSdp() { IBluetooth service = sService; - if (service == null || isBluetoothEnabled() == false) { + if (service == null || !isBluetoothEnabled()) { Log.e(TAG, "BT not enabled. Cannot fetchUuidsWithSdp"); return false; } try { return service.fetchRemoteUuids(this); - } catch (RemoteException e) {Log.e(TAG, "", e);} - return false; + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + return false; } - /** - * Perform a service discovery on the remote device to get the SDP records associated - * with the specified UUID. - * - * <p>This API is asynchronous and {@link #ACTION_SDP_RECORD} intent is sent, - * with the SDP records found on the remote end. If there is an error - * in getting the SDP records or if the process takes a long time, - * {@link #ACTION_SDP_RECORD} intent is sent with an status value in - * {@link #EXTRA_SDP_SEARCH_STATUS} different from 0. - * Detailed status error codes can be found by members of the Bluetooth package in - * the AbstractionLayer class. - * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. - * The SDP record data will be stored in the intent as {@link #EXTRA_SDP_RECORD}. - * The object type will match one of the SdpXxxRecord types, depending on the UUID searched - * for. - * - * @return False if the sanity check fails, True if the process - * of initiating an ACL connection to the remote device - * was started. - */ - /** @hide */ - public boolean sdpSearch(ParcelUuid uuid) { - if (sService == null) { - Log.e(TAG, "BT not enabled. Cannot query remote device sdp records"); - return false; - } - try { - return sService.sdpSearch(this,uuid); - } catch (RemoteException e) {Log.e(TAG, "", e);} - return false; - } + /** + * Perform a service discovery on the remote device to get the SDP records associated + * with the specified UUID. + * + * <p>This API is asynchronous and {@link #ACTION_SDP_RECORD} intent is sent, + * with the SDP records found on the remote end. If there is an error + * in getting the SDP records or if the process takes a long time, + * {@link #ACTION_SDP_RECORD} intent is sent with an status value in + * {@link #EXTRA_SDP_SEARCH_STATUS} different from 0. + * Detailed status error codes can be found by members of the Bluetooth package in + * the AbstractionLayer class. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. + * The SDP record data will be stored in the intent as {@link #EXTRA_SDP_RECORD}. + * The object type will match one of the SdpXxxRecord types, depending on the UUID searched + * for. + * + * @return False if the sanity check fails, True if the process + * of initiating an ACL connection to the remote device + * was started. + */ + /** @hide */ + public boolean sdpSearch(ParcelUuid uuid) { + if (sService == null) { + Log.e(TAG, "BT not enabled. Cannot query remote device sdp records"); + return false; + } + try { + return sService.sdpSearch(this, uuid); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + return false; + } /** * Set the pin during pairing when the pairing method is {@link #PAIRING_VARIANT_PIN} * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. * - * @return true pin has been set - * false for error + * @return true pin has been set false for error */ public boolean setPin(byte[] pin) { if (sService == null) { @@ -1254,7 +1314,9 @@ public final class BluetoothDevice implements Parcelable { } try { return sService.setPin(this, true, pin.length, pin); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return false; } @@ -1271,8 +1333,7 @@ public final class BluetoothDevice implements Parcelable { /** * Confirm passkey for {@link #PAIRING_VARIANT_PASSKEY_CONFIRMATION} pairing. * - * @return true confirmation has been sent out - * false for error + * @return true confirmation has been sent out false for error */ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setPairingConfirmation(boolean confirm) { @@ -1282,7 +1343,9 @@ public final class BluetoothDevice implements Parcelable { } try { return sService.setPairingConfirmation(this, confirm); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return false; } @@ -1293,7 +1356,7 @@ public final class BluetoothDevice implements Parcelable { try { return sService.setRemoteOutOfBandData(this); } catch (RemoteException e) {Log.e(TAG, "", e);}*/ - return false; + return false; } /** @hide */ @@ -1304,7 +1367,9 @@ public final class BluetoothDevice implements Parcelable { } try { return sService.cancelBondProcess(this); - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return false; } @@ -1318,19 +1383,20 @@ public final class BluetoothDevice implements Parcelable { return false; } - boolean isBluetoothEnabled() { - boolean ret = false; - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - if (adapter != null && adapter.isEnabled() == true) { - ret = true; - } - return ret; - } + boolean isBluetoothEnabled() { + boolean ret = false; + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + if (adapter != null && adapter.isEnabled()) { + ret = true; + } + return ret; + } /** * Requires {@link android.Manifest.permission#BLUETOOTH}. - * @return Whether the phonebook access is allowed to this device. Can be - * {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}. + * + * @return Whether the phonebook access is allowed to this device. Can be {@link + * #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}. * @hide */ public int getPhonebookAccessPermission() { @@ -1348,8 +1414,9 @@ public final class BluetoothDevice implements Parcelable { /** * Sets whether the phonebook access is allowed to this device. * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. - * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or - * {@link #ACCESS_REJECTED}. + * + * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link + * #ACCESS_REJECTED}. * @return Whether the value has been successfully set. * @hide */ @@ -1367,8 +1434,9 @@ public final class BluetoothDevice implements Parcelable { /** * Requires {@link android.Manifest.permission#BLUETOOTH}. - * @return Whether the message access is allowed to this device. Can be - * {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}. + * + * @return Whether the message access is allowed to this device. Can be {@link #ACCESS_UNKNOWN}, + * {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}. * @hide */ public int getMessageAccessPermission() { @@ -1386,8 +1454,9 @@ public final class BluetoothDevice implements Parcelable { /** * Sets whether the message access is allowed to this device. * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. - * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or - * {@link #ACCESS_REJECTED}. + * + * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link + * #ACCESS_REJECTED}. * @return Whether the value has been successfully set. * @hide */ @@ -1405,8 +1474,9 @@ public final class BluetoothDevice implements Parcelable { /** * Requires {@link android.Manifest.permission#BLUETOOTH}. - * @return Whether the Sim access is allowed to this device. Can be - * {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}. + * + * @return Whether the Sim access is allowed to this device. Can be {@link #ACCESS_UNKNOWN}, + * {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}. * @hide */ public int getSimAccessPermission() { @@ -1424,8 +1494,9 @@ public final class BluetoothDevice implements Parcelable { /** * Sets whether the Sim access is allowed to this device. * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. - * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or - * {@link #ACCESS_REJECTED}. + * + * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link + * #ACCESS_REJECTED}. * @return Whether the value has been successfully set. * @hide */ @@ -1462,12 +1533,12 @@ public final class BluetoothDevice implements Parcelable { * * @param channel RFCOMM channel to connect to * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection - * @throws IOException on error, for example Bluetooth not available, or - * insufficient permissions + * @throws IOException on error, for example Bluetooth not available, or insufficient + * permissions * @hide */ public BluetoothSocket createRfcommSocket(int channel) throws IOException { - if (isBluetoothEnabled() == false) { + if (!isBluetoothEnabled()) { Log.e(TAG, "Bluetooth is not enabled"); throw new IOException(); } @@ -1496,8 +1567,8 @@ public final class BluetoothDevice implements Parcelable { * * @param channel L2cap PSM/channel to connect to * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection - * @throws IOException on error, for example Bluetooth not available, or - * insufficient permissions + * @throws IOException on error, for example Bluetooth not available, or insufficient + * permissions * @hide */ public BluetoothSocket createL2capSocket(int channel) throws IOException { @@ -1517,8 +1588,8 @@ public final class BluetoothDevice implements Parcelable { * * @param channel L2cap PSM/channel to connect to * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection - * @throws IOException on error, for example Bluetooth not available, or - * insufficient permissions + * @throws IOException on error, for example Bluetooth not available, or insufficient + * permissions * @hide */ public BluetoothSocket createInsecureL2capSocket(int channel) throws IOException { @@ -1553,12 +1624,12 @@ public final class BluetoothDevice implements Parcelable { * * @param uuid service record uuid to lookup RFCOMM channel * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection - * @throws IOException on error, for example Bluetooth not available, or - * insufficient permissions + * @throws IOException on error, for example Bluetooth not available, or insufficient + * permissions */ @RequiresPermission(Manifest.permission.BLUETOOTH) public BluetoothSocket createRfcommSocketToServiceRecord(UUID uuid) throws IOException { - if (isBluetoothEnabled() == false) { + if (!isBluetoothEnabled()) { Log.e(TAG, "Bluetooth is not enabled"); throw new IOException(); } @@ -1591,12 +1662,12 @@ public final class BluetoothDevice implements Parcelable { * * @param uuid service record uuid to lookup RFCOMM channel * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection - * @throws IOException on error, for example Bluetooth not available, or - * insufficient permissions + * @throws IOException on error, for example Bluetooth not available, or insufficient + * permissions */ @RequiresPermission(Manifest.permission.BLUETOOTH) public BluetoothSocket createInsecureRfcommSocketToServiceRecord(UUID uuid) throws IOException { - if (isBluetoothEnabled() == false) { + if (!isBluetoothEnabled()) { Log.e(TAG, "Bluetooth is not enabled"); throw new IOException(); } @@ -1612,15 +1683,14 @@ public final class BluetoothDevice implements Parcelable { * socket will not be encrypted. * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} * - * @param port remote port + * @param port remote port * @return An RFCOMM BluetoothSocket - * @throws IOException On error, for example Bluetooth not available, or - * insufficient permissions. + * @throws IOException On error, for example Bluetooth not available, or insufficient + * permissions. * @hide */ public BluetoothSocket createInsecureRfcommSocket(int port) throws IOException { - - if (isBluetoothEnabled() == false) { + if (!isBluetoothEnabled()) { Log.e(TAG, "Bluetooth is not enabled"); throw new IOException(); } @@ -1634,13 +1704,12 @@ public final class BluetoothDevice implements Parcelable { * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} * * @return a SCO BluetoothSocket - * @throws IOException on error, for example Bluetooth not available, or - * insufficient permissions. + * @throws IOException on error, for example Bluetooth not available, or insufficient + * permissions. * @hide */ public BluetoothSocket createScoSocket() throws IOException { - - if (isBluetoothEnabled() == false) { + if (!isBluetoothEnabled()) { Log.e(TAG, "Bluetooth is not enabled"); throw new IOException(); } @@ -1651,9 +1720,9 @@ public final class BluetoothDevice implements Parcelable { * Check that a pin is valid and convert to byte array. * * Bluetooth pin's are 1 to 16 bytes of UTF-8 characters. + * * @param pin pin as java String - * @return the pin code as a UTF-8 byte array, or null if it is an invalid - * Bluetooth pin. + * @return the pin code as a UTF-8 byte array, or null if it is an invalid Bluetooth pin. * @hide */ public static byte[] convertPinToBytes(String pin) { @@ -1679,15 +1748,15 @@ public final class BluetoothDevice implements Parcelable { * as any further GATT client operations. * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct * GATT client operations. + * * @param callback GATT callback handler that will receive asynchronous callbacks. - * @param autoConnect Whether to directly connect to the remote device (false) - * or to automatically connect as soon as the remote - * device becomes available (true). + * @param autoConnect Whether to directly connect to the remote device (false) or to + * automatically connect as soon as the remote device becomes available (true). * @throws IllegalArgumentException if callback is null */ public BluetoothGatt connectGatt(Context context, boolean autoConnect, - BluetoothGattCallback callback) { - return (connectGatt(context, autoConnect,callback, TRANSPORT_AUTO)); + BluetoothGattCallback callback) { + return (connectGatt(context, autoConnect, callback, TRANSPORT_AUTO)); } /** @@ -1696,18 +1765,18 @@ public final class BluetoothDevice implements Parcelable { * as any further GATT client operations. * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct * GATT client operations. + * * @param callback GATT callback handler that will receive asynchronous callbacks. - * @param autoConnect Whether to directly connect to the remote device (false) - * or to automatically connect as soon as the remote - * device becomes available (true). - * @param transport preferred transport for GATT connections to remote dual-mode devices - * {@link BluetoothDevice#TRANSPORT_AUTO} or - * {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE} + * @param autoConnect Whether to directly connect to the remote device (false) or to + * automatically connect as soon as the remote device becomes available (true). + * @param transport preferred transport for GATT connections to remote dual-mode devices {@link + * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link + * BluetoothDevice#TRANSPORT_LE} * @throws IllegalArgumentException if callback is null */ public BluetoothGatt connectGatt(Context context, boolean autoConnect, - BluetoothGattCallback callback, int transport) { - return (connectGatt(context, autoConnect,callback, transport, PHY_LE_1M_MASK)); + BluetoothGattCallback callback, int transport) { + return (connectGatt(context, autoConnect, callback, transport, PHY_LE_1M_MASK)); } /** @@ -1716,22 +1785,22 @@ public final class BluetoothDevice implements Parcelable { * as any further GATT client operations. * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct * GATT client operations. + * * @param callback GATT callback handler that will receive asynchronous callbacks. - * @param autoConnect Whether to directly connect to the remote device (false) - * or to automatically connect as soon as the remote - * device becomes available (true). - * @param transport preferred transport for GATT connections to remote dual-mode devices - * {@link BluetoothDevice#TRANSPORT_AUTO} or - * {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE} - * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of - * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, - * and {@link BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect - * if {@code autoConnect} is set to true. + * @param autoConnect Whether to directly connect to the remote device (false) or to + * automatically connect as soon as the remote device becomes available (true). + * @param transport preferred transport for GATT connections to remote dual-mode devices {@link + * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link + * BluetoothDevice#TRANSPORT_LE} + * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of {@link + * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, and {@link + * BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if {@code autoConnect} + * is set to true. * @throws NullPointerException if callback is null */ public BluetoothGatt connectGatt(Context context, boolean autoConnect, - BluetoothGattCallback callback, int transport, int phy) { - return connectGatt(context, autoConnect,callback, transport, phy, null); + BluetoothGattCallback callback, int transport, int phy) { + return connectGatt(context, autoConnect, callback, transport, phy, null); } /** @@ -1740,24 +1809,24 @@ public final class BluetoothDevice implements Parcelable { * as any further GATT client operations. * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct * GATT client operations. + * * @param callback GATT callback handler that will receive asynchronous callbacks. - * @param autoConnect Whether to directly connect to the remote device (false) - * or to automatically connect as soon as the remote - * device becomes available (true). - * @param transport preferred transport for GATT connections to remote dual-mode devices - * {@link BluetoothDevice#TRANSPORT_AUTO} or - * {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE} - * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of - * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, - * an d{@link BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect - * if {@code autoConnect} is set to true. - * @param handler The handler to use for the callback. If {@code null}, callbacks will happen - * on an un-specified background thread. + * @param autoConnect Whether to directly connect to the remote device (false) or to + * automatically connect as soon as the remote device becomes available (true). + * @param transport preferred transport for GATT connections to remote dual-mode devices {@link + * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link + * BluetoothDevice#TRANSPORT_LE} + * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of {@link + * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, an d{@link + * BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if {@code autoConnect} + * is set to true. + * @param handler The handler to use for the callback. If {@code null}, callbacks will happen on + * an un-specified background thread. * @throws NullPointerException if callback is null */ public BluetoothGatt connectGatt(Context context, boolean autoConnect, - BluetoothGattCallback callback, int transport, int phy, - Handler handler) { + BluetoothGattCallback callback, int transport, int phy, + Handler handler) { return connectGatt(context, autoConnect, callback, transport, false, phy, handler); } @@ -1767,31 +1836,32 @@ public final class BluetoothDevice implements Parcelable { * as any further GATT client operations. * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct * GATT client operations. + * * @param callback GATT callback handler that will receive asynchronous callbacks. - * @param autoConnect Whether to directly connect to the remote device (false) - * or to automatically connect as soon as the remote - * device becomes available (true). - * @param transport preferred transport for GATT connections to remote dual-mode devices - * {@link BluetoothDevice#TRANSPORT_AUTO} or - * {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE} + * @param autoConnect Whether to directly connect to the remote device (false) or to + * automatically connect as soon as the remote device becomes available (true). + * @param transport preferred transport for GATT connections to remote dual-mode devices {@link + * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link + * BluetoothDevice#TRANSPORT_LE} * @param opportunistic Whether this GATT client is opportunistic. An opportunistic GATT client - * does not hold a GATT connection. It automatically disconnects when no - * other GATT connections are active for the remote device. - * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of - * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, - * an d{@link BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect - * if {@code autoConnect} is set to true. - * @param handler The handler to use for the callback. If {@code null}, callbacks will happen - * on an un-specified background thread. + * does not hold a GATT connection. It automatically disconnects when no other GATT connections + * are active for the remote device. + * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of {@link + * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, an d{@link + * BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if {@code autoConnect} + * is set to true. + * @param handler The handler to use for the callback. If {@code null}, callbacks will happen on + * an un-specified background thread. * @return A BluetoothGatt instance. You can use BluetoothGatt to conduct GATT client - * operations. + * operations. * @hide */ public BluetoothGatt connectGatt(Context context, boolean autoConnect, - BluetoothGattCallback callback, int transport, - boolean opportunistic, int phy, Handler handler) { - if (callback == null) + BluetoothGattCallback callback, int transport, + boolean opportunistic, int phy, Handler handler) { + if (callback == null) { throw new NullPointerException("callback is null"); + } // TODO(Bluetooth) check whether platform support BLE // Do the check here or in GattServer? @@ -1806,7 +1876,9 @@ public final class BluetoothDevice implements Parcelable { BluetoothGatt gatt = new BluetoothGatt(iGatt, this, transport, opportunistic, phy); gatt.connect(autoConnect, callback, handler); return gatt; - } catch (RemoteException e) {Log.e(TAG, "", e);} + } catch (RemoteException e) { + Log.e(TAG, "", e); + } return null; } } diff --git a/core/java/android/bluetooth/BluetoothDevicePicker.java b/core/java/android/bluetooth/BluetoothDevicePicker.java index c794be2e2c9e..09b0a80313f6 100644 --- a/core/java/android/bluetooth/BluetoothDevicePicker.java +++ b/core/java/android/bluetooth/BluetoothDevicePicker.java @@ -48,11 +48,11 @@ public interface BluetoothDevicePicker { * This intent contains below extra data: * - {@link #EXTRA_NEED_AUTH} (boolean): if need authentication * - {@link #EXTRA_FILTER_TYPE} (int): what kinds of device should be - * listed + * listed * - {@link #EXTRA_LAUNCH_PACKAGE} (string): where(which package) this - * intent come from + * intent come from * - {@link #EXTRA_LAUNCH_CLASS} (string): where(which class) this intent - * come from + * come from */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_LAUNCH = @@ -64,8 +64,10 @@ public interface BluetoothDevicePicker { public static final int FILTER_TYPE_AUDIO = 1; /** Ask device picker to show BT devices that support Object Transfer */ public static final int FILTER_TYPE_TRANSFER = 2; - /** Ask device picker to show BT devices that support - * Personal Area Networking User (PANU) profile*/ + /** + * Ask device picker to show BT devices that support + * Personal Area Networking User (PANU) profile + */ public static final int FILTER_TYPE_PANU = 3; /** Ask device picker to show BT devices that support Network Access Point (NAP) profile */ public static final int FILTER_TYPE_NAP = 4; diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java index 678159b71296..759d772920ba 100644 --- a/core/java/android/bluetooth/BluetoothGatt.java +++ b/core/java/android/bluetooth/BluetoothGatt.java @@ -118,18 +118,21 @@ public final class BluetoothGatt implements BluetoothProfile { /** * No authentication required. + * * @hide */ /*package*/ static final int AUTHENTICATION_NONE = 0; /** * Authentication requested; no man-in-the-middle protection required. + * * @hide */ /*package*/ static final int AUTHENTICATION_NO_MITM = 1; /** * Authentication with man-in-the-middle protection requested. + * * @hide */ /*package*/ static final int AUTHENTICATION_MITM = 2; @@ -138,498 +141,536 @@ public final class BluetoothGatt implements BluetoothProfile { * Bluetooth GATT callbacks. Overrides the default BluetoothGattCallback implementation. */ private final IBluetoothGattCallback mBluetoothGattCallback = - new IBluetoothGattCallback.Stub() { - /** - * Application interface registered - app is ready to go - * @hide - */ - @Override - public void onClientRegistered(int status, int clientIf) { - if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status - + " clientIf=" + clientIf); - if (VDBG) { - synchronized(mStateLock) { - if (mConnState != CONN_STATE_CONNECTING) { - Log.e(TAG, "Bad connection state: " + mConnState); + new IBluetoothGattCallback.Stub() { + /** + * Application interface registered - app is ready to go + * @hide + */ + @Override + public void onClientRegistered(int status, int clientIf) { + if (DBG) { + Log.d(TAG, "onClientRegistered() - status=" + status + + " clientIf=" + clientIf); + } + if (VDBG) { + synchronized (mStateLock) { + if (mConnState != CONN_STATE_CONNECTING) { + Log.e(TAG, "Bad connection state: " + mConnState); + } } } + mClientIf = clientIf; + if (status != GATT_SUCCESS) { + runOrQueueCallback(new Runnable() { + @Override + public void run() { + if (mCallback != null) { + mCallback.onConnectionStateChange(BluetoothGatt.this, + GATT_FAILURE, + BluetoothProfile.STATE_DISCONNECTED); + } + } + }); + + synchronized (mStateLock) { + mConnState = CONN_STATE_IDLE; + } + return; + } + try { + mService.clientConnect(mClientIf, mDevice.getAddress(), + !mAutoConnect, mTransport, mOpportunistic, + mPhy); // autoConnect is inverse of "isDirect" + } catch (RemoteException e) { + Log.e(TAG, "", e); + } } - mClientIf = clientIf; - if (status != GATT_SUCCESS) { + + /** + * Phy update callback + * @hide + */ + @Override + public void onPhyUpdate(String address, int txPhy, int rxPhy, int status) { + if (DBG) { + Log.d(TAG, "onPhyUpdate() - status=" + status + + " address=" + address + " txPhy=" + txPhy + " rxPhy=" + rxPhy); + } + if (!address.equals(mDevice.getAddress())) { + return; + } + runOrQueueCallback(new Runnable() { @Override public void run() { if (mCallback != null) { - mCallback.onConnectionStateChange(BluetoothGatt.this, GATT_FAILURE, - BluetoothProfile.STATE_DISCONNECTED); + mCallback.onPhyUpdate(BluetoothGatt.this, txPhy, rxPhy, status); } } }); + } - synchronized(mStateLock) { - mConnState = CONN_STATE_IDLE; + /** + * Phy read callback + * @hide + */ + @Override + public void onPhyRead(String address, int txPhy, int rxPhy, int status) { + if (DBG) { + Log.d(TAG, "onPhyRead() - status=" + status + + " address=" + address + " txPhy=" + txPhy + " rxPhy=" + rxPhy); + } + if (!address.equals(mDevice.getAddress())) { + return; } - return; - } - try { - mService.clientConnect(mClientIf, mDevice.getAddress(), - !mAutoConnect, mTransport, mOpportunistic, mPhy); // autoConnect is inverse of "isDirect" - } catch (RemoteException e) { - Log.e(TAG,"",e); - } - } - /** - * Phy update callback - * @hide - */ - @Override - public void onPhyUpdate(String address, int txPhy, int rxPhy, int status) { - if (DBG) Log.d(TAG, "onPhyUpdate() - status=" + status - + " address=" + address + " txPhy=" + txPhy + " rxPhy=" + rxPhy); - if (!address.equals(mDevice.getAddress())) { - return; + runOrQueueCallback(new Runnable() { + @Override + public void run() { + if (mCallback != null) { + mCallback.onPhyRead(BluetoothGatt.this, txPhy, rxPhy, status); + } + } + }); } - runOrQueueCallback(new Runnable() { - @Override - public void run() { - if (mCallback != null) { - mCallback.onPhyUpdate(BluetoothGatt.this, txPhy, rxPhy, status); - } + /** + * Client connection state changed + * @hide + */ + @Override + public void onClientConnectionState(int status, int clientIf, + boolean connected, String address) { + if (DBG) { + Log.d(TAG, "onClientConnectionState() - status=" + status + + " clientIf=" + clientIf + " device=" + address); } - }); - } - - /** - * Phy read callback - * @hide - */ - @Override - public void onPhyRead(String address, int txPhy, int rxPhy, int status) { - if (DBG) Log.d(TAG, "onPhyRead() - status=" + status - + " address=" + address + " txPhy=" + txPhy + " rxPhy=" + rxPhy); - if (!address.equals(mDevice.getAddress())) { - return; - } + if (!address.equals(mDevice.getAddress())) { + return; + } + int profileState = connected ? BluetoothProfile.STATE_CONNECTED : + BluetoothProfile.STATE_DISCONNECTED; - runOrQueueCallback(new Runnable() { - @Override - public void run() { - if (mCallback != null) { - mCallback.onPhyRead(BluetoothGatt.this, txPhy, rxPhy, status); + runOrQueueCallback(new Runnable() { + @Override + public void run() { + if (mCallback != null) { + mCallback.onConnectionStateChange(BluetoothGatt.this, status, + profileState); + } } - } - }); - } + }); - /** - * Client connection state changed - * @hide - */ - @Override - public void onClientConnectionState(int status, int clientIf, - boolean connected, String address) { - if (DBG) Log.d(TAG, "onClientConnectionState() - status=" + status - + " clientIf=" + clientIf + " device=" + address); - if (!address.equals(mDevice.getAddress())) { - return; - } - int profileState = connected ? BluetoothProfile.STATE_CONNECTED : - BluetoothProfile.STATE_DISCONNECTED; - - runOrQueueCallback(new Runnable() { - @Override - public void run() { - if (mCallback != null) { - mCallback.onConnectionStateChange(BluetoothGatt.this, status, - profileState); + synchronized (mStateLock) { + if (connected) { + mConnState = CONN_STATE_CONNECTED; + } else { + mConnState = CONN_STATE_IDLE; } } - }); - synchronized(mStateLock) { - if (connected) { - mConnState = CONN_STATE_CONNECTED; - } else { - mConnState = CONN_STATE_IDLE; + synchronized (mDeviceBusy) { + mDeviceBusy = false; } } - synchronized(mDeviceBusy) { - mDeviceBusy = false; - } - } - - /** - * Remote search has been completed. - * The internal object structure should now reflect the state - * of the remote device database. Let the application know that - * we are done at this point. - * @hide - */ - @Override - public void onSearchComplete(String address, List<BluetoothGattService> services, - int status) { - if (DBG) Log.d(TAG, "onSearchComplete() = Device=" + address + " Status=" + status); - if (!address.equals(mDevice.getAddress())) { - return; - } - - for (BluetoothGattService s : services) { - //services we receive don't have device set properly. - s.setDevice(mDevice); - } - - mServices.addAll(services); - - // Fix references to included services, as they doesn't point to right objects. - for (BluetoothGattService fixedService : mServices) { - ArrayList<BluetoothGattService> includedServices = - new ArrayList(fixedService.getIncludedServices()); - fixedService.getIncludedServices().clear(); + /** + * Remote search has been completed. + * The internal object structure should now reflect the state + * of the remote device database. Let the application know that + * we are done at this point. + * @hide + */ + @Override + public void onSearchComplete(String address, List<BluetoothGattService> services, + int status) { + if (DBG) { + Log.d(TAG, + "onSearchComplete() = Device=" + address + " Status=" + status); + } + if (!address.equals(mDevice.getAddress())) { + return; + } - for(BluetoothGattService brokenRef : includedServices) { - BluetoothGattService includedService = getService(mDevice, - brokenRef.getUuid(), brokenRef.getInstanceId(), brokenRef.getType()); - if (includedService != null) { - fixedService.addIncludedService(includedService); - } else { - Log.e(TAG, "Broken GATT database: can't find included service."); - } + for (BluetoothGattService s : services) { + //services we receive don't have device set properly. + s.setDevice(mDevice); } - } - runOrQueueCallback(new Runnable() { - @Override - public void run() { - if (mCallback != null) { - mCallback.onServicesDiscovered(BluetoothGatt.this, status); + mServices.addAll(services); + + // Fix references to included services, as they doesn't point to right objects. + for (BluetoothGattService fixedService : mServices) { + ArrayList<BluetoothGattService> includedServices = + new ArrayList(fixedService.getIncludedServices()); + fixedService.getIncludedServices().clear(); + + for (BluetoothGattService brokenRef : includedServices) { + BluetoothGattService includedService = getService(mDevice, + brokenRef.getUuid(), brokenRef.getInstanceId(), + brokenRef.getType()); + if (includedService != null) { + fixedService.addIncludedService(includedService); + } else { + Log.e(TAG, "Broken GATT database: can't find included service."); + } } } - }); - } - /** - * Remote characteristic has been read. - * Updates the internal value. - * @hide - */ - @Override - public void onCharacteristicRead(String address, int status, int handle, byte[] value) { - if (VDBG) Log.d(TAG, "onCharacteristicRead() - Device=" + address - + " handle=" + handle + " Status=" + status); - - if (!address.equals(mDevice.getAddress())) { - return; + runOrQueueCallback(new Runnable() { + @Override + public void run() { + if (mCallback != null) { + mCallback.onServicesDiscovered(BluetoothGatt.this, status); + } + } + }); } - synchronized(mDeviceBusy) { - mDeviceBusy = false; - } + /** + * Remote characteristic has been read. + * Updates the internal value. + * @hide + */ + @Override + public void onCharacteristicRead(String address, int status, int handle, + byte[] value) { + if (VDBG) { + Log.d(TAG, "onCharacteristicRead() - Device=" + address + + " handle=" + handle + " Status=" + status); + } - if ((status == GATT_INSUFFICIENT_AUTHENTICATION - || status == GATT_INSUFFICIENT_ENCRYPTION) - && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) { - try { - final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ? - AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM; - mService.readCharacteristic(mClientIf, address, handle, authReq); - mAuthRetryState++; + if (!address.equals(mDevice.getAddress())) { return; - } catch (RemoteException e) { - Log.e(TAG,"",e); } - } - mAuthRetryState = AUTH_RETRY_STATE_IDLE; + synchronized (mDeviceBusy) { + mDeviceBusy = false; + } - BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice, handle); - if (characteristic == null) { - Log.w(TAG, "onCharacteristicRead() failed to find characteristic!"); - return; - } + if ((status == GATT_INSUFFICIENT_AUTHENTICATION + || status == GATT_INSUFFICIENT_ENCRYPTION) + && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) { + try { + final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) + ? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM; + mService.readCharacteristic(mClientIf, address, handle, authReq); + mAuthRetryState++; + return; + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + } - if (status == 0) characteristic.setValue(value); + mAuthRetryState = AUTH_RETRY_STATE_IDLE; - runOrQueueCallback(new Runnable() { - @Override - public void run() { - if (mCallback != null) { - mCallback.onCharacteristicRead(BluetoothGatt.this, characteristic, - status); - } + BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice, + handle); + if (characteristic == null) { + Log.w(TAG, "onCharacteristicRead() failed to find characteristic!"); + return; } - }); - } - /** - * Characteristic has been written to the remote device. - * Let the app know how we did... - * @hide - */ - @Override - public void onCharacteristicWrite(String address, int status, int handle) { - if (VDBG) Log.d(TAG, "onCharacteristicWrite() - Device=" + address - + " handle=" + handle + " Status=" + status); - - if (!address.equals(mDevice.getAddress())) { - return; - } + if (status == 0) characteristic.setValue(value); - synchronized(mDeviceBusy) { - mDeviceBusy = false; + runOrQueueCallback(new Runnable() { + @Override + public void run() { + if (mCallback != null) { + mCallback.onCharacteristicRead(BluetoothGatt.this, characteristic, + status); + } + } + }); } - BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice, handle); - if (characteristic == null) return; + /** + * Characteristic has been written to the remote device. + * Let the app know how we did... + * @hide + */ + @Override + public void onCharacteristicWrite(String address, int status, int handle) { + if (VDBG) { + Log.d(TAG, "onCharacteristicWrite() - Device=" + address + + " handle=" + handle + " Status=" + status); + } - if ((status == GATT_INSUFFICIENT_AUTHENTICATION - || status == GATT_INSUFFICIENT_ENCRYPTION) - && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) { - try { - final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ? - AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM; - mService.writeCharacteristic(mClientIf, address, handle, - characteristic.getWriteType(), authReq, characteristic.getValue()); - mAuthRetryState++; + if (!address.equals(mDevice.getAddress())) { return; - } catch (RemoteException e) { - Log.e(TAG,"",e); } - } - mAuthRetryState = AUTH_RETRY_STATE_IDLE; + synchronized (mDeviceBusy) { + mDeviceBusy = false; + } - runOrQueueCallback(new Runnable() { - @Override - public void run() { - if (mCallback != null) { - mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic, - status); + BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice, + handle); + if (characteristic == null) return; + + if ((status == GATT_INSUFFICIENT_AUTHENTICATION + || status == GATT_INSUFFICIENT_ENCRYPTION) + && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) { + try { + final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) + ? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM; + mService.writeCharacteristic(mClientIf, address, handle, + characteristic.getWriteType(), authReq, + characteristic.getValue()); + mAuthRetryState++; + return; + } catch (RemoteException e) { + Log.e(TAG, "", e); } } - }); - } - /** - * Remote characteristic has been updated. - * Updates the internal value. - * @hide - */ - @Override - public void onNotify(String address, int handle, byte[] value) { - if (VDBG) Log.d(TAG, "onNotify() - Device=" + address + " handle=" + handle); - - if (!address.equals(mDevice.getAddress())) { - return; - } + mAuthRetryState = AUTH_RETRY_STATE_IDLE; - BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice, handle); - if (characteristic == null) return; + runOrQueueCallback(new Runnable() { + @Override + public void run() { + if (mCallback != null) { + mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic, + status); + } + } + }); + } - characteristic.setValue(value); + /** + * Remote characteristic has been updated. + * Updates the internal value. + * @hide + */ + @Override + public void onNotify(String address, int handle, byte[] value) { + if (VDBG) Log.d(TAG, "onNotify() - Device=" + address + " handle=" + handle); - runOrQueueCallback(new Runnable() { - @Override - public void run() { - if (mCallback != null) { - mCallback.onCharacteristicChanged(BluetoothGatt.this, characteristic); - } + if (!address.equals(mDevice.getAddress())) { + return; } - }); - } - /** - * Descriptor has been read. - * @hide - */ - @Override - public void onDescriptorRead(String address, int status, int handle, byte[] value) { - if (VDBG) Log.d(TAG, "onDescriptorRead() - Device=" + address + " handle=" + handle); + BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice, + handle); + if (characteristic == null) return; - if (!address.equals(mDevice.getAddress())) { - return; - } + characteristic.setValue(value); - synchronized(mDeviceBusy) { - mDeviceBusy = false; + runOrQueueCallback(new Runnable() { + @Override + public void run() { + if (mCallback != null) { + mCallback.onCharacteristicChanged(BluetoothGatt.this, + characteristic); + } + } + }); } - BluetoothGattDescriptor descriptor = getDescriptorById(mDevice, handle); - if (descriptor == null) return; - - if (status == 0) descriptor.setValue(value); + /** + * Descriptor has been read. + * @hide + */ + @Override + public void onDescriptorRead(String address, int status, int handle, byte[] value) { + if (VDBG) { + Log.d(TAG, + "onDescriptorRead() - Device=" + address + " handle=" + handle); + } - if ((status == GATT_INSUFFICIENT_AUTHENTICATION - || status == GATT_INSUFFICIENT_ENCRYPTION) - && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) { - try { - final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ? - AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM; - mService.readDescriptor(mClientIf, address, handle, authReq); - mAuthRetryState++; + if (!address.equals(mDevice.getAddress())) { return; - } catch (RemoteException e) { - Log.e(TAG,"",e); } - } - mAuthRetryState = AUTH_RETRY_STATE_IDLE; + synchronized (mDeviceBusy) { + mDeviceBusy = false; + } - runOrQueueCallback(new Runnable() { - @Override - public void run() { - if (mCallback != null) { - mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status); + BluetoothGattDescriptor descriptor = getDescriptorById(mDevice, handle); + if (descriptor == null) return; + + if (status == 0) descriptor.setValue(value); + + if ((status == GATT_INSUFFICIENT_AUTHENTICATION + || status == GATT_INSUFFICIENT_ENCRYPTION) + && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) { + try { + final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) + ? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM; + mService.readDescriptor(mClientIf, address, handle, authReq); + mAuthRetryState++; + return; + } catch (RemoteException e) { + Log.e(TAG, "", e); } } - }); - } - - /** - * Descriptor write operation complete. - * @hide - */ - @Override - public void onDescriptorWrite(String address, int status, int handle) { - if (VDBG) Log.d(TAG, "onDescriptorWrite() - Device=" + address + " handle=" + handle); - if (!address.equals(mDevice.getAddress())) { - return; - } + mAuthRetryState = AUTH_RETRY_STATE_IDLE; - synchronized(mDeviceBusy) { - mDeviceBusy = false; + runOrQueueCallback(new Runnable() { + @Override + public void run() { + if (mCallback != null) { + mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status); + } + } + }); } - BluetoothGattDescriptor descriptor = getDescriptorById(mDevice, handle); - if (descriptor == null) return; + /** + * Descriptor write operation complete. + * @hide + */ + @Override + public void onDescriptorWrite(String address, int status, int handle) { + if (VDBG) { + Log.d(TAG, + "onDescriptorWrite() - Device=" + address + " handle=" + handle); + } - if ((status == GATT_INSUFFICIENT_AUTHENTICATION - || status == GATT_INSUFFICIENT_ENCRYPTION) - && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) { - try { - final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ? - AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM; - mService.writeDescriptor(mClientIf, address, handle, - authReq, descriptor.getValue()); - mAuthRetryState++; + if (!address.equals(mDevice.getAddress())) { return; - } catch (RemoteException e) { - Log.e(TAG,"",e); } - } - mAuthRetryState = AUTH_RETRY_STATE_IDLE; + synchronized (mDeviceBusy) { + mDeviceBusy = false; + } - runOrQueueCallback(new Runnable() { - @Override - public void run() { - if (mCallback != null) { - mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status); + BluetoothGattDescriptor descriptor = getDescriptorById(mDevice, handle); + if (descriptor == null) return; + + if ((status == GATT_INSUFFICIENT_AUTHENTICATION + || status == GATT_INSUFFICIENT_ENCRYPTION) + && (mAuthRetryState != AUTH_RETRY_STATE_MITM)) { + try { + final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) + ? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM; + mService.writeDescriptor(mClientIf, address, handle, + authReq, descriptor.getValue()); + mAuthRetryState++; + return; + } catch (RemoteException e) { + Log.e(TAG, "", e); } } - }); - } - /** - * Prepared write transaction completed (or aborted) - * @hide - */ - @Override - public void onExecuteWrite(String address, int status) { - if (VDBG) Log.d(TAG, "onExecuteWrite() - Device=" + address - + " status=" + status); - if (!address.equals(mDevice.getAddress())) { - return; - } + mAuthRetryState = AUTH_RETRY_STATE_IDLE; - synchronized(mDeviceBusy) { - mDeviceBusy = false; + runOrQueueCallback(new Runnable() { + @Override + public void run() { + if (mCallback != null) { + mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status); + } + } + }); } - runOrQueueCallback(new Runnable() { - @Override - public void run() { - if (mCallback != null) { - mCallback.onReliableWriteCompleted(BluetoothGatt.this, status); - } + /** + * Prepared write transaction completed (or aborted) + * @hide + */ + @Override + public void onExecuteWrite(String address, int status) { + if (VDBG) { + Log.d(TAG, "onExecuteWrite() - Device=" + address + + " status=" + status); + } + if (!address.equals(mDevice.getAddress())) { + return; } - }); - } - /** - * Remote device RSSI has been read - * @hide - */ - @Override - public void onReadRemoteRssi(String address, int rssi, int status) { - if (VDBG) Log.d(TAG, "onReadRemoteRssi() - Device=" + address + - " rssi=" + rssi + " status=" + status); - if (!address.equals(mDevice.getAddress())) { - return; - } - runOrQueueCallback(new Runnable() { - @Override - public void run() { - if (mCallback != null) { - mCallback.onReadRemoteRssi(BluetoothGatt.this, rssi, status); - } + synchronized (mDeviceBusy) { + mDeviceBusy = false; } - }); - } - /** - * Callback invoked when the MTU for a given connection changes - * @hide - */ - @Override - public void onConfigureMTU(String address, int mtu, int status) { - if (DBG) Log.d(TAG, "onConfigureMTU() - Device=" + address + - " mtu=" + mtu + " status=" + status); - if (!address.equals(mDevice.getAddress())) { - return; + runOrQueueCallback(new Runnable() { + @Override + public void run() { + if (mCallback != null) { + mCallback.onReliableWriteCompleted(BluetoothGatt.this, status); + } + } + }); } - runOrQueueCallback(new Runnable() { - @Override - public void run() { - if (mCallback != null) { - mCallback.onMtuChanged(BluetoothGatt.this, mtu, status); + /** + * Remote device RSSI has been read + * @hide + */ + @Override + public void onReadRemoteRssi(String address, int rssi, int status) { + if (VDBG) { + Log.d(TAG, "onReadRemoteRssi() - Device=" + address + + " rssi=" + rssi + " status=" + status); + } + if (!address.equals(mDevice.getAddress())) { + return; + } + runOrQueueCallback(new Runnable() { + @Override + public void run() { + if (mCallback != null) { + mCallback.onReadRemoteRssi(BluetoothGatt.this, rssi, status); + } } + }); + } + + /** + * Callback invoked when the MTU for a given connection changes + * @hide + */ + @Override + public void onConfigureMTU(String address, int mtu, int status) { + if (DBG) { + Log.d(TAG, "onConfigureMTU() - Device=" + address + + " mtu=" + mtu + " status=" + status); + } + if (!address.equals(mDevice.getAddress())) { + return; } - }); - } - /** - * Callback invoked when the given connection is updated - * @hide - */ - @Override - public void onConnectionUpdated(String address, int interval, int latency, - int timeout, int status) { - if (DBG) Log.d(TAG, "onConnectionUpdated() - Device=" + address + - " interval=" + interval + " latency=" + latency + - " timeout=" + timeout + " status=" + status); - if (!address.equals(mDevice.getAddress())) { - return; + runOrQueueCallback(new Runnable() { + @Override + public void run() { + if (mCallback != null) { + mCallback.onMtuChanged(BluetoothGatt.this, mtu, status); + } + } + }); } - runOrQueueCallback(new Runnable() { - @Override - public void run() { - if (mCallback != null) { - mCallback.onConnectionUpdated(BluetoothGatt.this, interval, latency, - timeout, status); - } + /** + * Callback invoked when the given connection is updated + * @hide + */ + @Override + public void onConnectionUpdated(String address, int interval, int latency, + int timeout, int status) { + if (DBG) { + Log.d(TAG, "onConnectionUpdated() - Device=" + address + + " interval=" + interval + " latency=" + latency + + " timeout=" + timeout + " status=" + status); + } + if (!address.equals(mDevice.getAddress())) { + return; } - }); - } - }; + + runOrQueueCallback(new Runnable() { + @Override + public void run() { + if (mCallback != null) { + mCallback.onConnectionUpdated(BluetoothGatt.this, interval, latency, + timeout, status); + } + } + }); + } + }; /*package*/ BluetoothGatt(IBluetoothGatt iGatt, BluetoothDevice device, - int transport, boolean opportunistic, int phy) { + int transport, boolean opportunistic, int phy) { mService = iGatt; mDevice = device; mTransport = transport; @@ -657,15 +698,16 @@ public final class BluetoothGatt implements BluetoothProfile { /** * Returns a service by UUID, instance and type. + * * @hide */ /*package*/ BluetoothGattService getService(BluetoothDevice device, UUID uuid, - int instanceId, int type) { - for(BluetoothGattService svc : mServices) { - if (svc.getDevice().equals(device) && - svc.getType() == type && - svc.getInstanceId() == instanceId && - svc.getUuid().equals(uuid)) { + int instanceId, int type) { + for (BluetoothGattService svc : mServices) { + if (svc.getDevice().equals(device) + && svc.getType() == type + && svc.getInstanceId() == instanceId + && svc.getUuid().equals(uuid)) { return svc; } } @@ -675,13 +717,16 @@ public final class BluetoothGatt implements BluetoothProfile { /** * Returns a characteristic with id equal to instanceId. + * * @hide */ - /*package*/ BluetoothGattCharacteristic getCharacteristicById(BluetoothDevice device, int instanceId) { - for(BluetoothGattService svc : mServices) { - for(BluetoothGattCharacteristic charac : svc.getCharacteristics()) { - if (charac.getInstanceId() == instanceId) + /*package*/ BluetoothGattCharacteristic getCharacteristicById(BluetoothDevice device, + int instanceId) { + for (BluetoothGattService svc : mServices) { + for (BluetoothGattCharacteristic charac : svc.getCharacteristics()) { + if (charac.getInstanceId() == instanceId) { return charac; + } } } return null; @@ -689,14 +734,16 @@ public final class BluetoothGatt implements BluetoothProfile { /** * Returns a descriptor with id equal to instanceId. + * * @hide */ /*package*/ BluetoothGattDescriptor getDescriptorById(BluetoothDevice device, int instanceId) { - for(BluetoothGattService svc : mServices) { - for(BluetoothGattCharacteristic charac : svc.getCharacteristics()) { - for(BluetoothGattDescriptor desc : charac.getDescriptors()) { - if (desc.getInstanceId() == instanceId) + for (BluetoothGattService svc : mServices) { + for (BluetoothGattCharacteristic charac : svc.getCharacteristics()) { + for (BluetoothGattDescriptor desc : charac.getDescriptors()) { + if (desc.getInstanceId() == instanceId) { return desc; + } } } } @@ -709,13 +756,13 @@ public final class BluetoothGatt implements BluetoothProfile { */ private void runOrQueueCallback(final Runnable cb) { if (mHandler == null) { - try { - cb.run(); - } catch (Exception ex) { - Log.w(TAG, "Unhandled exception in callback", ex); - } + try { + cb.run(); + } catch (Exception ex) { + Log.w(TAG, "Unhandled exception in callback", ex); + } } else { - mHandler.post(cb); + mHandler.post(cb); } } @@ -728,8 +775,8 @@ public final class BluetoothGatt implements BluetoothProfile { * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param callback GATT callback handler that will receive asynchronous callbacks. - * @return If true, the callback will be called to notify success or failure, - * false on immediate error + * @return If true, the callback will be called to notify success or failure, false on immediate + * error */ private boolean registerApp(BluetoothGattCallback callback, Handler handler) { if (DBG) Log.d(TAG, "registerApp()"); @@ -743,7 +790,7 @@ public final class BluetoothGatt implements BluetoothProfile { try { mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); return false; } @@ -762,7 +809,7 @@ public final class BluetoothGatt implements BluetoothProfile { mService.unregisterClient(mClientIf); mClientIf = 0; } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -784,15 +831,17 @@ public final class BluetoothGatt implements BluetoothProfile { * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param device Remote device to connect to - * @param autoConnect Whether to directly connect to the remote device (false) - * or to automatically connect as soon as the remote - * device becomes available (true). + * @param autoConnect Whether to directly connect to the remote device (false) or to + * automatically connect as soon as the remote device becomes available (true). * @return true, if the connection attempt was initiated successfully */ /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback, - Handler handler) { - if (DBG) Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect); - synchronized(mStateLock) { + Handler handler) { + if (DBG) { + Log.d(TAG, + "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect); + } + synchronized (mStateLock) { if (mConnState != CONN_STATE_IDLE) { throw new IllegalStateException("Not idle"); } @@ -802,7 +851,7 @@ public final class BluetoothGatt implements BluetoothProfile { mAutoConnect = autoConnect; if (!registerApp(callback, handler)) { - synchronized(mStateLock) { + synchronized (mStateLock) { mConnState = CONN_STATE_IDLE; } Log.e(TAG, "Failed to register callback"); @@ -826,7 +875,7 @@ public final class BluetoothGatt implements BluetoothProfile { try { mService.clientDisconnect(mClientIf, mDevice.getAddress()); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -845,7 +894,7 @@ public final class BluetoothGatt implements BluetoothProfile { mOpportunistic, mPhy); // autoConnect is inverse of "isDirect" return true; } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); return false; } } @@ -858,22 +907,22 @@ public final class BluetoothGatt implements BluetoothProfile { * {@link BluetoothGattCallback#onPhyUpdate} will be triggered as a result of this call, even * if no PHY change happens. It is also triggered when remote device updates the PHY. * - * @param txPhy preferred transmitter PHY. Bitwise OR of any of - * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, - * and {@link BluetoothDevice#PHY_LE_CODED_MASK}. - * @param rxPhy preferred receiver PHY. Bitwise OR of any of - * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, - * and {@link BluetoothDevice#PHY_LE_CODED_MASK}. + * @param txPhy preferred transmitter PHY. Bitwise OR of any of {@link + * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, and {@link + * BluetoothDevice#PHY_LE_CODED_MASK}. + * @param rxPhy preferred receiver PHY. Bitwise OR of any of {@link + * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, and {@link + * BluetoothDevice#PHY_LE_CODED_MASK}. * @param phyOptions preferred coding to use when transmitting on the LE Coded PHY. Can be one - * of {@link BluetoothDevice#PHY_OPTION_NO_PREFERRED}, - * {@link BluetoothDevice#PHY_OPTION_S2} or {@link BluetoothDevice#PHY_OPTION_S8} + * of {@link BluetoothDevice#PHY_OPTION_NO_PREFERRED}, {@link BluetoothDevice#PHY_OPTION_S2} or + * {@link BluetoothDevice#PHY_OPTION_S8} */ public void setPreferredPhy(int txPhy, int rxPhy, int phyOptions) { try { mService.clientSetPreferredPhy(mClientIf, mDevice.getAddress(), txPhy, rxPhy, - phyOptions); + phyOptions); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -885,7 +934,7 @@ public final class BluetoothGatt implements BluetoothProfile { try { mService.clientReadPhy(mClientIf, mDevice.getAddress()); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -920,7 +969,7 @@ public final class BluetoothGatt implements BluetoothProfile { try { mService.discoverServices(mClientIf, mDevice.getAddress()); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); return false; } @@ -960,8 +1009,8 @@ public final class BluetoothGatt implements BluetoothProfile { * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * - * @return List of services on the remote device. Returns an empty list - * if service discovery has not yet been performed. + * @return List of services on the remote device. Returns an empty list if service discovery has + * not yet been performed. */ public List<BluetoothGattService> getServices() { List<BluetoothGattService> result = @@ -989,13 +1038,12 @@ public final class BluetoothGatt implements BluetoothProfile { * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param uuid UUID of the requested service - * @return BluetoothGattService if supported, or null if the requested - * service is not offered by the remote device. + * @return BluetoothGattService if supported, or null if the requested service is not offered by + * the remote device. */ public BluetoothGattService getService(UUID uuid) { for (BluetoothGattService service : mServices) { - if (service.getDevice().equals(mDevice) && - service.getUuid().equals(uuid)) { + if (service.getDevice().equals(mDevice) && service.getUuid().equals(uuid)) { return service; } } @@ -1016,8 +1064,9 @@ public final class BluetoothGatt implements BluetoothProfile { * @return true, if the read operation was initiated successfully */ public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) { - if ((characteristic.getProperties() & - BluetoothGattCharacteristic.PROPERTY_READ) == 0) return false; + if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_READ) == 0) { + return false; + } if (VDBG) Log.d(TAG, "readCharacteristic() - uuid: " + characteristic.getUuid()); if (mService == null || mClientIf == 0) return false; @@ -1028,16 +1077,16 @@ public final class BluetoothGatt implements BluetoothProfile { BluetoothDevice device = service.getDevice(); if (device == null) return false; - synchronized(mDeviceBusy) { + synchronized (mDeviceBusy) { if (mDeviceBusy) return false; mDeviceBusy = true; } try { mService.readCharacteristic(mClientIf, device.getAddress(), - characteristic.getInstanceId(), AUTHENTICATION_NONE); + characteristic.getInstanceId(), AUTHENTICATION_NONE); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); mDeviceBusy = false; return false; } @@ -1062,16 +1111,16 @@ public final class BluetoothGatt implements BluetoothProfile { if (VDBG) Log.d(TAG, "readUsingCharacteristicUuid() - uuid: " + uuid); if (mService == null || mClientIf == 0) return false; - synchronized(mDeviceBusy) { + synchronized (mDeviceBusy) { if (mDeviceBusy) return false; mDeviceBusy = true; } try { mService.readUsingCharacteristicUuid(mClientIf, mDevice.getAddress(), - new ParcelUuid(uuid), startHandle, endHandle, AUTHENTICATION_NONE); + new ParcelUuid(uuid), startHandle, endHandle, AUTHENTICATION_NONE); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); mDeviceBusy = false; return false; } @@ -1094,8 +1143,10 @@ public final class BluetoothGatt implements BluetoothProfile { */ public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) { if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0 - && (characteristic.getProperties() & - BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) return false; + && (characteristic.getProperties() + & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) { + return false; + } if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid()); if (mService == null || mClientIf == 0 || characteristic.getValue() == null) return false; @@ -1106,17 +1157,17 @@ public final class BluetoothGatt implements BluetoothProfile { BluetoothDevice device = service.getDevice(); if (device == null) return false; - synchronized(mDeviceBusy) { + synchronized (mDeviceBusy) { if (mDeviceBusy) return false; mDeviceBusy = true; } try { mService.writeCharacteristic(mClientIf, device.getAddress(), - characteristic.getInstanceId(), characteristic.getWriteType(), - AUTHENTICATION_NONE, characteristic.getValue()); + characteristic.getInstanceId(), characteristic.getWriteType(), + AUTHENTICATION_NONE, characteristic.getValue()); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); mDeviceBusy = false; return false; } @@ -1149,16 +1200,16 @@ public final class BluetoothGatt implements BluetoothProfile { BluetoothDevice device = service.getDevice(); if (device == null) return false; - synchronized(mDeviceBusy) { + synchronized (mDeviceBusy) { if (mDeviceBusy) return false; mDeviceBusy = true; } try { mService.readDescriptor(mClientIf, device.getAddress(), - descriptor.getInstanceId(), AUTHENTICATION_NONE); + descriptor.getInstanceId(), AUTHENTICATION_NONE); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); mDeviceBusy = false; return false; } @@ -1190,16 +1241,16 @@ public final class BluetoothGatt implements BluetoothProfile { BluetoothDevice device = service.getDevice(); if (device == null) return false; - synchronized(mDeviceBusy) { + synchronized (mDeviceBusy) { if (mDeviceBusy) return false; mDeviceBusy = true; } try { mService.writeDescriptor(mClientIf, device.getAddress(), descriptor.getInstanceId(), - AUTHENTICATION_NONE, descriptor.getValue()); + AUTHENTICATION_NONE, descriptor.getValue()); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); mDeviceBusy = false; return false; } @@ -1234,7 +1285,7 @@ public final class BluetoothGatt implements BluetoothProfile { try { mService.beginReliableWrite(mClientIf, mDevice.getAddress()); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); return false; } @@ -1258,7 +1309,7 @@ public final class BluetoothGatt implements BluetoothProfile { if (VDBG) Log.d(TAG, "executeReliableWrite() - device: " + mDevice.getAddress()); if (mService == null || mClientIf == 0) return false; - synchronized(mDeviceBusy) { + synchronized (mDeviceBusy) { if (mDeviceBusy) return false; mDeviceBusy = true; } @@ -1266,7 +1317,7 @@ public final class BluetoothGatt implements BluetoothProfile { try { mService.endReliableWrite(mClientIf, mDevice.getAddress(), true); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); mDeviceBusy = false; return false; } @@ -1289,7 +1340,7 @@ public final class BluetoothGatt implements BluetoothProfile { try { mService.endReliableWrite(mClientIf, mDevice.getAddress(), false); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -1316,9 +1367,11 @@ public final class BluetoothGatt implements BluetoothProfile { * @return true, if the requested notification status was set successfully */ public boolean setCharacteristicNotification(BluetoothGattCharacteristic characteristic, - boolean enable) { - if (DBG) Log.d(TAG, "setCharacteristicNotification() - uuid: " + characteristic.getUuid() - + " enable: " + enable); + boolean enable) { + if (DBG) { + Log.d(TAG, "setCharacteristicNotification() - uuid: " + characteristic.getUuid() + + " enable: " + enable); + } if (mService == null || mClientIf == 0) return false; BluetoothGattService service = characteristic.getService(); @@ -1329,9 +1382,9 @@ public final class BluetoothGatt implements BluetoothProfile { try { mService.registerForNotification(mClientIf, device.getAddress(), - characteristic.getInstanceId(), enable); + characteristic.getInstanceId(), enable); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); return false; } @@ -1341,6 +1394,7 @@ public final class BluetoothGatt implements BluetoothProfile { /** * Clears the internal cache and forces a refresh of the services from the * remote device. + * * @hide */ public boolean refresh() { @@ -1350,7 +1404,7 @@ public final class BluetoothGatt implements BluetoothProfile { try { mService.refreshDevice(mClientIf, mDevice.getAddress()); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); return false; } @@ -1374,7 +1428,7 @@ public final class BluetoothGatt implements BluetoothProfile { try { mService.readRemoteRssi(mClientIf, mDevice.getAddress()); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); return false; } @@ -1396,14 +1450,16 @@ public final class BluetoothGatt implements BluetoothProfile { * @return true, if the new MTU value has been requested successfully */ public boolean requestMtu(int mtu) { - if (DBG) Log.d(TAG, "configureMTU() - device: " + mDevice.getAddress() - + " mtu: " + mtu); + if (DBG) { + Log.d(TAG, "configureMTU() - device: " + mDevice.getAddress() + + " mtu: " + mtu); + } if (mService == null || mClientIf == 0) return false; try { mService.configureMTU(mClientIf, mDevice.getAddress(), mtu); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); return false; } @@ -1416,16 +1472,14 @@ public final class BluetoothGatt implements BluetoothProfile { * <p>This function will send a connection parameter update request to the * remote device. * - * @param connectionPriority Request a specific connection priority. Must be one of - * {@link BluetoothGatt#CONNECTION_PRIORITY_BALANCED}, - * {@link BluetoothGatt#CONNECTION_PRIORITY_HIGH} - * or {@link BluetoothGatt#CONNECTION_PRIORITY_LOW_POWER}. - * @throws IllegalArgumentException If the parameters are outside of their - * specified range. + * @param connectionPriority Request a specific connection priority. Must be one of {@link + * BluetoothGatt#CONNECTION_PRIORITY_BALANCED}, {@link BluetoothGatt#CONNECTION_PRIORITY_HIGH} + * or {@link BluetoothGatt#CONNECTION_PRIORITY_LOW_POWER}. + * @throws IllegalArgumentException If the parameters are outside of their specified range. */ public boolean requestConnectionPriority(int connectionPriority) { - if (connectionPriority < CONNECTION_PRIORITY_BALANCED || - connectionPriority > CONNECTION_PRIORITY_LOW_POWER) { + if (connectionPriority < CONNECTION_PRIORITY_BALANCED + || connectionPriority > CONNECTION_PRIORITY_LOW_POWER) { throw new IllegalArgumentException("connectionPriority not within valid range"); } @@ -1435,7 +1489,7 @@ public final class BluetoothGatt implements BluetoothProfile { try { mService.connectionParameterUpdate(mClientIf, mDevice.getAddress(), connectionPriority); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); return false; } @@ -1461,8 +1515,8 @@ public final class BluetoothGatt implements BluetoothProfile { */ @Override public List<BluetoothDevice> getConnectedDevices() { - throw new UnsupportedOperationException - ("Use BluetoothManager#getConnectedDevices instead."); + throw new UnsupportedOperationException( + "Use BluetoothManager#getConnectedDevices instead."); } /** @@ -1474,7 +1528,7 @@ public final class BluetoothGatt implements BluetoothProfile { */ @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { - throw new UnsupportedOperationException - ("Use BluetoothManager#getDevicesMatchingConnectionStates instead."); + throw new UnsupportedOperationException( + "Use BluetoothManager#getDevicesMatchingConnectionStates instead."); } } diff --git a/core/java/android/bluetooth/BluetoothGattCallback.java b/core/java/android/bluetooth/BluetoothGattCallback.java index c6f82ffb7ae4..cf82a3304572 100644 --- a/core/java/android/bluetooth/BluetoothGattCallback.java +++ b/core/java/android/bluetooth/BluetoothGattCallback.java @@ -19,19 +19,19 @@ package android.bluetooth; /** * This abstract class is used to implement {@link BluetoothGatt} callbacks. */ -public abstract class BluetoothGattCallback{ +public abstract class BluetoothGattCallback { /** * Callback triggered as result of {@link BluetoothGatt#setPreferredPhy}, or as a result of * remote device changing the PHY. * * @param gatt GATT client - * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, - * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}. - * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, - * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}. - * @param status Status of the PHY update operation. - * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds. + * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link + * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}. + * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link + * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}. + * @param status Status of the PHY update operation. {@link BluetoothGatt#GATT_SUCCESS} if the + * operation succeeds. */ public void onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status) { } @@ -40,12 +40,12 @@ public abstract class BluetoothGattCallback{ * Callback triggered as result of {@link BluetoothGatt#readPhy} * * @param gatt GATT client - * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, - * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}. - * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, - * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}. - * @param status Status of the PHY read operation. - * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds. + * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link + * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}. + * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link + * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}. + * @param status Status of the PHY read operation. {@link BluetoothGatt#GATT_SUCCESS} if the + * operation succeeds. */ public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) { } @@ -55,14 +55,13 @@ public abstract class BluetoothGattCallback{ * GATT server. * * @param gatt GATT client - * @param status Status of the connect or disconnect operation. - * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds. - * @param newState Returns the new connection state. Can be one of - * {@link BluetoothProfile#STATE_DISCONNECTED} or - * {@link BluetoothProfile#STATE_CONNECTED} + * @param status Status of the connect or disconnect operation. {@link + * BluetoothGatt#GATT_SUCCESS} if the operation succeeds. + * @param newState Returns the new connection state. Can be one of {@link + * BluetoothProfile#STATE_DISCONNECTED} or {@link BluetoothProfile#STATE_CONNECTED} */ public void onConnectionStateChange(BluetoothGatt gatt, int status, - int newState) { + int newState) { } /** @@ -70,8 +69,8 @@ public abstract class BluetoothGattCallback{ * for the remote device have been updated, ie new services have been discovered. * * @param gatt GATT client invoked {@link BluetoothGatt#discoverServices} - * @param status {@link BluetoothGatt#GATT_SUCCESS} if the remote device - * has been explored successfully. + * @param status {@link BluetoothGatt#GATT_SUCCESS} if the remote device has been explored + * successfully. */ public void onServicesDiscovered(BluetoothGatt gatt, int status) { } @@ -80,13 +79,12 @@ public abstract class BluetoothGattCallback{ * Callback reporting the result of a characteristic read operation. * * @param gatt GATT client invoked {@link BluetoothGatt#readCharacteristic} - * @param characteristic Characteristic that was read from the associated - * remote device. - * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation - * was completed successfully. + * @param characteristic Characteristic that was read from the associated remote device. + * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed + * successfully. */ public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, - int status) { + int status) { } /** @@ -99,58 +97,55 @@ public abstract class BluetoothGattCallback{ * the application must abort the reliable write transaction. * * @param gatt GATT client invoked {@link BluetoothGatt#writeCharacteristic} - * @param characteristic Characteristic that was written to the associated - * remote device. - * @param status The result of the write operation - * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds. + * @param characteristic Characteristic that was written to the associated remote device. + * @param status The result of the write operation {@link BluetoothGatt#GATT_SUCCESS} if the + * operation succeeds. */ public void onCharacteristicWrite(BluetoothGatt gatt, - BluetoothGattCharacteristic characteristic, int status) { + BluetoothGattCharacteristic characteristic, int status) { } /** * Callback triggered as a result of a remote characteristic notification. * * @param gatt GATT client the characteristic is associated with - * @param characteristic Characteristic that has been updated as a result - * of a remote notification event. + * @param characteristic Characteristic that has been updated as a result of a remote + * notification event. */ public void onCharacteristicChanged(BluetoothGatt gatt, - BluetoothGattCharacteristic characteristic) { + BluetoothGattCharacteristic characteristic) { } /** * Callback reporting the result of a descriptor read operation. * * @param gatt GATT client invoked {@link BluetoothGatt#readDescriptor} - * @param descriptor Descriptor that was read from the associated - * remote device. - * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation - * was completed successfully + * @param descriptor Descriptor that was read from the associated remote device. + * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation was completed + * successfully */ public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, - int status) { + int status) { } /** * Callback indicating the result of a descriptor write operation. * * @param gatt GATT client invoked {@link BluetoothGatt#writeDescriptor} - * @param descriptor Descriptor that was writte to the associated - * remote device. - * @param status The result of the write operation - * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds. + * @param descriptor Descriptor that was writte to the associated remote device. + * @param status The result of the write operation {@link BluetoothGatt#GATT_SUCCESS} if the + * operation succeeds. */ public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, - int status) { + int status) { } /** * Callback invoked when a reliable write transaction has been completed. * * @param gatt GATT client invoked {@link BluetoothGatt#executeReliableWrite} - * @param status {@link BluetoothGatt#GATT_SUCCESS} if the reliable write - * transaction was executed successfully + * @param status {@link BluetoothGatt#GATT_SUCCESS} if the reliable write transaction was + * executed successfully */ public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { } @@ -186,17 +181,17 @@ public abstract class BluetoothGattCallback{ * Callback indicating the connection parameters were updated. * * @param gatt GATT client involved - * @param interval Connection interval used on this connection, 1.25ms unit. Valid - * range is from 6 (7.5ms) to 3200 (4000ms). - * @param latency Slave latency for the connection in number of connection events. Valid - * range is from 0 to 499 - * @param timeout Supervision timeout for this connection, in 10ms unit. Valid range is - * from 10 (0.1s) to 3200 (32s) + * @param interval Connection interval used on this connection, 1.25ms unit. Valid range is from + * 6 (7.5ms) to 3200 (4000ms). + * @param latency Slave latency for the connection in number of connection events. Valid range + * is from 0 to 499 + * @param timeout Supervision timeout for this connection, in 10ms unit. Valid range is from 10 + * (0.1s) to 3200 (32s) * @param status {@link BluetoothGatt#GATT_SUCCESS} if the connection has been updated - * successfully + * successfully * @hide */ public void onConnectionUpdated(BluetoothGatt gatt, int interval, int latency, int timeout, - int status) { + int status) { } } diff --git a/core/java/android/bluetooth/BluetoothGattCharacteristic.java b/core/java/android/bluetooth/BluetoothGattCharacteristic.java index 1cc2270be566..2c124034b786 100644 --- a/core/java/android/bluetooth/BluetoothGattCharacteristic.java +++ b/core/java/android/bluetooth/BluetoothGattCharacteristic.java @@ -16,8 +16,9 @@ package android.bluetooth; import android.os.Parcel; -import android.os.Parcelable; import android.os.ParcelUuid; +import android.os.Parcelable; + import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -171,30 +172,35 @@ public class BluetoothGattCharacteristic implements Parcelable { /** * The UUID of this characteristic. + * * @hide */ protected UUID mUuid; /** * Instance ID for this characteristic. + * * @hide */ protected int mInstance; /** * Characteristic properties. + * * @hide */ protected int mProperties; /** * Characteristic permissions. + * * @hide */ protected int mPermissions; /** * Key size (default = 16). + * * @hide */ protected int mKeySize = 16; @@ -202,18 +208,21 @@ public class BluetoothGattCharacteristic implements Parcelable { /** * Write type for this characteristic. * See WRITE_TYPE_* constants. + * * @hide */ protected int mWriteType; /** * Back-reference to the service this characteristic belongs to. + * * @hide */ protected BluetoothGattService mService; /** * The cached value of this characteristic. + * * @hide */ protected byte[] mValue; @@ -237,26 +246,28 @@ public class BluetoothGattCharacteristic implements Parcelable { /** * Create a new BluetoothGattCharacteristic + * * @hide */ /*package*/ BluetoothGattCharacteristic(BluetoothGattService service, - UUID uuid, int instanceId, - int properties, int permissions) { + UUID uuid, int instanceId, + int properties, int permissions) { initCharacteristic(service, uuid, instanceId, properties, permissions); } /** * Create a new BluetoothGattCharacteristic + * * @hide */ public BluetoothGattCharacteristic(UUID uuid, int instanceId, - int properties, int permissions) { + int properties, int permissions) { initCharacteristic(null, uuid, instanceId, properties, permissions); } private void initCharacteristic(BluetoothGattService service, - UUID uuid, int instanceId, - int properties, int permissions) { + UUID uuid, int instanceId, + int properties, int permissions) { mUuid = uuid; mInstance = instanceId; mProperties = properties; @@ -272,13 +283,12 @@ public class BluetoothGattCharacteristic implements Parcelable { } } - /** - * @hide - */ + @Override public int describeContents() { return 0; } + @Override public void writeToParcel(Parcel out, int flags) { out.writeParcelable(new ParcelUuid(mUuid), 0); out.writeInt(mInstance); @@ -289,8 +299,8 @@ public class BluetoothGattCharacteristic implements Parcelable { out.writeTypedList(mDescriptors); } - public static final Parcelable.Creator<BluetoothGattCharacteristic> CREATOR - = new Parcelable.Creator<BluetoothGattCharacteristic>() { + public static final Parcelable.Creator<BluetoothGattCharacteristic> CREATOR = + new Parcelable.Creator<BluetoothGattCharacteristic>() { public BluetoothGattCharacteristic createFromParcel(Parcel in) { return new BluetoothGattCharacteristic(in); } @@ -301,7 +311,7 @@ public class BluetoothGattCharacteristic implements Parcelable { }; private BluetoothGattCharacteristic(Parcel in) { - mUuid = ((ParcelUuid)in.readParcelable(null)).getUuid(); + mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid(); mInstance = in.readInt(); mProperties = in.readInt(); mPermissions = in.readInt(); @@ -313,7 +323,7 @@ public class BluetoothGattCharacteristic implements Parcelable { ArrayList<BluetoothGattDescriptor> descs = in.createTypedArrayList(BluetoothGattDescriptor.CREATOR); if (descs != null) { - for (BluetoothGattDescriptor desc: descs) { + for (BluetoothGattDescriptor desc : descs) { desc.setCharacteristic(this); mDescriptors.add(desc); } @@ -322,6 +332,7 @@ public class BluetoothGattCharacteristic implements Parcelable { /** * Returns the desired key size. + * * @hide */ public int getKeySize() { @@ -343,12 +354,13 @@ public class BluetoothGattCharacteristic implements Parcelable { /** * Get a descriptor by UUID and isntance id. + * * @hide */ /*package*/ BluetoothGattDescriptor getDescriptor(UUID uuid, int instanceId) { - for(BluetoothGattDescriptor descriptor : mDescriptors) { + for (BluetoothGattDescriptor descriptor : mDescriptors) { if (descriptor.getUuid().equals(uuid) - && descriptor.getInstanceId() == instanceId) { + && descriptor.getInstanceId() == instanceId) { return descriptor; } } @@ -357,6 +369,7 @@ public class BluetoothGattCharacteristic implements Parcelable { /** * Returns the service this characteristic belongs to. + * * @return The asscociated service */ public BluetoothGattService getService() { @@ -365,6 +378,7 @@ public class BluetoothGattCharacteristic implements Parcelable { /** * Sets the service associated with this device. + * * @hide */ /*package*/ void setService(BluetoothGattService service) { @@ -394,6 +408,7 @@ public class BluetoothGattCharacteristic implements Parcelable { /** * Force the instance ID. + * * @hide */ public void setInstanceId(int instanceId) { @@ -437,11 +452,8 @@ public class BluetoothGattCharacteristic implements Parcelable { * {@link BluetoothGatt#writeCharacteristic} function write this * characteristic. * - * @param writeType The write type to for this characteristic. Can be one - * of: - * {@link #WRITE_TYPE_DEFAULT}, - * {@link #WRITE_TYPE_NO_RESPONSE} or - * {@link #WRITE_TYPE_SIGNED}. + * @param writeType The write type to for this characteristic. Can be one of: {@link + * #WRITE_TYPE_DEFAULT}, {@link #WRITE_TYPE_NO_RESPONSE} or {@link #WRITE_TYPE_SIGNED}. */ public void setWriteType(int writeType) { mWriteType = writeType; @@ -449,6 +461,7 @@ public class BluetoothGattCharacteristic implements Parcelable { /** * Set the desired key size. + * * @hide */ public void setKeySize(int keySize) { @@ -468,11 +481,10 @@ public class BluetoothGattCharacteristic implements Parcelable { * Returns a descriptor with a given UUID out of the list of * descriptors for this characteristic. * - * @return GATT descriptor object or null if no descriptor with the - * given UUID was found. + * @return GATT descriptor object or null if no descriptor with the given UUID was found. */ public BluetoothGattDescriptor getDescriptor(UUID uuid) { - for(BluetoothGattDescriptor descriptor : mDescriptors) { + for (BluetoothGattDescriptor descriptor : mDescriptors) { if (descriptor.getUuid().equals(uuid)) { return descriptor; } @@ -503,11 +515,9 @@ public class BluetoothGattCharacteristic implements Parcelable { * characteristic value at the given offset are interpreted to generate the * return value. * - * @param formatType The format type used to interpret the characteristic - * value. + * @param formatType The format type used to interpret the characteristic value. * @param offset Offset at which the integer value can be found. - * @return Cached value of the characteristic or null of offset exceeds - * value size. + * @return Cached value of the characteristic or null of offset exceeds value size. */ public Integer getIntValue(int formatType, int offset) { if ((offset + getTypeLen(formatType)) > mValue.length) return null; @@ -517,21 +527,21 @@ public class BluetoothGattCharacteristic implements Parcelable { return unsignedByteToInt(mValue[offset]); case FORMAT_UINT16: - return unsignedBytesToInt(mValue[offset], mValue[offset+1]); + return unsignedBytesToInt(mValue[offset], mValue[offset + 1]); case FORMAT_UINT32: - return unsignedBytesToInt(mValue[offset], mValue[offset+1], - mValue[offset+2], mValue[offset+3]); + return unsignedBytesToInt(mValue[offset], mValue[offset + 1], + mValue[offset + 2], mValue[offset + 3]); case FORMAT_SINT8: return unsignedToSigned(unsignedByteToInt(mValue[offset]), 8); case FORMAT_SINT16: return unsignedToSigned(unsignedBytesToInt(mValue[offset], - mValue[offset+1]), 16); + mValue[offset + 1]), 16); case FORMAT_SINT32: return unsignedToSigned(unsignedBytesToInt(mValue[offset], - mValue[offset+1], mValue[offset+2], mValue[offset+3]), 32); + mValue[offset + 1], mValue[offset + 2], mValue[offset + 3]), 32); } return null; @@ -541,22 +551,21 @@ public class BluetoothGattCharacteristic implements Parcelable { * Return the stored value of this characteristic. * <p>See {@link #getValue} for details. * - * @param formatType The format type used to interpret the characteristic - * value. + * @param formatType The format type used to interpret the characteristic value. * @param offset Offset at which the float value can be found. - * @return Cached value of the characteristic at a given offset or null - * if the requested offset exceeds the value size. + * @return Cached value of the characteristic at a given offset or null if the requested offset + * exceeds the value size. */ public Float getFloatValue(int formatType, int offset) { if ((offset + getTypeLen(formatType)) > mValue.length) return null; switch (formatType) { case FORMAT_SFLOAT: - return bytesToFloat(mValue[offset], mValue[offset+1]); + return bytesToFloat(mValue[offset], mValue[offset + 1]); case FORMAT_FLOAT: - return bytesToFloat(mValue[offset], mValue[offset+1], - mValue[offset+2], mValue[offset+3]); + return bytesToFloat(mValue[offset], mValue[offset + 1], + mValue[offset + 2], mValue[offset + 3]); } return null; @@ -572,7 +581,7 @@ public class BluetoothGattCharacteristic implements Parcelable { public String getStringValue(int offset) { if (mValue == null || offset > mValue.length) return null; byte[] strBytes = new byte[mValue.length - offset]; - for (int i=0; i != (mValue.length-offset); ++i) strBytes[i] = mValue[offset+i]; + for (int i = 0; i != (mValue.length - offset); ++i) strBytes[i] = mValue[offset + i]; return new String(strBytes); } @@ -585,8 +594,8 @@ public class BluetoothGattCharacteristic implements Parcelable { * remote device. * * @param value New value for this characteristic - * @return true if the locally stored value has been set, false if the - * requested value could not be stored locally. + * @return true if the locally stored value has been set, false if the requested value could not + * be stored locally. */ public boolean setValue(byte[] value) { mValue = value; @@ -612,25 +621,25 @@ public class BluetoothGattCharacteristic implements Parcelable { value = intToSignedBits(value, 8); // Fall-through intended case FORMAT_UINT8: - mValue[offset] = (byte)(value & 0xFF); + mValue[offset] = (byte) (value & 0xFF); break; case FORMAT_SINT16: value = intToSignedBits(value, 16); // Fall-through intended case FORMAT_UINT16: - mValue[offset++] = (byte)(value & 0xFF); - mValue[offset] = (byte)((value >> 8) & 0xFF); + mValue[offset++] = (byte) (value & 0xFF); + mValue[offset] = (byte) ((value >> 8) & 0xFF); break; case FORMAT_SINT32: value = intToSignedBits(value, 32); // Fall-through intended case FORMAT_UINT32: - mValue[offset++] = (byte)(value & 0xFF); - mValue[offset++] = (byte)((value >> 8) & 0xFF); - mValue[offset++] = (byte)((value >> 16) & 0xFF); - mValue[offset] = (byte)((value >> 24) & 0xFF); + mValue[offset++] = (byte) (value & 0xFF); + mValue[offset++] = (byte) ((value >> 8) & 0xFF); + mValue[offset++] = (byte) ((value >> 16) & 0xFF); + mValue[offset] = (byte) ((value >> 24) & 0xFF); break; default: @@ -644,7 +653,7 @@ public class BluetoothGattCharacteristic implements Parcelable { * <p>See {@link #setValue(byte[])} for details. * * @param mantissa Mantissa for this characteristic - * @param exponent exponent value for this characteristic + * @param exponent exponent value for this characteristic * @param formatType Float format type used to transform the value parameter * @param offset Offset at which the value should be placed * @return true if the locally stored value has been set @@ -658,18 +667,18 @@ public class BluetoothGattCharacteristic implements Parcelable { case FORMAT_SFLOAT: mantissa = intToSignedBits(mantissa, 12); exponent = intToSignedBits(exponent, 4); - mValue[offset++] = (byte)(mantissa & 0xFF); - mValue[offset] = (byte)((mantissa >> 8) & 0x0F); - mValue[offset] += (byte)((exponent & 0x0F) << 4); + mValue[offset++] = (byte) (mantissa & 0xFF); + mValue[offset] = (byte) ((mantissa >> 8) & 0x0F); + mValue[offset] += (byte) ((exponent & 0x0F) << 4); break; case FORMAT_FLOAT: mantissa = intToSignedBits(mantissa, 24); exponent = intToSignedBits(exponent, 8); - mValue[offset++] = (byte)(mantissa & 0xFF); - mValue[offset++] = (byte)((mantissa >> 8) & 0xFF); - mValue[offset++] = (byte)((mantissa >> 16) & 0xFF); - mValue[offset] += (byte)(exponent & 0xFF); + mValue[offset++] = (byte) (mantissa & 0xFF); + mValue[offset++] = (byte) ((mantissa >> 8) & 0xFF); + mValue[offset++] = (byte) ((mantissa >> 16) & 0xFF); + mValue[offset] += (byte) (exponent & 0xFF); break; default: @@ -717,7 +726,7 @@ public class BluetoothGattCharacteristic implements Parcelable { */ private int unsignedBytesToInt(byte b0, byte b1, byte b2, byte b3) { return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8)) - + (unsignedByteToInt(b2) << 16) + (unsignedByteToInt(b3) << 24); + + (unsignedByteToInt(b2) << 16) + (unsignedByteToInt(b3) << 24); } /** @@ -725,9 +734,9 @@ public class BluetoothGattCharacteristic implements Parcelable { */ private float bytesToFloat(byte b0, byte b1) { int mantissa = unsignedToSigned(unsignedByteToInt(b0) - + ((unsignedByteToInt(b1) & 0x0F) << 8), 12); + + ((unsignedByteToInt(b1) & 0x0F) << 8), 12); int exponent = unsignedToSigned(unsignedByteToInt(b1) >> 4, 4); - return (float)(mantissa * Math.pow(10, exponent)); + return (float) (mantissa * Math.pow(10, exponent)); } /** @@ -735,9 +744,9 @@ public class BluetoothGattCharacteristic implements Parcelable { */ private float bytesToFloat(byte b0, byte b1, byte b2, byte b3) { int mantissa = unsignedToSigned(unsignedByteToInt(b0) - + (unsignedByteToInt(b1) << 8) - + (unsignedByteToInt(b2) << 16), 24); - return (float)(mantissa * Math.pow(10, b3)); + + (unsignedByteToInt(b1) << 8) + + (unsignedByteToInt(b2) << 16), 24); + return (float) (mantissa * Math.pow(10, b3)); } /** @@ -745,8 +754,8 @@ public class BluetoothGattCharacteristic implements Parcelable { * signed value. */ private int unsignedToSigned(int unsigned, int size) { - if ((unsigned & (1 << size-1)) != 0) { - unsigned = -1 * ((1 << size-1) - (unsigned & ((1 << size-1) - 1))); + if ((unsigned & (1 << size - 1)) != 0) { + unsigned = -1 * ((1 << size - 1) - (unsigned & ((1 << size - 1) - 1))); } return unsigned; } @@ -756,7 +765,7 @@ public class BluetoothGattCharacteristic implements Parcelable { */ private int intToSignedBits(int i, int size) { if (i < 0) { - i = (1 << size-1) + (i & ((1 << size-1) - 1)); + i = (1 << size - 1) + (i & ((1 << size - 1) - 1)); } return i; } diff --git a/core/java/android/bluetooth/BluetoothGattDescriptor.java b/core/java/android/bluetooth/BluetoothGattDescriptor.java index 1a4fa487a4d7..217a5abf1fe5 100644 --- a/core/java/android/bluetooth/BluetoothGattDescriptor.java +++ b/core/java/android/bluetooth/BluetoothGattDescriptor.java @@ -17,8 +17,9 @@ package android.bluetooth; import android.os.Parcel; -import android.os.Parcelable; import android.os.ParcelUuid; +import android.os.Parcelable; + import java.util.UUID; /** @@ -89,30 +90,35 @@ public class BluetoothGattDescriptor implements Parcelable { /** * The UUID of this descriptor. + * * @hide */ protected UUID mUuid; /** * Instance ID for this descriptor. + * * @hide */ protected int mInstance; /** * Permissions for this descriptor + * * @hide */ protected int mPermissions; /** * Back-reference to the characteristic this descriptor belongs to. + * * @hide */ protected BluetoothGattCharacteristic mCharacteristic; /** * The value for this descriptor. + * * @hide */ protected byte[] mValue; @@ -137,7 +143,7 @@ public class BluetoothGattDescriptor implements Parcelable { * @param permissions Permissions for this descriptor */ /*package*/ BluetoothGattDescriptor(BluetoothGattCharacteristic characteristic, UUID uuid, - int instance, int permissions) { + int instance, int permissions) { initDescriptor(characteristic, uuid, instance, permissions); } @@ -149,28 +155,27 @@ public class BluetoothGattDescriptor implements Parcelable { } private void initDescriptor(BluetoothGattCharacteristic characteristic, UUID uuid, - int instance, int permissions) { + int instance, int permissions) { mCharacteristic = characteristic; mUuid = uuid; mInstance = instance; mPermissions = permissions; } - /** - * @hide - */ + @Override public int describeContents() { return 0; } + @Override public void writeToParcel(Parcel out, int flags) { out.writeParcelable(new ParcelUuid(mUuid), 0); out.writeInt(mInstance); out.writeInt(mPermissions); } - public static final Parcelable.Creator<BluetoothGattDescriptor> CREATOR - = new Parcelable.Creator<BluetoothGattDescriptor>() { + public static final Parcelable.Creator<BluetoothGattDescriptor> CREATOR = + new Parcelable.Creator<BluetoothGattDescriptor>() { public BluetoothGattDescriptor createFromParcel(Parcel in) { return new BluetoothGattDescriptor(in); } @@ -181,13 +186,14 @@ public class BluetoothGattDescriptor implements Parcelable { }; private BluetoothGattDescriptor(Parcel in) { - mUuid = ((ParcelUuid)in.readParcelable(null)).getUuid(); + mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid(); mInstance = in.readInt(); mPermissions = in.readInt(); } /** * Returns the characteristic this descriptor belongs to. + * * @return The characteristic. */ public BluetoothGattCharacteristic getCharacteristic() { @@ -196,6 +202,7 @@ public class BluetoothGattDescriptor implements Parcelable { /** * Set the back-reference to the associated characteristic + * * @hide */ /*package*/ void setCharacteristic(BluetoothGattCharacteristic characteristic) { @@ -228,6 +235,7 @@ public class BluetoothGattDescriptor implements Parcelable { /** * Force the instance ID. + * * @hide */ public void setInstanceId(int instanceId) { @@ -266,8 +274,8 @@ public class BluetoothGattDescriptor implements Parcelable { * remote device. * * @param value New value for this descriptor - * @return true if the locally stored value has been set, false if the - * requested value could not be stored locally. + * @return true if the locally stored value has been set, false if the requested value could not + * be stored locally. */ public boolean setValue(byte[] value) { mValue = value; diff --git a/core/java/android/bluetooth/BluetoothGattIncludedService.java b/core/java/android/bluetooth/BluetoothGattIncludedService.java index 155dc571d230..bccf20ef96b3 100644 --- a/core/java/android/bluetooth/BluetoothGattIncludedService.java +++ b/core/java/android/bluetooth/BluetoothGattIncludedService.java @@ -16,14 +16,14 @@ package android.bluetooth; import android.os.Parcel; -import android.os.Parcelable; import android.os.ParcelUuid; -import java.util.ArrayList; -import java.util.List; +import android.os.Parcelable; + import java.util.UUID; /** * Represents a Bluetooth GATT Included Service + * * @hide */ public class BluetoothGattIncludedService implements Parcelable { @@ -52,18 +52,20 @@ public class BluetoothGattIncludedService implements Parcelable { mServiceType = serviceType; } + @Override public int describeContents() { return 0; } + @Override public void writeToParcel(Parcel out, int flags) { out.writeParcelable(new ParcelUuid(mUuid), 0); out.writeInt(mInstanceId); out.writeInt(mServiceType); - } + } - public static final Parcelable.Creator<BluetoothGattIncludedService> CREATOR - = new Parcelable.Creator<BluetoothGattIncludedService>() { + public static final Parcelable.Creator<BluetoothGattIncludedService> CREATOR = + new Parcelable.Creator<BluetoothGattIncludedService>() { public BluetoothGattIncludedService createFromParcel(Parcel in) { return new BluetoothGattIncludedService(in); } @@ -74,7 +76,7 @@ public class BluetoothGattIncludedService implements Parcelable { }; private BluetoothGattIncludedService(Parcel in) { - mUuid = ((ParcelUuid)in.readParcelable(null)).getUuid(); + mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid(); mInstanceId = in.readInt(); mServiceType = in.readInt(); } diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java index eddc278851f4..4ed250043ae9 100644 --- a/core/java/android/bluetooth/BluetoothGattServer.java +++ b/core/java/android/bluetooth/BluetoothGattServer.java @@ -16,10 +16,6 @@ package android.bluetooth; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; -import android.content.Context; import android.os.ParcelUuid; import android.os.RemoteException; import android.util.Log; @@ -60,300 +56,322 @@ public final class BluetoothGattServer implements BluetoothProfile { * Bluetooth GATT interface callbacks */ private final IBluetoothGattServerCallback mBluetoothGattServerCallback = - new IBluetoothGattServerCallback.Stub() { - /** - * Application interface registered - app is ready to go - * @hide - */ - @Override - public void onServerRegistered(int status, int serverIf) { - if (DBG) Log.d(TAG, "onServerRegistered() - status=" + status - + " serverIf=" + serverIf); - synchronized(mServerIfLock) { - if (mCallback != null) { - mServerIf = serverIf; - mServerIfLock.notify(); - } else { - // registration timeout - Log.e(TAG, "onServerRegistered: mCallback is null"); + new IBluetoothGattServerCallback.Stub() { + /** + * Application interface registered - app is ready to go + * @hide + */ + @Override + public void onServerRegistered(int status, int serverIf) { + if (DBG) { + Log.d(TAG, "onServerRegistered() - status=" + status + + " serverIf=" + serverIf); + } + synchronized (mServerIfLock) { + if (mCallback != null) { + mServerIf = serverIf; + mServerIfLock.notify(); + } else { + // registration timeout + Log.e(TAG, "onServerRegistered: mCallback is null"); + } } } - } - /** - * Server connection state changed - * @hide - */ - @Override - public void onServerConnectionState(int status, int serverIf, - boolean connected, String address) { - if (DBG) Log.d(TAG, "onServerConnectionState() - status=" + status - + " serverIf=" + serverIf + " device=" + address); - try { - mCallback.onConnectionStateChange(mAdapter.getRemoteDevice(address), status, - connected ? BluetoothProfile.STATE_CONNECTED : - BluetoothProfile.STATE_DISCONNECTED); - } catch (Exception ex) { - Log.w(TAG, "Unhandled exception in callback", ex); + /** + * Server connection state changed + * @hide + */ + @Override + public void onServerConnectionState(int status, int serverIf, + boolean connected, String address) { + if (DBG) { + Log.d(TAG, "onServerConnectionState() - status=" + status + + " serverIf=" + serverIf + " device=" + address); + } + try { + mCallback.onConnectionStateChange(mAdapter.getRemoteDevice(address), status, + connected ? BluetoothProfile.STATE_CONNECTED : + BluetoothProfile.STATE_DISCONNECTED); + } catch (Exception ex) { + Log.w(TAG, "Unhandled exception in callback", ex); + } } - } - /** - * Service has been added - * @hide - */ - @Override - public void onServiceAdded(int status, BluetoothGattService service) { - if (DBG) Log.d(TAG, "onServiceAdded() - handle=" + service.getInstanceId() - + " uuid=" + service.getUuid() + " status=" + status); - - if (mPendingService == null) - return; - - BluetoothGattService tmp = mPendingService; - mPendingService = null; - - // Rewrite newly assigned handles to existing service. - tmp.setInstanceId(service.getInstanceId()); - List<BluetoothGattCharacteristic> temp_chars = tmp.getCharacteristics(); - List<BluetoothGattCharacteristic> svc_chars = service.getCharacteristics(); - for (int i=0; i<svc_chars.size(); i++) { - BluetoothGattCharacteristic temp_char = temp_chars.get(i); - BluetoothGattCharacteristic svc_char = svc_chars.get(i); - - temp_char.setInstanceId(svc_char.getInstanceId()); - - List<BluetoothGattDescriptor> temp_descs = temp_char.getDescriptors(); - List<BluetoothGattDescriptor> svc_descs = svc_char.getDescriptors(); - for (int j=0; j<svc_descs.size(); j++) { - temp_descs.get(j).setInstanceId(svc_descs.get(j).getInstanceId()); + /** + * Service has been added + * @hide + */ + @Override + public void onServiceAdded(int status, BluetoothGattService service) { + if (DBG) { + Log.d(TAG, "onServiceAdded() - handle=" + service.getInstanceId() + + " uuid=" + service.getUuid() + " status=" + status); } - } - mServices.add(tmp); + if (mPendingService == null) { + return; + } - try { - mCallback.onServiceAdded((int)status, tmp); - } catch (Exception ex) { - Log.w(TAG, "Unhandled exception in callback", ex); - } - } + BluetoothGattService tmp = mPendingService; + mPendingService = null; - /** - * Remote client characteristic read request. - * @hide - */ - @Override - public void onCharacteristicReadRequest(String address, int transId, - int offset, boolean isLong, int handle) { - if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - handle=" + handle); - - BluetoothDevice device = mAdapter.getRemoteDevice(address); - BluetoothGattCharacteristic characteristic = getCharacteristicByHandle(handle); - if (characteristic == null) { - Log.w(TAG, "onCharacteristicReadRequest() no char for handle " + handle); - return; - } + // Rewrite newly assigned handles to existing service. + tmp.setInstanceId(service.getInstanceId()); + List<BluetoothGattCharacteristic> temp_chars = tmp.getCharacteristics(); + List<BluetoothGattCharacteristic> svc_chars = service.getCharacteristics(); + for (int i = 0; i < svc_chars.size(); i++) { + BluetoothGattCharacteristic temp_char = temp_chars.get(i); + BluetoothGattCharacteristic svc_char = svc_chars.get(i); - try { - mCallback.onCharacteristicReadRequest(device, transId, offset, characteristic); - } catch (Exception ex) { - Log.w(TAG, "Unhandled exception in callback", ex); - } - } + temp_char.setInstanceId(svc_char.getInstanceId()); - /** - * Remote client descriptor read request. - * @hide - */ - @Override - public void onDescriptorReadRequest(String address, int transId, - int offset, boolean isLong, int handle) { - if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - handle=" + handle); - - BluetoothDevice device = mAdapter.getRemoteDevice(address); - BluetoothGattDescriptor descriptor = getDescriptorByHandle(handle); - if (descriptor == null) { - Log.w(TAG, "onDescriptorReadRequest() no desc for handle " + handle); - return; - } + List<BluetoothGattDescriptor> temp_descs = temp_char.getDescriptors(); + List<BluetoothGattDescriptor> svc_descs = svc_char.getDescriptors(); + for (int j = 0; j < svc_descs.size(); j++) { + temp_descs.get(j).setInstanceId(svc_descs.get(j).getInstanceId()); + } + } + + mServices.add(tmp); - try { - mCallback.onDescriptorReadRequest(device, transId, offset, descriptor); - } catch (Exception ex) { - Log.w(TAG, "Unhandled exception in callback", ex); + try { + mCallback.onServiceAdded((int) status, tmp); + } catch (Exception ex) { + Log.w(TAG, "Unhandled exception in callback", ex); + } } - } - /** - * Remote client characteristic write request. - * @hide - */ - @Override - public void onCharacteristicWriteRequest(String address, int transId, - int offset, int length, boolean isPrep, boolean needRsp, - int handle, byte[] value) { - if (VDBG) Log.d(TAG, "onCharacteristicWriteRequest() - handle=" + handle); - - BluetoothDevice device = mAdapter.getRemoteDevice(address); - BluetoothGattCharacteristic characteristic = getCharacteristicByHandle(handle); - if (characteristic == null) { - Log.w(TAG, "onCharacteristicWriteRequest() no char for handle " + handle); - return; + /** + * Remote client characteristic read request. + * @hide + */ + @Override + public void onCharacteristicReadRequest(String address, int transId, + int offset, boolean isLong, int handle) { + if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - handle=" + handle); + + BluetoothDevice device = mAdapter.getRemoteDevice(address); + BluetoothGattCharacteristic characteristic = getCharacteristicByHandle(handle); + if (characteristic == null) { + Log.w(TAG, "onCharacteristicReadRequest() no char for handle " + handle); + return; + } + + try { + mCallback.onCharacteristicReadRequest(device, transId, offset, + characteristic); + } catch (Exception ex) { + Log.w(TAG, "Unhandled exception in callback", ex); + } } - try { - mCallback.onCharacteristicWriteRequest(device, transId, characteristic, - isPrep, needRsp, offset, value); - } catch (Exception ex) { - Log.w(TAG, "Unhandled exception in callback", ex); + /** + * Remote client descriptor read request. + * @hide + */ + @Override + public void onDescriptorReadRequest(String address, int transId, + int offset, boolean isLong, int handle) { + if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - handle=" + handle); + + BluetoothDevice device = mAdapter.getRemoteDevice(address); + BluetoothGattDescriptor descriptor = getDescriptorByHandle(handle); + if (descriptor == null) { + Log.w(TAG, "onDescriptorReadRequest() no desc for handle " + handle); + return; + } + + try { + mCallback.onDescriptorReadRequest(device, transId, offset, descriptor); + } catch (Exception ex) { + Log.w(TAG, "Unhandled exception in callback", ex); + } } - } + /** + * Remote client characteristic write request. + * @hide + */ + @Override + public void onCharacteristicWriteRequest(String address, int transId, + int offset, int length, boolean isPrep, boolean needRsp, + int handle, byte[] value) { + if (VDBG) Log.d(TAG, "onCharacteristicWriteRequest() - handle=" + handle); + + BluetoothDevice device = mAdapter.getRemoteDevice(address); + BluetoothGattCharacteristic characteristic = getCharacteristicByHandle(handle); + if (characteristic == null) { + Log.w(TAG, "onCharacteristicWriteRequest() no char for handle " + handle); + return; + } + + try { + mCallback.onCharacteristicWriteRequest(device, transId, characteristic, + isPrep, needRsp, offset, value); + } catch (Exception ex) { + Log.w(TAG, "Unhandled exception in callback", ex); + } - /** - * Remote client descriptor write request. - * @hide - */ - @Override - public void onDescriptorWriteRequest(String address, int transId, int offset, - int length, boolean isPrep, boolean needRsp, int handle, byte[] value) { - if (VDBG) Log.d(TAG, "onDescriptorWriteRequest() - handle=" + handle); - - BluetoothDevice device = mAdapter.getRemoteDevice(address); - BluetoothGattDescriptor descriptor = getDescriptorByHandle(handle); - if (descriptor == null) { - Log.w(TAG, "onDescriptorWriteRequest() no desc for handle " + handle); - return; } - try { - mCallback.onDescriptorWriteRequest(device, transId, descriptor, - isPrep, needRsp, offset, value); - } catch (Exception ex) { - Log.w(TAG, "Unhandled exception in callback", ex); + /** + * Remote client descriptor write request. + * @hide + */ + @Override + public void onDescriptorWriteRequest(String address, int transId, int offset, + int length, boolean isPrep, boolean needRsp, int handle, byte[] value) { + if (VDBG) Log.d(TAG, "onDescriptorWriteRequest() - handle=" + handle); + + BluetoothDevice device = mAdapter.getRemoteDevice(address); + BluetoothGattDescriptor descriptor = getDescriptorByHandle(handle); + if (descriptor == null) { + Log.w(TAG, "onDescriptorWriteRequest() no desc for handle " + handle); + return; + } + + try { + mCallback.onDescriptorWriteRequest(device, transId, descriptor, + isPrep, needRsp, offset, value); + } catch (Exception ex) { + Log.w(TAG, "Unhandled exception in callback", ex); + } } - } - /** - * Execute pending writes. - * @hide - */ - @Override - public void onExecuteWrite(String address, int transId, - boolean execWrite) { - if (DBG) Log.d(TAG, "onExecuteWrite() - " - + "device=" + address + ", transId=" + transId - + "execWrite=" + execWrite); - - BluetoothDevice device = mAdapter.getRemoteDevice(address); - if (device == null) return; - - try { - mCallback.onExecuteWrite(device, transId, execWrite); - } catch (Exception ex) { - Log.w(TAG, "Unhandled exception in callback", ex); + /** + * Execute pending writes. + * @hide + */ + @Override + public void onExecuteWrite(String address, int transId, + boolean execWrite) { + if (DBG) { + Log.d(TAG, "onExecuteWrite() - " + + "device=" + address + ", transId=" + transId + + "execWrite=" + execWrite); + } + + BluetoothDevice device = mAdapter.getRemoteDevice(address); + if (device == null) return; + + try { + mCallback.onExecuteWrite(device, transId, execWrite); + } catch (Exception ex) { + Log.w(TAG, "Unhandled exception in callback", ex); + } } - } - /** - * A notification/indication has been sent. - * @hide - */ - @Override - public void onNotificationSent(String address, int status) { - if (VDBG) Log.d(TAG, "onNotificationSent() - " - + "device=" + address + ", status=" + status); - - BluetoothDevice device = mAdapter.getRemoteDevice(address); - if (device == null) return; - - try { - mCallback.onNotificationSent(device, status); - } catch (Exception ex) { - Log.w(TAG, "Unhandled exception: " + ex); + /** + * A notification/indication has been sent. + * @hide + */ + @Override + public void onNotificationSent(String address, int status) { + if (VDBG) { + Log.d(TAG, "onNotificationSent() - " + + "device=" + address + ", status=" + status); + } + + BluetoothDevice device = mAdapter.getRemoteDevice(address); + if (device == null) return; + + try { + mCallback.onNotificationSent(device, status); + } catch (Exception ex) { + Log.w(TAG, "Unhandled exception: " + ex); + } } - } - /** - * The MTU for a connection has changed - * @hide - */ - @Override - public void onMtuChanged(String address, int mtu) { - if (DBG) Log.d(TAG, "onMtuChanged() - " - + "device=" + address + ", mtu=" + mtu); - - BluetoothDevice device = mAdapter.getRemoteDevice(address); - if (device == null) return; - - try { - mCallback.onMtuChanged(device, mtu); - } catch (Exception ex) { - Log.w(TAG, "Unhandled exception: " + ex); + /** + * The MTU for a connection has changed + * @hide + */ + @Override + public void onMtuChanged(String address, int mtu) { + if (DBG) { + Log.d(TAG, "onMtuChanged() - " + + "device=" + address + ", mtu=" + mtu); + } + + BluetoothDevice device = mAdapter.getRemoteDevice(address); + if (device == null) return; + + try { + mCallback.onMtuChanged(device, mtu); + } catch (Exception ex) { + Log.w(TAG, "Unhandled exception: " + ex); + } } - } - /** - * The PHY for a connection was updated - * @hide - */ - @Override - public void onPhyUpdate(String address, int txPhy, int rxPhy, int status) { - if (DBG) Log.d(TAG, "onPhyUpdate() - " + "device=" + address + ", txPHy=" + txPhy - + ", rxPHy=" + rxPhy); - - BluetoothDevice device = mAdapter.getRemoteDevice(address); - if (device == null) return; - - try { - mCallback.onPhyUpdate(device, txPhy, rxPhy, status); - } catch (Exception ex) { - Log.w(TAG, "Unhandled exception: " + ex); + /** + * The PHY for a connection was updated + * @hide + */ + @Override + public void onPhyUpdate(String address, int txPhy, int rxPhy, int status) { + if (DBG) { + Log.d(TAG, + "onPhyUpdate() - " + "device=" + address + ", txPHy=" + txPhy + + ", rxPHy=" + rxPhy); + } + + BluetoothDevice device = mAdapter.getRemoteDevice(address); + if (device == null) return; + + try { + mCallback.onPhyUpdate(device, txPhy, rxPhy, status); + } catch (Exception ex) { + Log.w(TAG, "Unhandled exception: " + ex); + } } - } - /** - * The PHY for a connection was read - * @hide - */ - @Override - public void onPhyRead(String address, int txPhy, int rxPhy, int status) { - if (DBG) Log.d(TAG, "onPhyUpdate() - " + "device=" + address + ", txPHy=" + txPhy - + ", rxPHy=" + rxPhy); - - BluetoothDevice device = mAdapter.getRemoteDevice(address); - if (device == null) return; - - try { - mCallback.onPhyRead(device, txPhy, rxPhy, status); - } catch (Exception ex) { - Log.w(TAG, "Unhandled exception: " + ex); + /** + * The PHY for a connection was read + * @hide + */ + @Override + public void onPhyRead(String address, int txPhy, int rxPhy, int status) { + if (DBG) { + Log.d(TAG, + "onPhyUpdate() - " + "device=" + address + ", txPHy=" + txPhy + + ", rxPHy=" + rxPhy); + } + + BluetoothDevice device = mAdapter.getRemoteDevice(address); + if (device == null) return; + + try { + mCallback.onPhyRead(device, txPhy, rxPhy, status); + } catch (Exception ex) { + Log.w(TAG, "Unhandled exception: " + ex); + } } - } - /** - * Callback invoked when the given connection is updated - * @hide - */ - @Override - public void onConnectionUpdated(String address, int interval, int latency, - int timeout, int status) { - if (DBG) Log.d(TAG, "onConnectionUpdated() - Device=" + address + - " interval=" + interval + " latency=" + latency + - " timeout=" + timeout + " status=" + status); - BluetoothDevice device = mAdapter.getRemoteDevice(address); - if (device == null) return; - - try { - mCallback.onConnectionUpdated(device, interval, latency, - timeout, status); - } catch (Exception ex) { - Log.w(TAG, "Unhandled exception: " + ex); + /** + * Callback invoked when the given connection is updated + * @hide + */ + @Override + public void onConnectionUpdated(String address, int interval, int latency, + int timeout, int status) { + if (DBG) { + Log.d(TAG, "onConnectionUpdated() - Device=" + address + + " interval=" + interval + " latency=" + latency + + " timeout=" + timeout + " status=" + status); + } + BluetoothDevice device = mAdapter.getRemoteDevice(address); + if (device == null) return; + + try { + mCallback.onConnectionUpdated(device, interval, latency, + timeout, status); + } catch (Exception ex) { + Log.w(TAG, "Unhandled exception: " + ex); + } } - } - }; + }; /** * Create a BluetoothGattServer proxy object. @@ -369,13 +387,15 @@ public final class BluetoothGattServer implements BluetoothProfile { /** * Returns a characteristic with given handle. + * * @hide */ /*package*/ BluetoothGattCharacteristic getCharacteristicByHandle(int handle) { - for(BluetoothGattService svc : mServices) { - for(BluetoothGattCharacteristic charac : svc.getCharacteristics()) { - if (charac.getInstanceId() == handle) + for (BluetoothGattService svc : mServices) { + for (BluetoothGattCharacteristic charac : svc.getCharacteristics()) { + if (charac.getInstanceId() == handle) { return charac; + } } } return null; @@ -383,14 +403,16 @@ public final class BluetoothGattServer implements BluetoothProfile { /** * Returns a descriptor with given handle. + * * @hide */ /*package*/ BluetoothGattDescriptor getDescriptorByHandle(int handle) { - for(BluetoothGattService svc : mServices) { - for(BluetoothGattCharacteristic charac : svc.getCharacteristics()) { - for(BluetoothGattDescriptor desc : charac.getDescriptors()) { - if (desc.getInstanceId() == handle) + for (BluetoothGattService svc : mServices) { + for (BluetoothGattCharacteristic charac : svc.getCharacteristics()) { + for (BluetoothGattDescriptor desc : charac.getDescriptors()) { + if (desc.getInstanceId() == handle) { return desc; + } } } } @@ -416,10 +438,9 @@ public final class BluetoothGattServer implements BluetoothProfile { * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * - * @param callback GATT callback handler that will receive asynchronous - * callbacks. - * @return true, the callback will be called to notify success or failure, - * false on immediate error + * @param callback GATT callback handler that will receive asynchronous callbacks. + * @return true, the callback will be called to notify success or failure, false on immediate + * error */ /*package*/ boolean registerCallback(BluetoothGattServerCallback callback) { if (DBG) Log.d(TAG, "registerCallback()"); @@ -430,7 +451,7 @@ public final class BluetoothGattServer implements BluetoothProfile { UUID uuid = UUID.randomUUID(); if (DBG) Log.d(TAG, "registerCallback() - UUID=" + uuid); - synchronized(mServerIfLock) { + synchronized (mServerIfLock) { if (mCallback != null) { Log.e(TAG, "App can register callback only once"); return false; @@ -440,7 +461,7 @@ public final class BluetoothGattServer implements BluetoothProfile { try { mService.registerServer(new ParcelUuid(uuid), mBluetoothGattServerCallback); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); mCallback = null; return false; } @@ -473,19 +494,20 @@ public final class BluetoothGattServer implements BluetoothProfile { mService.unregisterServer(mServerIf); mServerIf = 0; } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } /** * Returns a service by UUID, instance and type. + * * @hide */ /*package*/ BluetoothGattService getService(UUID uuid, int instanceId, int type) { - for(BluetoothGattService svc : mServices) { - if (svc.getType() == type && - svc.getInstanceId() == instanceId && - svc.getUuid().equals(uuid)) { + for (BluetoothGattService svc : mServices) { + if (svc.getType() == type + && svc.getInstanceId() == instanceId + && svc.getUuid().equals(uuid)) { return svc; } } @@ -509,20 +531,22 @@ public final class BluetoothGattServer implements BluetoothProfile { * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * - * @param autoConnect Whether to directly connect to the remote device (false) - * or to automatically connect as soon as the remote - * device becomes available (true). + * @param autoConnect Whether to directly connect to the remote device (false) or to + * automatically connect as soon as the remote device becomes available (true). * @return true, if the connection attempt was initiated successfully */ public boolean connect(BluetoothDevice device, boolean autoConnect) { - if (DBG) Log.d(TAG, "connect() - device: " + device.getAddress() + ", auto: " + autoConnect); + if (DBG) { + Log.d(TAG, + "connect() - device: " + device.getAddress() + ", auto: " + autoConnect); + } if (mService == null || mServerIf == 0) return false; try { - mService.serverConnect(mServerIf, device.getAddress(), - autoConnect ? false : true,mTransport); // autoConnect is inverse of "isDirect" + // autoConnect is inverse of "isDirect" + mService.serverConnect(mServerIf, device.getAddress(), !autoConnect, mTransport); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); return false; } @@ -544,35 +568,34 @@ public final class BluetoothGattServer implements BluetoothProfile { try { mService.serverDisconnect(mServerIf, device.getAddress()); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } /** * Set the preferred connection PHY for this app. Please note that this is just a * recommendation, whether the PHY change will happen depends on other applications peferences, - * local and remote controller capabilities. Controller can override these settings. - * <p> - * {@link BluetoothGattServerCallback#onPhyUpdate} will be triggered as a result of this call, even - * if no PHY change happens. It is also triggered when remote device updates the PHY. + * local and remote controller capabilities. Controller can override these settings. <p> {@link + * BluetoothGattServerCallback#onPhyUpdate} will be triggered as a result of this call, even if + * no PHY change happens. It is also triggered when remote device updates the PHY. * * @param device The remote device to send this response to - * @param txPhy preferred transmitter PHY. Bitwise OR of any of - * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, - * and {@link BluetoothDevice#PHY_LE_CODED_MASK}. - * @param rxPhy preferred receiver PHY. Bitwise OR of any of - * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, - * and {@link BluetoothDevice#PHY_LE_CODED_MASK}. + * @param txPhy preferred transmitter PHY. Bitwise OR of any of {@link + * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, and {@link + * BluetoothDevice#PHY_LE_CODED_MASK}. + * @param rxPhy preferred receiver PHY. Bitwise OR of any of {@link + * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, and {@link + * BluetoothDevice#PHY_LE_CODED_MASK}. * @param phyOptions preferred coding to use when transmitting on the LE Coded PHY. Can be one - * of {@link BluetoothDevice#PHY_OPTION_NO_PREFERRED}, - * {@link BluetoothDevice#PHY_OPTION_S2} or {@link BluetoothDevice#PHY_OPTION_S8} + * of {@link BluetoothDevice#PHY_OPTION_NO_PREFERRED}, {@link BluetoothDevice#PHY_OPTION_S2} or + * {@link BluetoothDevice#PHY_OPTION_S8} */ public void setPreferredPhy(BluetoothDevice device, int txPhy, int rxPhy, int phyOptions) { try { mService.serverSetPreferredPhy(mServerIf, device.getAddress(), txPhy, rxPhy, - phyOptions); + phyOptions); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -586,7 +609,7 @@ public final class BluetoothGattServer implements BluetoothProfile { try { mService.serverReadPhy(mServerIf, device.getAddress()); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -597,10 +620,10 @@ public final class BluetoothGattServer implements BluetoothProfile { * is received by one of these callback methods: * * <ul> - * <li>{@link BluetoothGattServerCallback#onCharacteristicReadRequest} - * <li>{@link BluetoothGattServerCallback#onCharacteristicWriteRequest} - * <li>{@link BluetoothGattServerCallback#onDescriptorReadRequest} - * <li>{@link BluetoothGattServerCallback#onDescriptorWriteRequest} + * <li>{@link BluetoothGattServerCallback#onCharacteristicReadRequest} + * <li>{@link BluetoothGattServerCallback#onCharacteristicWriteRequest} + * <li>{@link BluetoothGattServerCallback#onDescriptorReadRequest} + * <li>{@link BluetoothGattServerCallback#onDescriptorWriteRequest} * </ul> * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. @@ -612,15 +635,15 @@ public final class BluetoothGattServer implements BluetoothProfile { * @param value The value of the attribute that was read/written (optional) */ public boolean sendResponse(BluetoothDevice device, int requestId, - int status, int offset, byte[] value) { + int status, int offset, byte[] value) { if (VDBG) Log.d(TAG, "sendResponse() - device: " + device.getAddress()); if (mService == null || mServerIf == 0) return false; try { mService.sendResponse(mServerIf, device.getAddress(), requestId, - status, offset, value); + status, offset, value); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); return false; } return true; @@ -639,13 +662,13 @@ public final class BluetoothGattServer implements BluetoothProfile { * * @param device The remote device to receive the notification/indication * @param characteristic The local characteristic that has been updated - * @param confirm true to request confirmation from the client (indication), - * false to send a notification - * @throws IllegalArgumentException + * @param confirm true to request confirmation from the client (indication), false to send a + * notification * @return true, if the notification has been triggered successfully + * @throws IllegalArgumentException */ public boolean notifyCharacteristicChanged(BluetoothDevice device, - BluetoothGattCharacteristic characteristic, boolean confirm) { + BluetoothGattCharacteristic characteristic, boolean confirm) { if (VDBG) Log.d(TAG, "notifyCharacteristicChanged() - device: " + device.getAddress()); if (mService == null || mServerIf == 0) return false; @@ -662,7 +685,7 @@ public final class BluetoothGattServer implements BluetoothProfile { characteristic.getInstanceId(), confirm, characteristic.getValue()); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); return false; } @@ -680,8 +703,7 @@ public final class BluetoothGattServer implements BluetoothProfile { * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * - * @param service Service to be added to the list of services provided - * by this device. + * @param service Service to be added to the list of services provided by this device. * @return true, if the service has been added successfully */ public boolean addService(BluetoothGattService service) { @@ -693,7 +715,7 @@ public final class BluetoothGattServer implements BluetoothProfile { try { mService.addService(mServerIf, service); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); return false; } @@ -713,14 +735,14 @@ public final class BluetoothGattServer implements BluetoothProfile { if (mService == null || mServerIf == 0) return false; BluetoothGattService intService = getService(service.getUuid(), - service.getInstanceId(), service.getType()); + service.getInstanceId(), service.getType()); if (intService == null) return false; try { mService.removeService(mServerIf, service.getInstanceId()); mServices.remove(intService); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); return false; } @@ -739,7 +761,7 @@ public final class BluetoothGattServer implements BluetoothProfile { mService.clearServices(mServerIf); mServices.clear(); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -751,8 +773,7 @@ public final class BluetoothGattServer implements BluetoothProfile { * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * - * @return List of services. Returns an empty list - * if no services have been added yet. + * @return List of services. Returns an empty list if no services have been added yet. */ public List<BluetoothGattService> getServices() { return mServices; @@ -768,8 +789,8 @@ public final class BluetoothGattServer implements BluetoothProfile { * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param uuid UUID of the requested service - * @return BluetoothGattService if supported, or null if the requested - * service is not offered by this device. + * @return BluetoothGattService if supported, or null if the requested service is not offered by + * this device. */ public BluetoothGattService getService(UUID uuid) { for (BluetoothGattService service : mServices) { @@ -801,8 +822,8 @@ public final class BluetoothGattServer implements BluetoothProfile { */ @Override public List<BluetoothDevice> getConnectedDevices() { - throw new UnsupportedOperationException - ("Use BluetoothManager#getConnectedDevices instead."); + throw new UnsupportedOperationException( + "Use BluetoothManager#getConnectedDevices instead."); } /** @@ -814,7 +835,7 @@ public final class BluetoothGattServer implements BluetoothProfile { */ @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { - throw new UnsupportedOperationException - ("Use BluetoothManager#getDevicesMatchingConnectionStates instead."); + throw new UnsupportedOperationException( + "Use BluetoothManager#getDevicesMatchingConnectionStates instead."); } } diff --git a/core/java/android/bluetooth/BluetoothGattServerCallback.java b/core/java/android/bluetooth/BluetoothGattServerCallback.java index 02307bd9ef9f..22eba351b361 100644 --- a/core/java/android/bluetooth/BluetoothGattServerCallback.java +++ b/core/java/android/bluetooth/BluetoothGattServerCallback.java @@ -16,8 +16,6 @@ package android.bluetooth; -import android.bluetooth.BluetoothDevice; - /** * This abstract class is used to implement {@link BluetoothGattServer} callbacks. */ @@ -28,19 +26,18 @@ public abstract class BluetoothGattServerCallback { * * @param device Remote device that has been connected or disconnected. * @param status Status of the connect or disconnect operation. - * @param newState Returns the new connection state. Can be one of - * {@link BluetoothProfile#STATE_DISCONNECTED} or - * {@link BluetoothProfile#STATE_CONNECTED} + * @param newState Returns the new connection state. Can be one of {@link + * BluetoothProfile#STATE_DISCONNECTED} or {@link BluetoothProfile#STATE_CONNECTED} */ public void onConnectionStateChange(BluetoothDevice device, int status, - int newState) { + int newState) { } /** * Indicates whether a local service has been added successfully. * - * @param status Returns {@link BluetoothGatt#GATT_SUCCESS} if the service - * was added successfully. + * @param status Returns {@link BluetoothGatt#GATT_SUCCESS} if the service was added + * successfully. * @param service The service that has been added */ public void onServiceAdded(int status, BluetoothGattService service) { @@ -58,7 +55,7 @@ public abstract class BluetoothGattServerCallback { * @param characteristic Characteristic to be read */ public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, - int offset, BluetoothGattCharacteristic characteristic) { + int offset, BluetoothGattCharacteristic characteristic) { } /** @@ -70,16 +67,15 @@ public abstract class BluetoothGattServerCallback { * @param device The remote device that has requested the write operation * @param requestId The Id of the request * @param characteristic Characteristic to be written to. - * @param preparedWrite true, if this write operation should be queued for - * later execution. + * @param preparedWrite true, if this write operation should be queued for later execution. * @param responseNeeded true, if the remote device requires a response * @param offset The offset given for the value * @param value The value the client wants to assign to the characteristic */ public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, - BluetoothGattCharacteristic characteristic, - boolean preparedWrite, boolean responseNeeded, - int offset, byte[] value) { + BluetoothGattCharacteristic characteristic, + boolean preparedWrite, boolean responseNeeded, + int offset, byte[] value) { } /** @@ -94,7 +90,7 @@ public abstract class BluetoothGattServerCallback { * @param descriptor Descriptor to be read */ public void onDescriptorReadRequest(BluetoothDevice device, int requestId, - int offset, BluetoothGattDescriptor descriptor) { + int offset, BluetoothGattDescriptor descriptor) { } /** @@ -106,16 +102,15 @@ public abstract class BluetoothGattServerCallback { * @param device The remote device that has requested the write operation * @param requestId The Id of the request * @param descriptor Descriptor to be written to. - * @param preparedWrite true, if this write operation should be queued for - * later execution. + * @param preparedWrite true, if this write operation should be queued for later execution. * @param responseNeeded true, if the remote device requires a response * @param offset The offset given for the value * @param value The value the client wants to assign to the descriptor */ public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, - BluetoothGattDescriptor descriptor, - boolean preparedWrite, boolean responseNeeded, - int offset, byte[] value) { + BluetoothGattDescriptor descriptor, + boolean preparedWrite, boolean responseNeeded, + int offset, byte[] value) { } /** @@ -126,8 +121,7 @@ public abstract class BluetoothGattServerCallback { * * @param device The remote device that has requested the write operations * @param requestId The Id of the request - * @param execute Whether the pending writes should be executed (true) or - * cancelled (false) + * @param execute Whether the pending writes should be executed (true) or cancelled (false) */ public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) { } @@ -163,12 +157,12 @@ public abstract class BluetoothGattServerCallback { * of remote device changing the PHY. * * @param device The remote device - * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, - * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED} - * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, - * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED} - * @param status Status of the PHY update operation. - * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds. + * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link + * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED} + * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link + * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED} + * @param status Status of the PHY update operation. {@link BluetoothGatt#GATT_SUCCESS} if the + * operation succeeds. */ public void onPhyUpdate(BluetoothDevice device, int txPhy, int rxPhy, int status) { } @@ -177,12 +171,12 @@ public abstract class BluetoothGattServerCallback { * Callback triggered as result of {@link BluetoothGattServer#readPhy} * * @param device The remote device that requested the PHY read - * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, - * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED} - * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, - * {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED} - * @param status Status of the PHY read operation. - * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds. + * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link + * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED} + * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M}, {@link + * BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED} + * @param status Status of the PHY read operation. {@link BluetoothGatt#GATT_SUCCESS} if the + * operation succeeds. */ public void onPhyRead(BluetoothDevice device, int txPhy, int rxPhy, int status) { } @@ -190,19 +184,19 @@ public abstract class BluetoothGattServerCallback { /** * Callback indicating the connection parameters were updated. * - * @param device The remote device involved - * @param interval Connection interval used on this connection, 1.25ms unit. Valid - * range is from 6 (7.5ms) to 3200 (4000ms). - * @param latency Slave latency for the connection in number of connection events. Valid - * range is from 0 to 499 - * @param timeout Supervision timeout for this connection, in 10ms unit. Valid range is - * from 10 (0.1s) to 3200 (32s) + * @param gatt The remote device involved + * @param interval Connection interval used on this connection, 1.25ms unit. Valid range is from + * 6 (7.5ms) to 3200 (4000ms). + * @param latency Slave latency for the connection in number of connection events. Valid range + * is from 0 to 499 + * @param timeout Supervision timeout for this connection, in 10ms unit. Valid range is from 10 + * (0.1s) to 3200 (32s) * @param status {@link BluetoothGatt#GATT_SUCCESS} if the connection has been updated - * successfully + * successfully * @hide */ public void onConnectionUpdated(BluetoothDevice gatt, int interval, int latency, int timeout, - int status) { + int status) { } } diff --git a/core/java/android/bluetooth/BluetoothGattService.java b/core/java/android/bluetooth/BluetoothGattService.java index c888a451e9e5..ce1dc1ce6311 100644 --- a/core/java/android/bluetooth/BluetoothGattService.java +++ b/core/java/android/bluetooth/BluetoothGattService.java @@ -16,8 +16,9 @@ package android.bluetooth; import android.os.Parcel; -import android.os.Parcelable; import android.os.ParcelUuid; +import android.os.Parcelable; + import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -44,30 +45,35 @@ public class BluetoothGattService implements Parcelable { /** * The remote device his service is associated with. * This applies to client applications only. + * * @hide */ protected BluetoothDevice mDevice; /** * The UUID of this service. + * * @hide */ protected UUID mUuid; /** * Instance ID for this service. + * * @hide */ protected int mInstanceId; /** * Handle counter override (for conformance testing). + * * @hide */ protected int mHandles = 0; /** * Service type (Primary/Secondary). + * * @hide */ protected int mServiceType; @@ -93,8 +99,8 @@ public class BluetoothGattService implements Parcelable { * * @param uuid The UUID for this service * @param serviceType The type of this service, - * {@link BluetoothGattService#SERVICE_TYPE_PRIMARY} or - * {@link BluetoothGattService#SERVICE_TYPE_SECONDARY} + * {@link BluetoothGattService#SERVICE_TYPE_PRIMARY} + * or {@link BluetoothGattService#SERVICE_TYPE_SECONDARY} */ public BluetoothGattService(UUID uuid, int serviceType) { mDevice = null; @@ -107,10 +113,11 @@ public class BluetoothGattService implements Parcelable { /** * Create a new BluetoothGattService + * * @hide */ /*package*/ BluetoothGattService(BluetoothDevice device, UUID uuid, - int instanceId, int serviceType) { + int instanceId, int serviceType) { mDevice = device; mUuid = uuid; mInstanceId = instanceId; @@ -121,6 +128,7 @@ public class BluetoothGattService implements Parcelable { /** * Create a new BluetoothGattService + * * @hide */ public BluetoothGattService(UUID uuid, int instanceId, int serviceType) { @@ -148,15 +156,15 @@ public class BluetoothGattService implements Parcelable { ArrayList<BluetoothGattIncludedService> includedServices = new ArrayList<BluetoothGattIncludedService>(mIncludedServices.size()); - for(BluetoothGattService s : mIncludedServices) { + for (BluetoothGattService s : mIncludedServices) { includedServices.add(new BluetoothGattIncludedService(s.getUuid(), - s.getInstanceId(), s.getType())); + s.getInstanceId(), s.getType())); } out.writeTypedList(includedServices); - } + } - public static final Parcelable.Creator<BluetoothGattService> CREATOR - = new Parcelable.Creator<BluetoothGattService>() { + public static final Parcelable.Creator<BluetoothGattService> CREATOR = + new Parcelable.Creator<BluetoothGattService>() { public BluetoothGattService createFromParcel(Parcel in) { return new BluetoothGattService(in); } @@ -167,7 +175,7 @@ public class BluetoothGattService implements Parcelable { }; private BluetoothGattService(Parcel in) { - mUuid = ((ParcelUuid)in.readParcelable(null)).getUuid(); + mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid(); mInstanceId = in.readInt(); mServiceType = in.readInt(); @@ -189,13 +197,14 @@ public class BluetoothGattService implements Parcelable { if (chrcs != null) { for (BluetoothGattIncludedService isvc : inclSvcs) { mIncludedServices.add(new BluetoothGattService(null, isvc.getUuid(), - isvc.getInstanceId(), isvc.getType())); + isvc.getInstanceId(), isvc.getType())); } } } /** * Returns the device associated with this service. + * * @hide */ /*package*/ BluetoothDevice getDevice() { @@ -204,10 +213,11 @@ public class BluetoothGattService implements Parcelable { /** * Returns the device associated with this service. + * * @hide */ /*package*/ void setDevice(BluetoothDevice device) { - this.mDevice = device; + mDevice = device; } /** @@ -237,19 +247,22 @@ public class BluetoothGattService implements Parcelable { /** * Get characteristic by UUID and instanceId. + * * @hide */ /*package*/ BluetoothGattCharacteristic getCharacteristic(UUID uuid, int instanceId) { - for(BluetoothGattCharacteristic characteristic : mCharacteristics) { + for (BluetoothGattCharacteristic characteristic : mCharacteristics) { if (uuid.equals(characteristic.getUuid()) - && characteristic.getInstanceId() == instanceId) + && characteristic.getInstanceId() == instanceId) { return characteristic; + } } return null; } /** * Force the instance ID. + * * @hide */ public void setInstanceId(int instanceId) { @@ -258,6 +271,7 @@ public class BluetoothGattService implements Parcelable { /** * Get the handle count override (conformance testing. + * * @hide */ /*package*/ int getHandles() { @@ -267,6 +281,7 @@ public class BluetoothGattService implements Parcelable { /** * Force the number of handles to reserve for this service. * This is needed for conformance testing only. + * * @hide */ public void setHandles(int handles) { @@ -275,6 +290,7 @@ public class BluetoothGattService implements Parcelable { /** * Add an included service to the internal map. + * * @hide */ public void addIncludedService(BluetoothGattService includedService) { @@ -313,8 +329,7 @@ public class BluetoothGattService implements Parcelable { /** * Get the list of included GATT services for this service. * - * @return List of included services or empty list if no included services - * were discovered. + * @return List of included services or empty list if no included services were discovered. */ public List<BluetoothGattService> getIncludedServices() { return mIncludedServices; @@ -341,30 +356,33 @@ public class BluetoothGattService implements Parcelable { * UUID, the first instance of a characteristic with the given UUID * is returned. * - * @return GATT characteristic object or null if no characteristic with the - * given UUID was found. + * @return GATT characteristic object or null if no characteristic with the given UUID was + * found. */ public BluetoothGattCharacteristic getCharacteristic(UUID uuid) { - for(BluetoothGattCharacteristic characteristic : mCharacteristics) { - if (uuid.equals(characteristic.getUuid())) + for (BluetoothGattCharacteristic characteristic : mCharacteristics) { + if (uuid.equals(characteristic.getUuid())) { return characteristic; + } } return null; } /** * Returns whether the uuid of the service should be advertised. + * * @hide */ public boolean isAdvertisePreferred() { - return mAdvertisePreferred; + return mAdvertisePreferred; } /** * Set whether the service uuid should be advertised. + * * @hide */ public void setAdvertisePreferred(boolean advertisePreferred) { - this.mAdvertisePreferred = advertisePreferred; + mAdvertisePreferred = advertisePreferred; } } diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java index c84643fc46b3..be1ce63cadc2 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -56,9 +56,9 @@ public final class BluetoothHeadset implements BluetoothProfile { * * <p>This intent will have 3 extras: * <ul> - * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> - * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> * </ul> * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING}, @@ -69,7 +69,7 @@ public final class BluetoothHeadset implements BluetoothProfile { */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CONNECTION_STATE_CHANGED = - "android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED"; + "android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED"; /** * Intent used to broadcast the change in the Audio Connection state of the @@ -77,9 +77,9 @@ public final class BluetoothHeadset implements BluetoothProfile { * * <p>This intent will have 3 extras: * <ul> - * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> - * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> * </ul> * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of * {@link #STATE_AUDIO_CONNECTED}, {@link #STATE_AUDIO_DISCONNECTED}, @@ -89,7 +89,7 @@ public final class BluetoothHeadset implements BluetoothProfile { */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_AUDIO_STATE_CHANGED = - "android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED"; + "android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED"; /** @@ -98,19 +98,19 @@ public final class BluetoothHeadset implements BluetoothProfile { * * <p>This intent will have 4 extras and 1 category. * <ul> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote Bluetooth Device - * </li> - * <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD} - The vendor - * specific command </li> - * <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE} - The AT - * command type which can be one of {@link #AT_CMD_TYPE_READ}, - * {@link #AT_CMD_TYPE_TEST}, or {@link #AT_CMD_TYPE_SET}, - * {@link #AT_CMD_TYPE_BASIC},{@link #AT_CMD_TYPE_ACTION}. </li> - * <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS} - Command - * arguments. </li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote Bluetooth Device + * </li> + * <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD} - The vendor + * specific command </li> + * <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE} - The AT + * command type which can be one of {@link #AT_CMD_TYPE_READ}, + * {@link #AT_CMD_TYPE_TEST}, or {@link #AT_CMD_TYPE_SET}, + * {@link #AT_CMD_TYPE_BASIC},{@link #AT_CMD_TYPE_ACTION}. </li> + * <li> {@link #EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS} - Command + * arguments. </li> * </ul> * - *<p> The category is the Company ID of the vendor defining the + * <p> The category is the Company ID of the vendor defining the * vendor-specific command. {@link BluetoothAssignedNumbers} * * For example, for Plantronics specific events @@ -118,9 +118,9 @@ public final class BluetoothHeadset implements BluetoothProfile { * * <p> For example, an AT+XEVENT=foo,3 will get translated into * <ul> - * <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD = +XEVENT </li> - * <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE = AT_CMD_TYPE_SET </li> - * <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS = foo, 3 </li> + * <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD = +XEVENT </li> + * <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE = AT_CMD_TYPE_SET </li> + * <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS = foo, 3 </li> * </ul> * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission * to receive. @@ -191,7 +191,7 @@ public final class BluetoothHeadset implements BluetoothProfile { * The intent category to be used with {@link #ACTION_VENDOR_SPECIFIC_HEADSET_EVENT} * for the companyId */ - public static final String VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY = + public static final String VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY = "android.bluetooth.headset.intent.category.companyid"; /** @@ -201,12 +201,14 @@ public final class BluetoothHeadset implements BluetoothProfile { /** * A vendor-specific AT command + * * @hide */ public static final String VENDOR_SPECIFIC_HEADSET_EVENT_XAPL = "+XAPL"; /** * A vendor-specific AT command + * * @hide */ public static final String VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV = "+IPHONEACCEV"; @@ -214,18 +216,21 @@ public final class BluetoothHeadset implements BluetoothProfile { /** * Battery level indicator associated with * {@link #VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV} + * * @hide */ public static final int VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV_BATTERY_LEVEL = 1; /** * A vendor-specific AT command + * * @hide */ public static final String VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT = "+XEVENT"; /** * Battery level indicator associated with {@link #VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT} + * * @hide */ public static final String VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT_BATTERY_LEVEL = "BATTERY"; @@ -258,17 +263,18 @@ public final class BluetoothHeadset implements BluetoothProfile { * * <p>This intent will have 3 extras: * <ul> - * <li> {@link #EXTRA_HF_INDICATORS_IND_ID} - The Assigned number of headset Indicator which - * is supported by the headset ( as indicated by AT+BIND command in the SLC - * sequence) or whose value is changed (indicated by AT+BIEV command) </li> - * <li> {@link #EXTRA_HF_INDICATORS_IND_VALUE} - Updated value of headset indicator. </li> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - Remote device. </li> + * <li> {@link #EXTRA_HF_INDICATORS_IND_ID} - The Assigned number of headset Indicator which + * is supported by the headset ( as indicated by AT+BIND command in the SLC + * sequence) or whose value is changed (indicated by AT+BIEV command) </li> + * <li> {@link #EXTRA_HF_INDICATORS_IND_VALUE} - Updated value of headset indicator. </li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - Remote device. </li> * </ul> * <p>{@link #EXTRA_HF_INDICATORS_IND_ID} is defined by Bluetooth SIG and each of the indicators - * are given an assigned number. Below shows the assigned number of Indicator added so far + * are given an assigned number. Below shows the assigned number of Indicator added so far * - Enhanced Safety - 1, Valid Values: 0 - Disabled, 1 - Enabled * - Battery Level - 2, Valid Values: 0~100 - Remaining level of Battery * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to receive. + * * @hide */ public static final String ACTION_HF_INDICATORS_VALUE_CHANGED = @@ -278,6 +284,7 @@ public final class BluetoothHeadset implements BluetoothProfile { * A int extra field in {@link #ACTION_HF_INDICATORS_VALUE_CHANGED} * intents that contains the assigned number of the headset indicator as defined by * Bluetooth SIG that is being sent. Value range is 0-65535 as defined in HFP 1.7 + * * @hide */ public static final String EXTRA_HF_INDICATORS_IND_ID = @@ -286,6 +293,7 @@ public final class BluetoothHeadset implements BluetoothProfile { /** * A int extra field in {@link #ACTION_HF_INDICATORS_VALUE_CHANGED} * intents that contains the value of the Headset indicator that is being sent. + * * @hide */ public static final String EXTRA_HF_INDICATORS_IND_VALUE = @@ -301,27 +309,27 @@ public final class BluetoothHeadset implements BluetoothProfile { private IBluetoothHeadset mService; private BluetoothAdapter mAdapter; - final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { public void onBluetoothStateChange(boolean up) { if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); if (!up) { - if (VDBG) Log.d(TAG,"Unbinding service..."); + if (VDBG) Log.d(TAG, "Unbinding service..."); doUnbind(); } else { synchronized (mConnection) { try { if (mService == null) { - if (VDBG) Log.d(TAG,"Binding service..."); + if (VDBG) Log.d(TAG, "Binding service..."); doBind(); } } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } } - }; + }; /** * Create a BluetoothHeadset proxy object. @@ -336,7 +344,7 @@ public final class BluetoothHeadset implements BluetoothProfile { try { mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -360,7 +368,7 @@ public final class BluetoothHeadset implements BluetoothProfile { mAdapter.getBluetoothManager().unbindBluetoothProfileService( BluetoothProfile.HEADSET, mConnection); } catch (RemoteException e) { - Log.e(TAG,"Unable to unbind HeadsetService", e); + Log.e(TAG, "Unable to unbind HeadsetService", e); } } } @@ -380,7 +388,7 @@ public final class BluetoothHeadset implements BluetoothProfile { try { mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); } catch (Exception e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } mServiceListener = null; @@ -405,14 +413,12 @@ public final class BluetoothHeadset implements BluetoothProfile { * permission. * * @param device Remote Bluetooth Device - * @return false on immediate error, - * true otherwise + * @return false on immediate error, true otherwise * @hide */ public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.connect(device); } catch (RemoteException e) { @@ -446,19 +452,17 @@ public final class BluetoothHeadset implements BluetoothProfile { * permission. * * @param device Remote Bluetooth Device - * @return false on immediate error, - * true otherwise + * @return false on immediate error, true otherwise * @hide */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.disconnect(device); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return false; } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -468,6 +472,7 @@ public final class BluetoothHeadset implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); if (mService != null && isEnabled()) { @@ -485,6 +490,7 @@ public final class BluetoothHeadset implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); if (mService != null && isEnabled()) { @@ -502,10 +508,10 @@ public final class BluetoothHeadset implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getConnectionState(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.getConnectionState(device); } catch (RemoteException e) { @@ -521,7 +527,7 @@ public final class BluetoothHeadset implements BluetoothProfile { * Set priority of the profile * * <p> The device should already be paired. - * Priority can be one of {@link #PRIORITY_ON} or + * Priority can be one of {@link #PRIORITY_ON} or * {@link #PRIORITY_OFF}, * * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} @@ -534,11 +540,10 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { - if (priority != BluetoothProfile.PRIORITY_OFF && - priority != BluetoothProfile.PRIORITY_ON) { - return false; + if (mService != null && isEnabled() && isValidDevice(device)) { + if (priority != BluetoothProfile.PRIORITY_OFF + && priority != BluetoothProfile.PRIORITY_ON) { + return false; } try { return mService.setPriority(device, priority); @@ -566,8 +571,7 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.getPriority(device); } catch (RemoteException e) { @@ -596,18 +600,16 @@ public final class BluetoothHeadset implements BluetoothProfile { * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param device Bluetooth headset - * @return false if there is no headset connected of if the - * connected headset doesn't support voice recognition - * or on error, true otherwise + * @return false if there is no headset connected of if the connected headset doesn't support + * voice recognition or on error, true otherwise */ public boolean startVoiceRecognition(BluetoothDevice device) { if (DBG) log("startVoiceRecognition()"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.startVoiceRecognition(device); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -621,17 +623,15 @@ public final class BluetoothHeadset implements BluetoothProfile { * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param device Bluetooth headset - * @return false if there is no headset connected - * or on error, true otherwise + * @return false if there is no headset connected or on error, true otherwise */ public boolean stopVoiceRecognition(BluetoothDevice device) { if (DBG) log("stopVoiceRecognition()"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.stopVoiceRecognition(device); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -644,17 +644,15 @@ public final class BluetoothHeadset implements BluetoothProfile { * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param device Bluetooth headset - * @return true if SCO is connected, - * false otherwise or on error + * @return true if SCO is connected, false otherwise or on error */ public boolean isAudioConnected(BluetoothDevice device) { if (VDBG) log("isAudioConnected()"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { - return mService.isAudioConnected(device); + return mService.isAudioConnected(device); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -671,18 +669,16 @@ public final class BluetoothHeadset implements BluetoothProfile { * rule of thumb, each AT command prevents the CPU from sleeping for 500 ms * * @param device the bluetooth headset. - * @return monotonically increasing battery usage hint, or a negative error - * code on error + * @return monotonically increasing battery usage hint, or a negative error code on error * @hide */ public int getBatteryUsageHint(BluetoothDevice device) { if (VDBG) log("getBatteryUsageHint()"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.getBatteryUsageHint(device); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -711,7 +707,9 @@ public final class BluetoothHeadset implements BluetoothProfile { if (mService != null && isEnabled()) { try { return mService.acceptIncomingConnect(device); - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); @@ -721,6 +719,7 @@ public final class BluetoothHeadset implements BluetoothProfile { /** * Reject the incoming connection. + * * @hide */ public boolean rejectIncomingConnect(BluetoothDevice device) { @@ -728,7 +727,9 @@ public final class BluetoothHeadset implements BluetoothProfile { if (mService != null) { try { return mService.rejectIncomingConnect(device); - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); @@ -747,7 +748,9 @@ public final class BluetoothHeadset implements BluetoothProfile { if (mService != null && !isDisabled()) { try { return mService.getAudioState(device); - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); @@ -763,7 +766,6 @@ public final class BluetoothHeadset implements BluetoothProfile { * Note: This is an internal function and shouldn't be exposed * * @param allowed {@code true} if the profile can reroute audio, {@code false} otherwise. - * * @hide */ public void setAudioRouteAllowed(boolean allowed) { @@ -771,7 +773,9 @@ public final class BluetoothHeadset implements BluetoothProfile { if (mService != null && isEnabled()) { try { mService.setAudioRouteAllowed(allowed); - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); @@ -789,7 +793,9 @@ public final class BluetoothHeadset implements BluetoothProfile { if (mService != null && isEnabled()) { try { return mService.getAudioRouteAllowed(); - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); @@ -800,9 +806,8 @@ public final class BluetoothHeadset implements BluetoothProfile { /** * Force SCO audio to be opened regardless any other restrictions * - * @param forced Whether or not SCO audio connection should be forced: - * True to force SCO audio - * False to use SCO audio in normal manner + * @param forced Whether or not SCO audio connection should be forced: True to force SCO audio + * False to use SCO audio in normal manner * @hide */ public void setForceScoAudio(boolean forced) { @@ -811,7 +816,7 @@ public final class BluetoothHeadset implements BluetoothProfile { try { mService.setForceScoAudio(forced); } catch (RemoteException e) { - Log.e(TAG, e.toString()); + Log.e(TAG, e.toString()); } } else { Log.w(TAG, "Proxy not attached to service"); @@ -824,17 +829,16 @@ public final class BluetoothHeadset implements BluetoothProfile { * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * - * @return true if SCO is connected, - * false otherwise or on error + * @return true if SCO is connected, false otherwise or on error * @hide */ public boolean isAudioOn() { if (VDBG) log("isAudioOn()"); if (mService != null && isEnabled()) { try { - return mService.isAudioOn(); + return mService.isAudioOn(); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -846,9 +850,8 @@ public final class BluetoothHeadset implements BluetoothProfile { * Initiates a connection of headset audio. * It setup SCO channel with remote connected headset device. * - * @return true if successful - * false if there was some error such as - * there is no connected headset + * @return true if successful false if there was some error such as there is no connected + * headset * @hide */ public boolean connectAudio() { @@ -869,9 +872,8 @@ public final class BluetoothHeadset implements BluetoothProfile { * Initiates a disconnection of headset audio. * It tears down the SCO channel from remote headset device. * - * @return true if successful - * false if there was some error such as - * there is no connected SCO channel + * @return true if successful false if there was some error such as there is no connected SCO + * channel * @hide */ public boolean disconnectAudio() { @@ -946,7 +948,7 @@ public final class BluetoothHeadset implements BluetoothProfile { * @hide */ public void phoneStateChanged(int numActive, int numHeld, int callState, String number, - int type) { + int type) { if (mService != null && isEnabled()) { try { mService.phoneStateChanged(numActive, numHeld, callState, number, type); @@ -965,7 +967,7 @@ public final class BluetoothHeadset implements BluetoothProfile { * @hide */ public void clccResponse(int index, int direction, int status, int mode, boolean mpty, - String number, int type) { + String number, int type) { if (mService != null && isEnabled()) { try { mService.clccResponse(index, direction, status, mode, mpty, number, type); @@ -981,9 +983,9 @@ public final class BluetoothHeadset implements BluetoothProfile { /** * Sends a vendor-specific unsolicited result code to the headset. * - * <p>The actual string to be sent is <code>command + ": " + arg</code>. - * For example, if {@code command} is {@link #VENDOR_RESULT_CODE_COMMAND_ANDROID} and {@code arg} - * is {@code "0"}, the string <code>"+ANDROID: 0"</code> will be sent. + * <p>The actual string to be sent is <code>command + ": " + arg</code>. For example, if {@code + * command} is {@link #VENDOR_RESULT_CODE_COMMAND_ANDROID} and {@code arg} is {@code "0"}, the + * string <code>"+ANDROID: 0"</code> will be sent. * * <p>Currently only {@link #VENDOR_RESULT_CODE_COMMAND_ANDROID} is allowed as {@code command}. * @@ -993,7 +995,7 @@ public final class BluetoothHeadset implements BluetoothProfile { * @param command A vendor-specific command. * @param arg The argument that will be attached to the command. * @return {@code false} if there is no headset connected, or if the command is not an allowed - * vendor-specific unsolicited result code, or on error. {@code true} otherwise. + * vendor-specific unsolicited result code, or on error. {@code true} otherwise. * @throws IllegalArgumentException if {@code command} is {@code null}. */ public boolean sendVendorSpecificResultCode(BluetoothDevice device, String command, @@ -1004,8 +1006,7 @@ public final class BluetoothHeadset implements BluetoothProfile { if (command == null) { throw new IllegalArgumentException("command is null"); } - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.sendVendorSpecificResultCode(device, command, arg); } catch (RemoteException e) { @@ -1021,9 +1022,8 @@ public final class BluetoothHeadset implements BluetoothProfile { /** * enable WBS codec setting. * - * @return true if successful - * false if there was some error such as - * there is no connected headset + * @return true if successful false if there was some error such as there is no connected + * headset * @hide */ public boolean enableWBS() { @@ -1043,9 +1043,8 @@ public final class BluetoothHeadset implements BluetoothProfile { /** * disable WBS codec settting. It set NBS codec. * - * @return true if successful - * false if there was some error such as - * there is no connected headset + * @return true if successful false if there was some error such as there is no connected + * headset * @hide */ public boolean disableWBS() { @@ -1065,8 +1064,7 @@ public final class BluetoothHeadset implements BluetoothProfile { /** * check if in-band ringing is supported for this platform. * - * @return true if in-band ringing is supported - * false if in-band ringing is not supported + * @return true if in-band ringing is supported false if in-band ringing is not supported * @hide */ public static boolean isInbandRingingSupported(Context context) { @@ -1078,16 +1076,16 @@ public final class BluetoothHeadset implements BluetoothProfile { * Send Headset the BIND response from AG to report change in the status of the * HF indicators to the headset * - * @param ind_id Assigned Number of the indicator (defined by SIG) - * @param ind_status - * possible values- false-Indicator is disabled, no value changes shall be sent for this indicator - * true-Indicator is enabled, value changes may be sent for this indicator + * @param indId Assigned Number of the indicator (defined by SIG) + * @param indStatus possible values- false-Indicator is disabled, no value changes shall be + * sent for this indicator true-Indicator is enabled, value changes may be sent for this + * indicator * @hide */ - public void bindResponse(int ind_id, boolean ind_status) { + public void bindResponse(int indId, boolean indStatus) { if (mService != null && isEnabled()) { try { - mService.bindResponse(ind_id, ind_status); + mService.bindResponse(indId, indStatus); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -1097,8 +1095,8 @@ public final class BluetoothHeadset implements BluetoothProfile { } } - private final IBluetoothProfileServiceConnection mConnection - = new IBluetoothProfileServiceConnection.Stub() { + private final IBluetoothProfileServiceConnection mConnection = + new IBluetoothProfileServiceConnection.Stub() { @Override public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "Proxy object connected"); @@ -1106,6 +1104,7 @@ public final class BluetoothHeadset implements BluetoothProfile { mHandler.sendMessage(mHandler.obtainMessage( MESSAGE_HEADSET_SERVICE_CONNECTED)); } + @Override public void onServiceDisconnected(ComponentName className) { if (DBG) Log.d(TAG, "Proxy object disconnected"); @@ -1116,20 +1115,20 @@ public final class BluetoothHeadset implements BluetoothProfile { }; private boolean isEnabled() { - if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; - return false; + if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; + return false; } private boolean isDisabled() { - if (mAdapter.getState() == BluetoothAdapter.STATE_OFF) return true; - return false; + if (mAdapter.getState() == BluetoothAdapter.STATE_OFF) return true; + return false; } private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; + if (device == null) return false; - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; + return false; } private static void log(String msg) { diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java index 544b3b95db0a..7ed2d2e98f7f 100644 --- a/core/java/android/bluetooth/BluetoothHeadsetClient.java +++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java @@ -28,7 +28,6 @@ import android.util.Log; import java.util.ArrayList; import java.util.List; -import java.util.UUID; /** * Public API to control Hands Free Profile (HFP role only). @@ -38,7 +37,7 @@ import java.util.UUID; * <p> * * @hide - * */ + */ public final class BluetoothHeadsetClient implements BluetoothProfile { private static final String TAG = "BluetoothHeadsetClient"; private static final boolean DBG = true; @@ -71,7 +70,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * and not supported ones are <strong>not</strong> being sent at all.</p> */ public static final String ACTION_CONNECTION_STATE_CHANGED = - "android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED"; + "android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED"; /** * Intent sent whenever audio state changes. @@ -89,7 +88,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * indicating wide band speech support.</p> */ public static final String ACTION_AUDIO_STATE_CHANGED = - "android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED"; + "android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED"; /** * Intent sending updates of the Audio Gateway state. @@ -146,7 +145,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { /** * Extra with information if connected audio is WBS. * <p>Possible values: <code>true</code>, - * <code>false</code>.</p> + * <code>false</code>.</p> */ public static final String EXTRA_AUDIO_WBS = "android.bluetooth.headsetclient.extra.AUDIO_WBS"; @@ -154,7 +153,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { /** * Extra for AG_EVENT indicates network status. * <p>Value: 0 - network unavailable, - * 1 - network available </p> + * 1 - network available </p> */ public static final String EXTRA_NETWORK_STATUS = "android.bluetooth.headsetclient.extra.NETWORK_STATUS"; @@ -167,7 +166,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { /** * Extra for AG_EVENT intent indicates roaming state. * <p>Value: 0 - no roaming - * 1 - active roaming</p> + * 1 - active roaming</p> */ public static final String EXTRA_NETWORK_ROAMING = "android.bluetooth.headsetclient.extra.NETWORK_ROAMING"; @@ -186,16 +185,16 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { /** * Extra for AG_EVENT intent indicates voice recognition state. * <p>Value: - * 0 - voice recognition stopped, - * 1 - voice recognition started.</p> + * 0 - voice recognition stopped, + * 1 - voice recognition started.</p> */ public static final String EXTRA_VOICE_RECOGNITION = "android.bluetooth.headsetclient.extra.VOICE_RECOGNITION"; /** * Extra for AG_EVENT intent indicates in band ring state. * <p>Value: - * 0 - in band ring tone not supported, or - * 1 - in band ring tone supported.</p> + * 0 - in band ring tone not supported, or + * 1 - in band ring tone supported.</p> */ public static final String EXTRA_IN_BAND_RING = "android.bluetooth.headsetclient.extra.IN_BAND_RING"; @@ -208,8 +207,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { "android.bluetooth.headsetclient.extra.SUBSCRIBER_INFO"; /** - * Extra for AG_CALL_CHANGED intent indicates the - * {@link BluetoothHeadsetClientCall} object that has changed. + * Extra for AG_CALL_CHANGED intent indicates the + * {@link BluetoothHeadsetClientCall} object that has changed. */ public static final String EXTRA_CALL = "android.bluetooth.headsetclient.extra.CALL"; @@ -251,53 +250,53 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { /** * AG feature: three way calling. */ - public final static String EXTRA_AG_FEATURE_3WAY_CALLING = + public static final String EXTRA_AG_FEATURE_3WAY_CALLING = "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_3WAY_CALLING"; /** * AG feature: voice recognition. */ - public final static String EXTRA_AG_FEATURE_VOICE_RECOGNITION = + public static final String EXTRA_AG_FEATURE_VOICE_RECOGNITION = "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_VOICE_RECOGNITION"; /** * AG feature: fetching phone number for voice tagging procedure. */ - public final static String EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT = + public static final String EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT = "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT"; /** * AG feature: ability to reject incoming call. */ - public final static String EXTRA_AG_FEATURE_REJECT_CALL = + public static final String EXTRA_AG_FEATURE_REJECT_CALL = "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_REJECT_CALL"; /** * AG feature: enhanced call handling (terminate specific call, private consultation). */ - public final static String EXTRA_AG_FEATURE_ECC = + public static final String EXTRA_AG_FEATURE_ECC = "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_ECC"; /** * AG feature: response and hold. */ - public final static String EXTRA_AG_FEATURE_RESPONSE_AND_HOLD = + public static final String EXTRA_AG_FEATURE_RESPONSE_AND_HOLD = "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_RESPONSE_AND_HOLD"; /** * AG call handling feature: accept held or waiting call in three way calling scenarios. */ - public final static String EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL = + public static final String EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL = "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL"; /** * AG call handling feature: release held or waiting call in three way calling scenarios. */ - public final static String EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL = + public static final String EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL = "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL"; /** * AG call handling feature: release active call and accept held or waiting call in three way * calling scenarios. */ - public final static String EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT = + public static final String EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT = "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT"; /** * AG call handling feature: merge two calls, held and active - multi party conference mode. */ - public final static String EXTRA_AG_FEATURE_MERGE = + public static final String EXTRA_AG_FEATURE_MERGE = "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_MERGE"; /** * AG call handling feature: merge calls and disconnect from multi party @@ -305,61 +304,61 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * Note that this feature needs to be supported by mobile network operator * as it requires connection and billing transfer. */ - public final static String EXTRA_AG_FEATURE_MERGE_AND_DETACH = + public static final String EXTRA_AG_FEATURE_MERGE_AND_DETACH = "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_MERGE_AND_DETACH"; /* Action result codes */ - public final static int ACTION_RESULT_OK = 0; - public final static int ACTION_RESULT_ERROR = 1; - public final static int ACTION_RESULT_ERROR_NO_CARRIER = 2; - public final static int ACTION_RESULT_ERROR_BUSY = 3; - public final static int ACTION_RESULT_ERROR_NO_ANSWER = 4; - public final static int ACTION_RESULT_ERROR_DELAYED = 5; - public final static int ACTION_RESULT_ERROR_BLACKLISTED = 6; - public final static int ACTION_RESULT_ERROR_CME = 7; + public static final int ACTION_RESULT_OK = 0; + public static final int ACTION_RESULT_ERROR = 1; + public static final int ACTION_RESULT_ERROR_NO_CARRIER = 2; + public static final int ACTION_RESULT_ERROR_BUSY = 3; + public static final int ACTION_RESULT_ERROR_NO_ANSWER = 4; + public static final int ACTION_RESULT_ERROR_DELAYED = 5; + public static final int ACTION_RESULT_ERROR_BLACKLISTED = 6; + public static final int ACTION_RESULT_ERROR_CME = 7; /* Detailed CME error codes */ - public final static int CME_PHONE_FAILURE = 0; - public final static int CME_NO_CONNECTION_TO_PHONE = 1; - public final static int CME_OPERATION_NOT_ALLOWED = 3; - public final static int CME_OPERATION_NOT_SUPPORTED = 4; - public final static int CME_PHSIM_PIN_REQUIRED = 5; - public final static int CME_PHFSIM_PIN_REQUIRED = 6; - public final static int CME_PHFSIM_PUK_REQUIRED = 7; - public final static int CME_SIM_NOT_INSERTED = 10; - public final static int CME_SIM_PIN_REQUIRED = 11; - public final static int CME_SIM_PUK_REQUIRED = 12; - public final static int CME_SIM_FAILURE = 13; - public final static int CME_SIM_BUSY = 14; - public final static int CME_SIM_WRONG = 15; - public final static int CME_INCORRECT_PASSWORD = 16; - public final static int CME_SIM_PIN2_REQUIRED = 17; - public final static int CME_SIM_PUK2_REQUIRED = 18; - public final static int CME_MEMORY_FULL = 20; - public final static int CME_INVALID_INDEX = 21; - public final static int CME_NOT_FOUND = 22; - public final static int CME_MEMORY_FAILURE = 23; - public final static int CME_TEXT_STRING_TOO_LONG = 24; - public final static int CME_INVALID_CHARACTER_IN_TEXT_STRING = 25; - public final static int CME_DIAL_STRING_TOO_LONG = 26; - public final static int CME_INVALID_CHARACTER_IN_DIAL_STRING = 27; - public final static int CME_NO_NETWORK_SERVICE = 30; - public final static int CME_NETWORK_TIMEOUT = 31; - public final static int CME_EMERGENCY_SERVICE_ONLY = 32; - public final static int CME_NO_SIMULTANOUS_VOIP_CS_CALLS = 33; - public final static int CME_NOT_SUPPORTED_FOR_VOIP = 34; - public final static int CME_SIP_RESPONSE_CODE = 35; - public final static int CME_NETWORK_PERSONALIZATION_PIN_REQUIRED = 40; - public final static int CME_NETWORK_PERSONALIZATION_PUK_REQUIRED = 41; - public final static int CME_NETWORK_SUBSET_PERSONALIZATION_PIN_REQUIRED = 42; - public final static int CME_NETWORK_SUBSET_PERSONALIZATION_PUK_REQUIRED = 43; - public final static int CME_SERVICE_PROVIDER_PERSONALIZATION_PIN_REQUIRED = 44; - public final static int CME_SERVICE_PROVIDER_PERSONALIZATION_PUK_REQUIRED = 45; - public final static int CME_CORPORATE_PERSONALIZATION_PIN_REQUIRED = 46; - public final static int CME_CORPORATE_PERSONALIZATION_PUK_REQUIRED = 47; - public final static int CME_HIDDEN_KEY_REQUIRED = 48; - public final static int CME_EAP_NOT_SUPPORTED = 49; - public final static int CME_INCORRECT_PARAMETERS = 50; + public static final int CME_PHONE_FAILURE = 0; + public static final int CME_NO_CONNECTION_TO_PHONE = 1; + public static final int CME_OPERATION_NOT_ALLOWED = 3; + public static final int CME_OPERATION_NOT_SUPPORTED = 4; + public static final int CME_PHSIM_PIN_REQUIRED = 5; + public static final int CME_PHFSIM_PIN_REQUIRED = 6; + public static final int CME_PHFSIM_PUK_REQUIRED = 7; + public static final int CME_SIM_NOT_INSERTED = 10; + public static final int CME_SIM_PIN_REQUIRED = 11; + public static final int CME_SIM_PUK_REQUIRED = 12; + public static final int CME_SIM_FAILURE = 13; + public static final int CME_SIM_BUSY = 14; + public static final int CME_SIM_WRONG = 15; + public static final int CME_INCORRECT_PASSWORD = 16; + public static final int CME_SIM_PIN2_REQUIRED = 17; + public static final int CME_SIM_PUK2_REQUIRED = 18; + public static final int CME_MEMORY_FULL = 20; + public static final int CME_INVALID_INDEX = 21; + public static final int CME_NOT_FOUND = 22; + public static final int CME_MEMORY_FAILURE = 23; + public static final int CME_TEXT_STRING_TOO_LONG = 24; + public static final int CME_INVALID_CHARACTER_IN_TEXT_STRING = 25; + public static final int CME_DIAL_STRING_TOO_LONG = 26; + public static final int CME_INVALID_CHARACTER_IN_DIAL_STRING = 27; + public static final int CME_NO_NETWORK_SERVICE = 30; + public static final int CME_NETWORK_TIMEOUT = 31; + public static final int CME_EMERGENCY_SERVICE_ONLY = 32; + public static final int CME_NO_SIMULTANOUS_VOIP_CS_CALLS = 33; + public static final int CME_NOT_SUPPORTED_FOR_VOIP = 34; + public static final int CME_SIP_RESPONSE_CODE = 35; + public static final int CME_NETWORK_PERSONALIZATION_PIN_REQUIRED = 40; + public static final int CME_NETWORK_PERSONALIZATION_PUK_REQUIRED = 41; + public static final int CME_NETWORK_SUBSET_PERSONALIZATION_PIN_REQUIRED = 42; + public static final int CME_NETWORK_SUBSET_PERSONALIZATION_PUK_REQUIRED = 43; + public static final int CME_SERVICE_PROVIDER_PERSONALIZATION_PIN_REQUIRED = 44; + public static final int CME_SERVICE_PROVIDER_PERSONALIZATION_PUK_REQUIRED = 45; + public static final int CME_CORPORATE_PERSONALIZATION_PIN_REQUIRED = 46; + public static final int CME_CORPORATE_PERSONALIZATION_PUK_REQUIRED = 47; + public static final int CME_HIDDEN_KEY_REQUIRED = 48; + public static final int CME_EAP_NOT_SUPPORTED = 49; + public static final int CME_INCORRECT_PARAMETERS = 50; /* Action policy for other calls when accepting call */ public static final int CALL_ACCEPT_NONE = 0; @@ -371,36 +370,37 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { private IBluetoothHeadsetClient mService; private BluetoothAdapter mAdapter; - final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { @Override public void onBluetoothStateChange(boolean up) { if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); if (!up) { - if (VDBG) Log.d(TAG,"Unbinding service..."); + if (VDBG) Log.d(TAG, "Unbinding service..."); synchronized (mConnection) { try { mService = null; mContext.unbindService(mConnection); } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } else { synchronized (mConnection) { try { if (mService == null) { - if (VDBG) Log.d(TAG,"Binding service..."); - Intent intent = new Intent(IBluetoothHeadsetClient.class.getName()); + if (VDBG) Log.d(TAG, "Binding service..."); + Intent intent = new Intent( + IBluetoothHeadsetClient.class.getName()); doBind(); } } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } } - }; + }; /** * Create a BluetoothHeadsetClient proxy object. @@ -415,7 +415,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { try { mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -427,7 +427,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, - android.os.Process.myUserHandle())) { + android.os.Process.myUserHandle())) { Log.e(TAG, "Could not bind to Bluetooth Headset Client Service with " + intent); return false; } @@ -448,7 +448,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { try { mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); } catch (Exception e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -458,7 +458,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { mService = null; mContext.unbindService(mConnection); } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } @@ -472,16 +472,13 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * second connection, this implementation will disconnect already connected * device automatically and will process the new one. * - * @param device a remote device we want connect to - * @return <code>true</code> if command has been issued successfully; - * <code>false</code> otherwise; - * upon completion HFP sends {@link #ACTION_CONNECTION_STATE_CHANGED} - * intent. + * @param device a remote device we want connect to + * @return <code>true</code> if command has been issued successfully; <code>false</code> + * otherwise; upon completion HFP sends {@link #ACTION_CONNECTION_STATE_CHANGED} intent. */ public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.connect(device); } catch (RemoteException e) { @@ -496,21 +493,18 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { /** * Disconnects remote device * - * @param device a remote device we want disconnect - * @return <code>true</code> if command has been issued successfully; - * <code>false</code> otherwise; - * upon completion HFP sends {@link #ACTION_CONNECTION_STATE_CHANGED} - * intent. + * @param device a remote device we want disconnect + * @return <code>true</code> if command has been issued successfully; <code>false</code> + * otherwise; upon completion HFP sends {@link #ACTION_CONNECTION_STATE_CHANGED} intent. */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.disconnect(device); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return false; } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -540,10 +534,9 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { /** * Returns list of remote devices in a particular state * - * @param states collection of states - * @return list of devices that state matches the states listed in - * <code>states</code>; empty list if nothing matches the - * <code>states</code> + * @param states collection of states + * @return list of devices that state matches the states listed in <code>states</code>; empty + * list if nothing matches the <code>states</code> */ @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { @@ -563,14 +556,13 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { /** * Returns state of the <code>device</code> * - * @param device a remote device - * @return the state of connection of the device + * @param device a remote device + * @return the state of connection of the device */ @Override public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getConnectionState(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.getConnectionState(device); } catch (RemoteException e) { @@ -589,11 +581,10 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { - if (priority != BluetoothProfile.PRIORITY_OFF && - priority != BluetoothProfile.PRIORITY_ON) { - return false; + if (mService != null && isEnabled() && isValidDevice(device)) { + if (priority != BluetoothProfile.PRIORITY_OFF + && priority != BluetoothProfile.PRIORITY_ON) { + return false; } try { return mService.setPriority(device, priority); @@ -611,8 +602,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.getPriority(device); } catch (RemoteException e) { @@ -627,24 +617,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { /** * Starts voice recognition. * - * @param device remote device - * @return <code>true</code> if command has been issued successfully; - * <code>false</code> otherwise; - * upon completion HFP sends {@link #ACTION_AG_EVENT} - * intent. + * @param device remote device + * @return <code>true</code> if command has been issued successfully; <code>false</code> + * otherwise; upon completion HFP sends {@link #ACTION_AG_EVENT} intent. * - * <p>Feature required for successful execution is being reported by: - * {@link #EXTRA_AG_FEATURE_VOICE_RECOGNITION}. - * This method invocation will fail silently when feature is not supported.</p> + * <p>Feature required for successful execution is being reported by: {@link + * #EXTRA_AG_FEATURE_VOICE_RECOGNITION}. This method invocation will fail silently when feature + * is not supported.</p> */ public boolean startVoiceRecognition(BluetoothDevice device) { if (DBG) log("startVoiceRecognition()"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.startVoiceRecognition(device); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -654,24 +641,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { /** * Stops voice recognition. * - * @param device remote device - * @return <code>true</code> if command has been issued successfully; - * <code>false</code> otherwise; - * upon completion HFP sends {@link #ACTION_AG_EVENT} - * intent. + * @param device remote device + * @return <code>true</code> if command has been issued successfully; <code>false</code> + * otherwise; upon completion HFP sends {@link #ACTION_AG_EVENT} intent. * - * <p>Feature required for successful execution is being reported by: - * {@link #EXTRA_AG_FEATURE_VOICE_RECOGNITION}. - * This method invocation will fail silently when feature is not supported.</p> + * <p>Feature required for successful execution is being reported by: {@link + * #EXTRA_AG_FEATURE_VOICE_RECOGNITION}. This method invocation will fail silently when feature + * is not supported.</p> */ public boolean stopVoiceRecognition(BluetoothDevice device) { if (DBG) log("stopVoiceRecognition()"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.stopVoiceRecognition(device); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -681,17 +665,16 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { /** * Returns list of all calls in any state. * - * @param device remote device - * @return list of calls; empty list if none call exists + * @param device remote device + * @return list of calls; empty list if none call exists */ public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) { if (DBG) log("getCurrentCalls()"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.getCurrentCalls(device); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -701,18 +684,16 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { /** * Returns list of current values of AG indicators. * - * @param device remote device - * @return bundle of AG indicators; null if device is not in - * CONNECTED state + * @param device remote device + * @return bundle of AG indicators; null if device is not in CONNECTED state */ public Bundle getCurrentAgEvents(BluetoothDevice device) { if (DBG) log("getCurrentCalls()"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.getCurrentAgEvents(device); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -722,23 +703,19 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { /** * Accepts a call * - * @param device remote device - * @param flag action policy while accepting a call. Possible values - * {@link #CALL_ACCEPT_NONE}, {@link #CALL_ACCEPT_HOLD}, - * {@link #CALL_ACCEPT_TERMINATE} - * @return <code>true</code> if command has been issued successfully; - * <code>false</code> otherwise; - * upon completion HFP sends {@link #ACTION_CALL_CHANGED} - * intent. + * @param device remote device + * @param flag action policy while accepting a call. Possible values {@link #CALL_ACCEPT_NONE}, + * {@link #CALL_ACCEPT_HOLD}, {@link #CALL_ACCEPT_TERMINATE} + * @return <code>true</code> if command has been issued successfully; <code>false</code> + * otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent. */ public boolean acceptCall(BluetoothDevice device, int flag) { if (DBG) log("acceptCall()"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.acceptCall(device, flag); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -748,20 +725,17 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { /** * Holds a call. * - * @param device remote device - * @return <code>true</code> if command has been issued successfully; - * <code>false</code> otherwise; - * upon completion HFP sends {@link #ACTION_CALL_CHANGED} - * intent. + * @param device remote device + * @return <code>true</code> if command has been issued successfully; <code>false</code> + * otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent. */ public boolean holdCall(BluetoothDevice device) { if (DBG) log("holdCall()"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.holdCall(device); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -771,24 +745,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { /** * Rejects a call. * - * @param device remote device - * @return <code>true</code> if command has been issued successfully; - * <code>false</code> otherwise; - * upon completion HFP sends {@link #ACTION_CALL_CHANGED} - * intent. + * @param device remote device + * @return <code>true</code> if command has been issued successfully; <code>false</code> + * otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent. * - * <p>Feature required for successful execution is being reported by: - * {@link #EXTRA_AG_FEATURE_REJECT_CALL}. - * This method invocation will fail silently when feature is not supported.</p> + * <p>Feature required for successful execution is being reported by: {@link + * #EXTRA_AG_FEATURE_REJECT_CALL}. This method invocation will fail silently when feature is not + * supported.</p> */ public boolean rejectCall(BluetoothDevice device) { if (DBG) log("rejectCall()"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.rejectCall(device); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -800,27 +771,24 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * * Works only when Extended Call Control is supported by Audio Gateway. * - * @param device remote device - * @param call Handle of call obtained in {@link dial()} or obtained via - * {@link ACTION_CALL_CHANGED}. {@code call} may be null in which - * case we will hangup all active calls. - * @return <code>true</code> if command has been issued successfully; - * <code>false</code> otherwise; - * upon completion HFP sends {@link #ACTION_CALL_CHANGED} - * intent. + * @param device remote device + * @param call Handle of call obtained in {@link #dial(BluetoothDevice, String)} or obtained via + * {@link #ACTION_CALL_CHANGED}. {@code call} may be null in which case we will hangup all active + * calls. + * @return <code>true</code> if command has been issued successfully; <code>false</code> + * otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent. * - * <p>Feature required for successful execution is being reported by: - * {@link #EXTRA_AG_FEATURE_ECC}. - * This method invocation will fail silently when feature is not supported.</p> + * <p>Feature required for successful execution is being reported by: {@link + * #EXTRA_AG_FEATURE_ECC}. This method invocation will fail silently when feature is not + * supported.</p> */ public boolean terminateCall(BluetoothDevice device, BluetoothHeadsetClientCall call) { if (DBG) log("terminateCall()"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.terminateCall(device, call); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -832,25 +800,22 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * * Works only when Extended Call Control is supported by Audio Gateway. * - * @param device remote device - * @param index index of the call to connect in private mode - * @return <code>true</code> if command has been issued successfully; - * <code>false</code> otherwise; - * upon completion HFP sends {@link #ACTION_CALL_CHANGED} - * intent. + * @param device remote device + * @param index index of the call to connect in private mode + * @return <code>true</code> if command has been issued successfully; <code>false</code> + * otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent. * - * <p>Feature required for successful execution is being reported by: - * {@link #EXTRA_AG_FEATURE_ECC}. - * This method invocation will fail silently when feature is not supported.</p> + * <p>Feature required for successful execution is being reported by: {@link + * #EXTRA_AG_FEATURE_ECC}. This method invocation will fail silently when feature is not + * supported.</p> */ public boolean enterPrivateMode(BluetoothDevice device, int index) { if (DBG) log("enterPrivateMode()"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.enterPrivateMode(device, index); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -862,24 +827,21 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * * That means connect other calls and disconnect. * - * @param device remote device - * @return <code>true</code> if command has been issued successfully; - * <code>false</code> otherwise; - * upon completion HFP sends {@link #ACTION_CALL_CHANGED} - * intent. + * @param device remote device + * @return <code>true</code> if command has been issued successfully; <code>false</code> + * otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent. * - * <p>Feature required for successful execution is being reported by: - * {@link #EXTRA_AG_FEATURE_MERGE_AND_DETACH}. - * This method invocation will fail silently when feature is not supported.</p> + * <p>Feature required for successful execution is being reported by: {@link + * #EXTRA_AG_FEATURE_MERGE_AND_DETACH}. This method invocation will fail silently when feature + * is not supported.</p> */ public boolean explicitCallTransfer(BluetoothDevice device) { if (DBG) log("explicitCallTransfer()"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.explicitCallTransfer(device); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -889,23 +851,19 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { /** * Places a call with specified number. * - * @param device remote device - * @param number valid phone number - * @return <code>{@link BluetoothHeadsetClientCall} call</code> if command has been - * issued successfully; - * <code>{@link null}</code> otherwise; - * upon completion HFP sends {@link #ACTION_CALL_CHANGED} - * intent in case of success; {@link #ACTION_RESULT} is sent - * otherwise; + * @param device remote device + * @param number valid phone number + * @return <code>{@link BluetoothHeadsetClientCall} call</code> if command has been issued + * successfully; <code>{@link null}</code> otherwise; upon completion HFP sends {@link + * #ACTION_CALL_CHANGED} intent in case of success; {@link #ACTION_RESULT} is sent otherwise; */ public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) { if (DBG) log("dial()"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.dial(device, number); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -917,20 +875,18 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * * Possible code values : 0,1,2,3,4,5,6,7,8,9,A,B,C,D,*,# * - * @param device remote device - * @param code ASCII code - * @return <code>true</code> if command has been issued successfully; - * <code>false</code> otherwise; - * upon completion HFP sends {@link #ACTION_RESULT} intent; + * @param device remote device + * @param code ASCII code + * @return <code>true</code> if command has been issued successfully; <code>false</code> + * otherwise; upon completion HFP sends {@link #ACTION_RESULT} intent; */ public boolean sendDTMF(BluetoothDevice device, byte code) { if (DBG) log("sendDTMF()"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.sendDTMF(device, code); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -940,24 +896,22 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { /** * Get a number corresponding to last voice tag recorded on AG. * - * @param device remote device - * @return <code>true</code> if command has been issued successfully; - * <code>false</code> otherwise; - * upon completion HFP sends {@link #ACTION_LAST_VTAG} - * or {@link #ACTION_RESULT} intent; + * @param device remote device + * @return <code>true</code> if command has been issued successfully; <code>false</code> + * otherwise; upon completion HFP sends {@link #ACTION_LAST_VTAG} or {@link #ACTION_RESULT} + * intent; * - * <p>Feature required for successful execution is being reported by: - * {@link #EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT}. - * This method invocation will fail silently when feature is not supported.</p> + * <p>Feature required for successful execution is being reported by: {@link + * #EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT}. This method invocation will fail silently when + * feature is not supported.</p> */ public boolean getLastVoiceTagNumber(BluetoothDevice device) { if (DBG) log("getLastVoiceTagNumber()"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.getLastVoiceTagNumber(device); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); + Log.e(TAG, Log.getStackTraceString(new Throwable())); } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -974,7 +928,9 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { if (mService != null && isEnabled()) { try { return mService.getAudioState(device); - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); @@ -985,16 +941,18 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { /** * Sets whether audio routing is allowed. * - * @param device remote device - * @param allowed if routing is allowed to the device - * Note: This is an internal function and shouldn't be exposed + * @param device remote device + * @param allowed if routing is allowed to the device Note: This is an internal function and + * shouldn't be exposed */ public void setAudioRouteAllowed(BluetoothDevice device, boolean allowed) { if (VDBG) log("setAudioRouteAllowed"); if (mService != null && isEnabled()) { try { mService.setAudioRouteAllowed(device, allowed); - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); @@ -1003,16 +961,19 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { /** * Returns whether audio routing is allowed. - * @param device remote device - * @return whether the command succeeded - * Note: This is an internal function and shouldn't be exposed + * + * @param device remote device + * @return whether the command succeeded Note: This is an internal function and shouldn't be + * exposed */ public boolean getAudioRouteAllowed(BluetoothDevice device) { if (VDBG) log("getAudioRouteAllowed"); if (mService != null && isEnabled()) { try { return mService.getAudioRouteAllowed(device); - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); @@ -1025,11 +986,9 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * * It setup SCO channel with remote connected Handsfree AG device. * - * @param device remote device - * @return <code>true</code> if command has been issued successfully; - * <code>false</code> otherwise; - * upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} - * intent; + * @param device remote device + * @return <code>true</code> if command has been issued successfully; <code>false</code> + * otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent; */ public boolean connectAudio(BluetoothDevice device) { if (mService != null && isEnabled()) { @@ -1050,11 +1009,9 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * * It tears down the SCO channel from remote AG device. * - * @param device remote device - * @return <code>true</code> if command has been issued successfully; - * <code>false</code> otherwise; - * upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} - * intent; + * @param device remote device + * @return <code>true</code> if command has been issued successfully; <code>false</code> + * otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent; */ public boolean disconnectAudio(BluetoothDevice device) { if (mService != null && isEnabled()) { @@ -1073,9 +1030,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { /** * Get Audio Gateway features * - * @param device remote device - * @return bundle of AG features; null if no service or - * AG not connected + * @param device remote device + * @return bundle of AG features; null if no service or AG not connected */ public Bundle getCurrentAgFeatures(BluetoothDevice device) { if (mService != null && isEnabled()) { @@ -1103,6 +1059,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { BluetoothHeadsetClient.this); } } + @Override public void onServiceDisconnected(ComponentName className) { if (DBG) Log.d(TAG, "Proxy object disconnected"); @@ -1114,15 +1071,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { }; private boolean isEnabled() { - if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; - return false; + if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; + return false; } private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; + if (device == null) return false; - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; + return false; } private static void log(String msg) { diff --git a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java index 420c079f5fea..dc00d63043fc 100644 --- a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java +++ b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java @@ -25,6 +25,7 @@ import java.util.UUID; /** * This class represents a single call, its state and properties. * It implements {@link Parcelable} for inter-process message passing. + * * @hide */ public final class BluetoothHeadsetClientCall implements Parcelable { @@ -98,7 +99,7 @@ public final class BluetoothHeadsetClientCall implements Parcelable { * * <p>Note: This is an internal function and shouldn't be exposed</p> * - * @param state new call state. + * @param state new call state. */ public void setState(int state) { mState = state; @@ -109,7 +110,7 @@ public final class BluetoothHeadsetClientCall implements Parcelable { * * <p>Note: This is an internal function and shouldn't be exposed</p> * - * @param number String representing phone number. + * @param number String representing phone number. */ public void setNumber(String number) { mNumber = number; @@ -120,8 +121,7 @@ public final class BluetoothHeadsetClientCall implements Parcelable { * * <p>Note: This is an internal function and shouldn't be exposed</p> * - * @param multiParty if <code>true</code> sets this call as a part - * of multi party conference. + * @param multiParty if <code>true</code> sets this call as a part of multi party conference. */ public void setMultiParty(boolean multiParty) { mMultiParty = multiParty; @@ -185,8 +185,7 @@ public final class BluetoothHeadsetClientCall implements Parcelable { /** * Checks if call is an active call in a conference mode (aka multi party). * - * @return <code>true</code> if call is a multi party call, - * <code>false</code> otherwise. + * @return <code>true</code> if call is a multi party call, <code>false</code> otherwise. */ public boolean isMultiParty() { return mMultiParty; @@ -195,17 +194,22 @@ public final class BluetoothHeadsetClientCall implements Parcelable { /** * Checks if this call is an outgoing call. * - * @return <code>true</code> if its outgoing call, - * <code>false</code> otherwise. + * @return <code>true</code> if its outgoing call, <code>false</code> otherwise. */ public boolean isOutgoing() { return mOutgoing; } + @Override public String toString() { return toString(false); } + /** + * Generate a log string for this call + * @param loggable whether device address should be logged + * @return log string + */ public String toString(boolean loggable) { StringBuilder builder = new StringBuilder("BluetoothHeadsetClientCall{mDevice: "); builder.append(loggable ? mDevice : mDevice.hashCode()); @@ -215,15 +219,33 @@ public final class BluetoothHeadsetClientCall implements Parcelable { builder.append(mUUID); builder.append(", mState: "); switch (mState) { - case CALL_STATE_ACTIVE: builder.append("ACTIVE"); break; - case CALL_STATE_HELD: builder.append("HELD"); break; - case CALL_STATE_DIALING: builder.append("DIALING"); break; - case CALL_STATE_ALERTING: builder.append("ALERTING"); break; - case CALL_STATE_INCOMING: builder.append("INCOMING"); break; - case CALL_STATE_WAITING: builder.append("WAITING"); break; - case CALL_STATE_HELD_BY_RESPONSE_AND_HOLD: builder.append("HELD_BY_RESPONSE_AND_HOLD"); break; - case CALL_STATE_TERMINATED: builder.append("TERMINATED"); break; - default: builder.append(mState); break; + case CALL_STATE_ACTIVE: + builder.append("ACTIVE"); + break; + case CALL_STATE_HELD: + builder.append("HELD"); + break; + case CALL_STATE_DIALING: + builder.append("DIALING"); + break; + case CALL_STATE_ALERTING: + builder.append("ALERTING"); + break; + case CALL_STATE_INCOMING: + builder.append("INCOMING"); + break; + case CALL_STATE_WAITING: + builder.append("WAITING"); + break; + case CALL_STATE_HELD_BY_RESPONSE_AND_HOLD: + builder.append("HELD_BY_RESPONSE_AND_HOLD"); + break; + case CALL_STATE_TERMINATED: + builder.append("TERMINATED"); + break; + default: + builder.append(mState); + break; } builder.append(", mNumber: "); builder.append(loggable ? mNumber : mNumber.hashCode()); @@ -242,7 +264,7 @@ public final class BluetoothHeadsetClientCall implements Parcelable { new Parcelable.Creator<BluetoothHeadsetClientCall>() { @Override public BluetoothHeadsetClientCall createFromParcel(Parcel in) { - return new BluetoothHeadsetClientCall((BluetoothDevice)in.readParcelable(null), + return new BluetoothHeadsetClientCall((BluetoothDevice) in.readParcelable(null), in.readInt(), UUID.fromString(in.readString()), in.readInt(), in.readString(), in.readInt() == 1, in.readInt() == 1); } diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java index 8d77888193b6..dc5f38135aaf 100644 --- a/core/java/android/bluetooth/BluetoothHealth.java +++ b/core/java/android/bluetooth/BluetoothHealth.java @@ -36,24 +36,23 @@ import java.util.List; * Service via IPC. * * <p> How to connect to a health device which is acting in the source role. - * <li> Use {@link BluetoothAdapter#getProfileProxy} to get - * the BluetoothHealth proxy object. </li> - * <li> Create an {@link BluetoothHealth} callback and call - * {@link #registerSinkAppConfiguration} to register an application - * configuration </li> - * <li> Pair with the remote device. This currently needs to be done manually - * from Bluetooth Settings </li> - * <li> Connect to a health device using {@link #connectChannelToSource}. Some - * devices will connect the channel automatically. The {@link BluetoothHealth} - * callback will inform the application of channel state change. </li> - * <li> Use the file descriptor provided with a connected channel to read and - * write data to the health channel. </li> - * <li> The received data needs to be interpreted using a health manager which - * implements the IEEE 11073-xxxxx specifications. - * <li> When done, close the health channel by calling {@link #disconnectChannel} - * and unregister the application configuration calling - * {@link #unregisterAppConfiguration} - * + * <li> Use {@link BluetoothAdapter#getProfileProxy} to get + * the BluetoothHealth proxy object. </li> + * <li> Create an {@link BluetoothHealth} callback and call + * {@link #registerSinkAppConfiguration} to register an application + * configuration </li> + * <li> Pair with the remote device. This currently needs to be done manually + * from Bluetooth Settings </li> + * <li> Connect to a health device using {@link #connectChannelToSource}. Some + * devices will connect the channel automatically. The {@link BluetoothHealth} + * callback will inform the application of channel state change. </li> + * <li> Use the file descriptor provided with a connected channel to read and + * write data to the health channel. </li> + * <li> The received data needs to be interpreted using a health manager which + * implements the IEEE 11073-xxxxx specifications. + * <li> When done, close the health channel by calling {@link #disconnectChannel} + * and unregister the application configuration calling + * {@link #unregisterAppConfiguration} */ public final class BluetoothHealth implements BluetoothProfile { private static final String TAG = "BluetoothHealth"; @@ -98,34 +97,34 @@ public final class BluetoothHealth implements BluetoothProfile { /** @hide */ public static final int HEALTH_OPERATION_NOT_ALLOWED = 6005; - final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { public void onBluetoothStateChange(boolean up) { if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); if (!up) { - if (VDBG) Log.d(TAG,"Unbinding service..."); + if (VDBG) Log.d(TAG, "Unbinding service..."); synchronized (mConnection) { try { mService = null; mContext.unbindService(mConnection); } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } else { synchronized (mConnection) { try { if (mService == null) { - if (VDBG) Log.d(TAG,"Binding service..."); + if (VDBG) Log.d(TAG, "Binding service..."); doBind(); } } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } } - }; + }; /** @@ -137,10 +136,10 @@ public final class BluetoothHealth implements BluetoothProfile { * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param name The friendly name associated with the application or configuration. - * @param dataType The dataType of the Source role of Health Profile to which - * the sink wants to connect to. - * @param callback A callback to indicate success or failure of the registration and - * all operations done on this application configuration. + * @param dataType The dataType of the Source role of Health Profile to which the sink wants to + * connect to. + * @param callback A callback to indicate success or failure of the registration and all + * operations done on this application configuration. * @return If true, callback will be called. */ public boolean registerSinkAppConfiguration(String name, int dataType, @@ -161,9 +160,8 @@ public final class BluetoothHealth implements BluetoothProfile { * * @param name The friendly name associated with the application or configuration. * @param dataType The dataType of the Source role of Health Profile. - * @param channelType The channel type. Will be one of - * {@link #CHANNEL_TYPE_RELIABLE} or - * {@link #CHANNEL_TYPE_STREAMING} + * @param channelType The channel type. Will be one of {@link #CHANNEL_TYPE_RELIABLE} or {@link + * #CHANNEL_TYPE_STREAMING} * @param callback - A callback to indicate success or failure. * @return If true, callback will be called. * @hide @@ -197,7 +195,7 @@ public final class BluetoothHealth implements BluetoothProfile { * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * - * @param config The health app configuration + * @param config The health app configuration * @return Success or failure. */ public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) { @@ -224,14 +222,13 @@ public final class BluetoothHealth implements BluetoothProfile { * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param device The remote Bluetooth device. - * @param config The application configuration which has been registered using - * {@link #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) } + * @param config The application configuration which has been registered using {@link + * #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) } * @return If true, the callback associated with the application config will be called. */ public boolean connectChannelToSource(BluetoothDevice device, BluetoothHealthAppConfiguration config) { - if (mService != null && isEnabled() && isValidDevice(device) && - config != null) { + if (mService != null && isEnabled() && isValidDevice(device) && config != null) { try { return mService.connectChannelToSource(device, config); } catch (RemoteException e) { @@ -249,18 +246,17 @@ public final class BluetoothHealth implements BluetoothProfile { * This is an asynchronous call. If this function returns true, the callback * associated with the application configuration will be called. * - *<p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param device The remote Bluetooth device. - * @param config The application configuration which has been registered using - * {@link #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) } + * @param config The application configuration which has been registered using {@link + * #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) } * @return If true, the callback associated with the application config will be called. * @hide */ public boolean connectChannelToSink(BluetoothDevice device, BluetoothHealthAppConfiguration config, int channelType) { - if (mService != null && isEnabled() && isValidDevice(device) && - config != null) { + if (mService != null && isEnabled() && isValidDevice(device) && config != null) { try { return mService.connectChannelToSink(device, config, channelType); } catch (RemoteException e) { @@ -278,18 +274,17 @@ public final class BluetoothHealth implements BluetoothProfile { * This is an asynchronous call. If this function returns true, the callback * associated with the application configuration will be called. * - *<p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. * * @param device The remote Bluetooth device. - * @param config The application configuration which has been registered using - * {@link #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) } + * @param config The application configuration which has been registered using {@link + * #registerSinkAppConfiguration(String, int, BluetoothHealthCallback) } * @param channelId The channel id associated with the channel * @return If true, the callback associated with the application config will be called. */ public boolean disconnectChannel(BluetoothDevice device, BluetoothHealthAppConfiguration config, int channelId) { - if (mService != null && isEnabled() && isValidDevice(device) && - config != null) { + if (mService != null && isEnabled() && isValidDevice(device) && config != null) { try { return mService.disconnectChannel(device, config, channelId); } catch (RemoteException e) { @@ -317,8 +312,7 @@ public final class BluetoothHealth implements BluetoothProfile { */ public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device, BluetoothHealthAppConfiguration config) { - if (mService != null && isEnabled() && isValidDevice(device) && - config != null) { + if (mService != null && isEnabled() && isValidDevice(device) && config != null) { try { return mService.getMainChannelFd(device, config); } catch (RemoteException e) { @@ -342,9 +336,8 @@ public final class BluetoothHealth implements BluetoothProfile { * local adapter. * * @param device Remote bluetooth device. - * @return State of the profile connection. One of - * {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING}, - * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING} + * @return State of the profile connection. One of {@link #STATE_CONNECTED}, {@link + * #STATE_CONNECTING}, {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING} */ @Override public int getConnectionState(BluetoothDevice device) { @@ -372,6 +365,7 @@ public final class BluetoothHealth implements BluetoothProfile { * state of the local Bluetooth adapter for this profile. This can be used * by applications like status bar which would just like to know the state of the * local adapter. + * * @return List of devices. The list will be empty on error. */ @Override @@ -401,9 +395,8 @@ public final class BluetoothHealth implements BluetoothProfile { * by applications like status bar which would just like to know the state of the * local adapter. * - * @param states Array of states. States can be one of - * {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING}, - * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}, + * @param states Array of states. States can be one of {@link #STATE_CONNECTED}, {@link + * #STATE_CONNECTING}, {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}, * @return List of devices. The list will be empty on error. */ @Override @@ -429,25 +422,25 @@ public final class BluetoothHealth implements BluetoothProfile { @Override public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration config, - int status) { - mCallback.onHealthAppConfigurationStatusChange(config, status); + int status) { + mCallback.onHealthAppConfigurationStatusChange(config, status); } @Override public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config, - BluetoothDevice device, int prevState, int newState, - ParcelFileDescriptor fd, int channelId) { + BluetoothDevice device, int prevState, int newState, + ParcelFileDescriptor fd, int channelId) { mCallback.onHealthChannelStateChange(config, device, prevState, newState, fd, - channelId); + channelId); } } - /** Health Channel Connection State - Disconnected */ - public static final int STATE_CHANNEL_DISCONNECTED = 0; + /** Health Channel Connection State - Disconnected */ + public static final int STATE_CHANNEL_DISCONNECTED = 0; /** Health Channel Connection State - Connecting */ - public static final int STATE_CHANNEL_CONNECTING = 1; + public static final int STATE_CHANNEL_CONNECTING = 1; /** Health Channel Connection State - Connected */ - public static final int STATE_CHANNEL_CONNECTED = 2; + public static final int STATE_CHANNEL_CONNECTED = 2; /** Health Channel Connection State - Disconnecting */ public static final int STATE_CHANNEL_DISCONNECTING = 3; @@ -477,7 +470,7 @@ public final class BluetoothHealth implements BluetoothProfile { try { mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -503,7 +496,7 @@ public final class BluetoothHealth implements BluetoothProfile { try { mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); } catch (Exception e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -513,7 +506,7 @@ public final class BluetoothHealth implements BluetoothProfile { mService = null; mContext.unbindService(mConnection); } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } @@ -529,6 +522,7 @@ public final class BluetoothHealth implements BluetoothProfile { mServiceListener.onServiceConnected(BluetoothProfile.HEALTH, BluetoothHealth.this); } } + public void onServiceDisconnected(ComponentName className) { if (DBG) Log.d(TAG, "Proxy object disconnected"); mService = null; @@ -555,10 +549,10 @@ public final class BluetoothHealth implements BluetoothProfile { private boolean checkAppParam(String name, int role, int channelType, BluetoothHealthCallback callback) { - if (name == null || (role != SOURCE_ROLE && role != SINK_ROLE) || - (channelType != CHANNEL_TYPE_RELIABLE && - channelType != CHANNEL_TYPE_STREAMING && - channelType != CHANNEL_TYPE_ANY) || callback == null) { + if (name == null || (role != SOURCE_ROLE && role != SINK_ROLE) + || (channelType != CHANNEL_TYPE_RELIABLE && channelType != CHANNEL_TYPE_STREAMING + && channelType != CHANNEL_TYPE_ANY) + || callback == null) { return false; } if (role == SOURCE_ROLE && channelType == CHANNEL_TYPE_ANY) return false; diff --git a/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java b/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java index 1717a1e36e1f..7c9db6f7213c 100644 --- a/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java +++ b/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java @@ -25,7 +25,6 @@ import android.os.Parcelable; * the {@link BluetoothHealth} class. This class represents an application configuration * that the Bluetooth Health third party application will register to communicate with the * remote Bluetooth health device. - * */ public final class BluetoothHealthAppConfiguration implements Parcelable { private final String mName; @@ -52,12 +51,11 @@ public final class BluetoothHealthAppConfiguration implements Parcelable { * * @param name Friendly name associated with the application configuration * @param dataType Data Type of the remote Bluetooth Health device - * @param role {@link BluetoothHealth#SOURCE_ROLE} or - * {@link BluetoothHealth#SINK_ROLE} + * @param role {@link BluetoothHealth#SOURCE_ROLE} or {@link BluetoothHealth#SINK_ROLE} * @hide */ BluetoothHealthAppConfiguration(String name, int dataType, int role, int - channelType) { + channelType) { mName = name; mDataType = dataType; mRole = role; @@ -71,10 +69,8 @@ public final class BluetoothHealthAppConfiguration implements Parcelable { if (mName == null) return false; - return mName.equals(config.getName()) && - mDataType == config.getDataType() && - mRole == config.getRole() && - mChannelType == config.getChannelType(); + return mName.equals(config.getName()) && mDataType == config.getDataType() + && mRole == config.getRole() && mChannelType == config.getChannelType(); } return false; } @@ -91,11 +87,11 @@ public final class BluetoothHealthAppConfiguration implements Parcelable { @Override public String toString() { - return "BluetoothHealthAppConfiguration [mName = " + mName + - ",mDataType = " + mDataType + ", mRole = " + mRole + ",mChannelType = " + - mChannelType + "]"; + return "BluetoothHealthAppConfiguration [mName = " + mName + ",mDataType = " + mDataType + + ", mRole = " + mRole + ",mChannelType = " + mChannelType + "]"; } + @Override public int describeContents() { return 0; } @@ -121,8 +117,7 @@ public final class BluetoothHealthAppConfiguration implements Parcelable { /** * Return the role associated with this application configuration. * - * @return One of {@link BluetoothHealth#SOURCE_ROLE} or - * {@link BluetoothHealth#SINK_ROLE} + * @return One of {@link BluetoothHealth#SOURCE_ROLE} or {@link BluetoothHealth#SINK_ROLE} */ public int getRole() { return mRole; @@ -131,9 +126,8 @@ public final class BluetoothHealthAppConfiguration implements Parcelable { /** * Return the channel type associated with this application configuration. * - * @return One of {@link BluetoothHealth#CHANNEL_TYPE_RELIABLE} or - * {@link BluetoothHealth#CHANNEL_TYPE_STREAMING} or - * {@link BluetoothHealth#CHANNEL_TYPE_ANY}. + * @return One of {@link BluetoothHealth#CHANNEL_TYPE_RELIABLE} or {@link + * BluetoothHealth#CHANNEL_TYPE_STREAMING} or {@link BluetoothHealth#CHANNEL_TYPE_ANY}. * @hide */ public int getChannelType() { @@ -141,23 +135,24 @@ public final class BluetoothHealthAppConfiguration implements Parcelable { } public static final Parcelable.Creator<BluetoothHealthAppConfiguration> CREATOR = - new Parcelable.Creator<BluetoothHealthAppConfiguration>() { - @Override - public BluetoothHealthAppConfiguration createFromParcel(Parcel in) { - String name = in.readString(); - int type = in.readInt(); - int role = in.readInt(); - int channelType = in.readInt(); - return new BluetoothHealthAppConfiguration(name, type, role, - channelType); - } - - @Override - public BluetoothHealthAppConfiguration[] newArray(int size) { - return new BluetoothHealthAppConfiguration[size]; - } - }; + new Parcelable.Creator<BluetoothHealthAppConfiguration>() { + @Override + public BluetoothHealthAppConfiguration createFromParcel(Parcel in) { + String name = in.readString(); + int type = in.readInt(); + int role = in.readInt(); + int channelType = in.readInt(); + return new BluetoothHealthAppConfiguration(name, type, role, + channelType); + } + + @Override + public BluetoothHealthAppConfiguration[] newArray(int size) { + return new BluetoothHealthAppConfiguration[size]; + } + }; + @Override public void writeToParcel(Parcel out, int flags) { out.writeString(mName); out.writeInt(mDataType); diff --git a/core/java/android/bluetooth/BluetoothHealthCallback.java b/core/java/android/bluetooth/BluetoothHealthCallback.java index 128376f24f3a..40234856b8ad 100644 --- a/core/java/android/bluetooth/BluetoothHealthCallback.java +++ b/core/java/android/bluetooth/BluetoothHealthCallback.java @@ -33,12 +33,11 @@ public abstract class BluetoothHealthCallback { * <p> This callback is called on the binder thread (not on the UI thread) * * @param config Bluetooth Health app configuration - * @param status Success or failure of the registration or unregistration - * calls. Can be one of - * {@link BluetoothHealth#APP_CONFIG_REGISTRATION_SUCCESS} or - * {@link BluetoothHealth#APP_CONFIG_REGISTRATION_FAILURE} or - * {@link BluetoothHealth#APP_CONFIG_UNREGISTRATION_SUCCESS} or - * {@link BluetoothHealth#APP_CONFIG_UNREGISTRATION_FAILURE} + * @param status Success or failure of the registration or unregistration calls. Can be one of + * {@link BluetoothHealth#APP_CONFIG_REGISTRATION_SUCCESS} or {@link + * BluetoothHealth#APP_CONFIG_REGISTRATION_FAILURE} or + * {@link BluetoothHealth#APP_CONFIG_UNREGISTRATION_SUCCESS} + * or {@link BluetoothHealth#APP_CONFIG_UNREGISTRATION_FAILURE} */ @BinderThread public void onHealthAppConfigurationStatusChange(BluetoothHealthAppConfiguration config, @@ -57,15 +56,15 @@ public abstract class BluetoothHealthCallback { * @param prevState The previous state of the channel * @param newState The new state of the channel. * @param fd The Parcel File Descriptor when the channel state is connected. - * @param channelId The id associated with the channel. This id will be used - * in future calls like when disconnecting the channel. + * @param channelId The id associated with the channel. This id will be used in future calls + * like when disconnecting the channel. */ @BinderThread public void onHealthChannelStateChange(BluetoothHealthAppConfiguration config, BluetoothDevice device, int prevState, int newState, ParcelFileDescriptor fd, int channelId) { - Log.d(TAG, "onHealthChannelStateChange: " + config + "Device: " + device + - "prevState:" + prevState + "newState:" + newState + "ParcelFd:" + fd + - "ChannelId:" + channelId); + Log.d(TAG, "onHealthChannelStateChange: " + config + "Device: " + device + + "prevState:" + prevState + "newState:" + newState + "ParcelFd:" + fd + + "ChannelId:" + channelId); } } diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.java b/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.java index 05ba64e981f1..2731935a4ea7 100644 --- a/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.java +++ b/core/java/android/bluetooth/BluetoothHidDeviceAppConfiguration.java @@ -49,19 +49,19 @@ public final class BluetoothHidDeviceAppConfiguration implements Parcelable { } public static final Parcelable.Creator<BluetoothHidDeviceAppConfiguration> CREATOR = - new Parcelable.Creator<BluetoothHidDeviceAppConfiguration>() { + new Parcelable.Creator<BluetoothHidDeviceAppConfiguration>() { - @Override - public BluetoothHidDeviceAppConfiguration createFromParcel(Parcel in) { - long hash = in.readLong(); - return new BluetoothHidDeviceAppConfiguration(hash); - } + @Override + public BluetoothHidDeviceAppConfiguration createFromParcel(Parcel in) { + long hash = in.readLong(); + return new BluetoothHidDeviceAppConfiguration(hash); + } - @Override - public BluetoothHidDeviceAppConfiguration[] newArray(int size) { - return new BluetoothHidDeviceAppConfiguration[size]; - } - }; + @Override + public BluetoothHidDeviceAppConfiguration[] newArray(int size) { + return new BluetoothHidDeviceAppConfiguration[size]; + } + }; @Override public void writeToParcel(Parcel out, int flags) { diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java index 0d6530c11a91..1f80ed78d75d 100644 --- a/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java +++ b/core/java/android/bluetooth/BluetoothHidDeviceAppQosSettings.java @@ -19,23 +19,21 @@ package android.bluetooth; import android.os.Parcel; import android.os.Parcelable; -import java.util.Random; - /** @hide */ public final class BluetoothHidDeviceAppQosSettings implements Parcelable { - final public int serviceType; - final public int tokenRate; - final public int tokenBucketSize; - final public int peakBandwidth; - final public int latency; - final public int delayVariation; + public final int serviceType; + public final int tokenRate; + public final int tokenBucketSize; + public final int peakBandwidth; + public final int latency; + public final int delayVariation; - final static public int SERVICE_NO_TRAFFIC = 0x00; - final static public int SERVICE_BEST_EFFORT = 0x01; - final static public int SERVICE_GUARANTEED = 0x02; + public static final int SERVICE_NO_TRAFFIC = 0x00; + public static final int SERVICE_BEST_EFFORT = 0x01; + public static final int SERVICE_GUARANTEED = 0x02; - final static public int MAX = (int) 0xffffffff; + public static final int MAX = (int) 0xffffffff; public BluetoothHidDeviceAppQosSettings(int serviceType, int tokenRate, int tokenBucketSize, int peakBandwidth, @@ -63,21 +61,22 @@ public final class BluetoothHidDeviceAppQosSettings implements Parcelable { } public static final Parcelable.Creator<BluetoothHidDeviceAppQosSettings> CREATOR = - new Parcelable.Creator<BluetoothHidDeviceAppQosSettings>() { + new Parcelable.Creator<BluetoothHidDeviceAppQosSettings>() { - @Override - public BluetoothHidDeviceAppQosSettings createFromParcel(Parcel in) { + @Override + public BluetoothHidDeviceAppQosSettings createFromParcel(Parcel in) { - return new BluetoothHidDeviceAppQosSettings(in.readInt(), in.readInt(), in.readInt(), - in.readInt(), - in.readInt(), in.readInt()); - } + return new BluetoothHidDeviceAppQosSettings(in.readInt(), in.readInt(), + in.readInt(), + in.readInt(), + in.readInt(), in.readInt()); + } - @Override - public BluetoothHidDeviceAppQosSettings[] newArray(int size) { - return new BluetoothHidDeviceAppQosSettings[size]; - } - }; + @Override + public BluetoothHidDeviceAppQosSettings[] newArray(int size) { + return new BluetoothHidDeviceAppQosSettings[size]; + } + }; @Override public void writeToParcel(Parcel out, int flags) { @@ -89,8 +88,9 @@ public final class BluetoothHidDeviceAppQosSettings implements Parcelable { out.writeInt(delayVariation); } + /** @return an int array representation of this instance */ public int[] toArray() { - return new int[] { + return new int[]{ serviceType, tokenRate, tokenBucketSize, peakBandwidth, latency, delayVariation }; } diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java index f9a224581953..d21d50611ab0 100644 --- a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java +++ b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java @@ -19,16 +19,14 @@ package android.bluetooth; import android.os.Parcel; import android.os.Parcelable; -import java.util.Random; - /** @hide */ public final class BluetoothHidDeviceAppSdpSettings implements Parcelable { - final public String name; - final public String description; - final public String provider; - final public byte subclass; - final public byte[] descriptors; + public final String name; + public final String description; + public final String provider; + public final byte subclass; + public final byte[] descriptors; public BluetoothHidDeviceAppSdpSettings(String name, String description, String provider, byte subclass, byte[] descriptors) { @@ -54,20 +52,20 @@ public final class BluetoothHidDeviceAppSdpSettings implements Parcelable { } public static final Parcelable.Creator<BluetoothHidDeviceAppSdpSettings> CREATOR = - new Parcelable.Creator<BluetoothHidDeviceAppSdpSettings>() { + new Parcelable.Creator<BluetoothHidDeviceAppSdpSettings>() { - @Override - public BluetoothHidDeviceAppSdpSettings createFromParcel(Parcel in) { + @Override + public BluetoothHidDeviceAppSdpSettings createFromParcel(Parcel in) { - return new BluetoothHidDeviceAppSdpSettings(in.readString(), in.readString(), - in.readString(), in.readByte(), in.createByteArray()); - } + return new BluetoothHidDeviceAppSdpSettings(in.readString(), in.readString(), + in.readString(), in.readByte(), in.createByteArray()); + } - @Override - public BluetoothHidDeviceAppSdpSettings[] newArray(int size) { - return new BluetoothHidDeviceAppSdpSettings[size]; - } - }; + @Override + public BluetoothHidDeviceAppSdpSettings[] newArray(int size) { + return new BluetoothHidDeviceAppSdpSettings[size]; + } + }; @Override public void writeToParcel(Parcel out, int flags) { diff --git a/core/java/android/bluetooth/BluetoothHidDeviceCallback.java b/core/java/android/bluetooth/BluetoothHidDeviceCallback.java index f519776276fc..3d407a6ca733 100644 --- a/core/java/android/bluetooth/BluetoothHidDeviceCallback.java +++ b/core/java/android/bluetooth/BluetoothHidDeviceCallback.java @@ -33,16 +33,14 @@ public abstract class BluetoothHidDeviceCallback { * , but can be also unsolicited in case e.g. Bluetooth was turned off in * which case application is unregistered automatically. * - * @param pluggedDevice {@link BluetoothDevice} object which represents host - * that currently has Virtual Cable established with device. Only - * valid when application is registered, can be <code>null</code> - * . - * @param config {@link BluetoothHidDeviceAppConfiguration} object which - * represents token required to unregister application using - * {@link BluetoothHidDevice#unregisterApp(BluetoothHidDeviceAppConfiguration)} - * . - * @param registered <code>true</code> if application is registered, - * <code>false</code> otherwise. + * @param pluggedDevice {@link BluetoothDevice} object which represents host that currently has + * Virtual Cable established with device. Only valid when application is registered, can be + * <code>null</code>. + * @param config {@link BluetoothHidDeviceAppConfiguration} object which represents token + * required to unregister application using + * {@link BluetoothHidDevice#unregisterApp(BluetoothHidDeviceAppConfiguration)}. + * @param registered <code>true</code> if application is registered, <code>false</code> + * otherwise. */ public void onAppStatusChanged(BluetoothDevice pluggedDevice, BluetoothHidDeviceAppConfiguration config, boolean registered) { @@ -55,8 +53,8 @@ public abstract class BluetoothHidDeviceCallback { * Application can assume than Virtual Cable is established when called with * {@link BluetoothProfile#STATE_CONNECTED} <code>state</code>. * - * @param device {@link BluetoothDevice} object representing host device - * which connection state was changed. + * @param device {@link BluetoothDevice} object representing host device which connection state + * was changed. * @param state Connection state as defined in {@link BluetoothProfile}. */ public void onConnectionStateChanged(BluetoothDevice device, int state) { @@ -69,10 +67,9 @@ public abstract class BluetoothHidDeviceCallback { * {@link BluetoothHidDevice#replyReport(BluetoothDevice, byte, byte, byte[])}. * * @param type Requested Report Type. - * @param id Requested Report Id, can be 0 if no Report Id are defined in - * descriptor. - * @param bufferSize Requested buffer size, application shall respond with - * at least given number of bytes. + * @param id Requested Report Id, can be 0 if no Report Id are defined in descriptor. + * @param bufferSize Requested buffer size, application shall respond with at least given number + * of bytes. */ public void onGetReport(BluetoothDevice device, byte type, byte id, int bufferSize) { Log.d(TAG, "onGetReport: device=" + device + " type=" + type + " id=" + id + " bufferSize=" diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java index a5a02435e37a..a9a9010c7edb 100644 --- a/core/java/android/bluetooth/BluetoothInputDevice.java +++ b/core/java/android/bluetooth/BluetoothInputDevice.java @@ -35,12 +35,13 @@ import java.util.List; * This class provides the public APIs to control the Bluetooth Input * Device Profile. * - *<p>BluetoothInputDevice is a proxy object for controlling the Bluetooth + * <p>BluetoothInputDevice is a proxy object for controlling the Bluetooth * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get * the BluetoothInputDevice proxy object. * - *<p>Each method is protected with its appropriate permission. - *@hide + * <p>Each method is protected with its appropriate permission. + * + * @hide */ public final class BluetoothInputDevice implements BluetoothProfile { private static final String TAG = "BluetoothInputDevice"; @@ -53,9 +54,9 @@ public final class BluetoothInputDevice implements BluetoothProfile { * * <p>This intent will have 3 extras: * <ul> - * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> - * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> * </ul> * * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of @@ -67,45 +68,46 @@ public final class BluetoothInputDevice implements BluetoothProfile { */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CONNECTION_STATE_CHANGED = - "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED"; + "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED"; /** * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PROTOCOL_MODE_CHANGED = - "android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED"; + "android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED"; /** * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_HANDSHAKE = - "android.bluetooth.input.profile.action.HANDSHAKE"; + "android.bluetooth.input.profile.action.HANDSHAKE"; /** * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_REPORT = - "android.bluetooth.input.profile.action.REPORT"; + "android.bluetooth.input.profile.action.REPORT"; /** * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_VIRTUAL_UNPLUG_STATUS = - "android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS"; + "android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS"; /** * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_IDLE_TIME_CHANGED = - "android.bluetooth.input.profile.action.IDLE_TIME_CHANGED"; + "android.bluetooth.input.profile.action.IDLE_TIME_CHANGED"; /** * Return codes for the connect and disconnect Bluez / Dbus calls. + * * @hide */ public static final int INPUT_DISCONNECT_FAILED_NOT_CONNECTED = 5000; @@ -174,22 +176,26 @@ public final class BluetoothInputDevice implements BluetoothProfile { /** * @hide */ - public static final String EXTRA_PROTOCOL_MODE = "android.bluetooth.BluetoothInputDevice.extra.PROTOCOL_MODE"; + public static final String EXTRA_PROTOCOL_MODE = + "android.bluetooth.BluetoothInputDevice.extra.PROTOCOL_MODE"; /** * @hide */ - public static final String EXTRA_REPORT_TYPE = "android.bluetooth.BluetoothInputDevice.extra.REPORT_TYPE"; + public static final String EXTRA_REPORT_TYPE = + "android.bluetooth.BluetoothInputDevice.extra.REPORT_TYPE"; /** * @hide */ - public static final String EXTRA_REPORT_ID = "android.bluetooth.BluetoothInputDevice.extra.REPORT_ID"; + public static final String EXTRA_REPORT_ID = + "android.bluetooth.BluetoothInputDevice.extra.REPORT_ID"; /** * @hide */ - public static final String EXTRA_REPORT_BUFFER_SIZE = "android.bluetooth.BluetoothInputDevice.extra.REPORT_BUFFER_SIZE"; + public static final String EXTRA_REPORT_BUFFER_SIZE = + "android.bluetooth.BluetoothInputDevice.extra.REPORT_BUFFER_SIZE"; /** * @hide @@ -204,51 +210,52 @@ public final class BluetoothInputDevice implements BluetoothProfile { /** * @hide */ - public static final String EXTRA_VIRTUAL_UNPLUG_STATUS = "android.bluetooth.BluetoothInputDevice.extra.VIRTUAL_UNPLUG_STATUS"; + public static final String EXTRA_VIRTUAL_UNPLUG_STATUS = + "android.bluetooth.BluetoothInputDevice.extra.VIRTUAL_UNPLUG_STATUS"; /** * @hide */ - public static final String EXTRA_IDLE_TIME = "android.bluetooth.BluetoothInputDevice.extra.IDLE_TIME"; + public static final String EXTRA_IDLE_TIME = + "android.bluetooth.BluetoothInputDevice.extra.IDLE_TIME"; private Context mContext; private ServiceListener mServiceListener; private BluetoothAdapter mAdapter; private IBluetoothInputDevice mService; - final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { public void onBluetoothStateChange(boolean up) { if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); if (!up) { - if (VDBG) Log.d(TAG,"Unbinding service..."); + if (VDBG) Log.d(TAG, "Unbinding service..."); synchronized (mConnection) { try { mService = null; mContext.unbindService(mConnection); } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } else { synchronized (mConnection) { try { if (mService == null) { - if (VDBG) Log.d(TAG,"Binding service..."); + if (VDBG) Log.d(TAG, "Binding service..."); doBind(); } } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } } - }; + }; /** * Create a BluetoothInputDevice proxy object for interacting with the local * Bluetooth Service which handles the InputDevice profile - * */ /*package*/ BluetoothInputDevice(Context context, ServiceListener l) { mContext = context; @@ -260,7 +267,7 @@ public final class BluetoothInputDevice implements BluetoothProfile { try { mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -286,7 +293,7 @@ public final class BluetoothInputDevice implements BluetoothProfile { try { mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); } catch (Exception e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -296,9 +303,9 @@ public final class BluetoothInputDevice implements BluetoothProfile { mService = null; mContext.unbindService(mConnection); } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } - } + } } mServiceListener = null; } @@ -319,8 +326,7 @@ public final class BluetoothInputDevice implements BluetoothProfile { * permission. * * @param device Remote Bluetooth Device - * @return false on immediate error, - * true otherwise + * @return false on immediate error, true otherwise * @hide */ public boolean connect(BluetoothDevice device) { @@ -359,8 +365,7 @@ public final class BluetoothInputDevice implements BluetoothProfile { * permission. * * @param device Remote Bluetooth Device - * @return false on immediate error, - * true otherwise + * @return false on immediate error, true otherwise * @hide */ public boolean disconnect(BluetoothDevice device) { @@ -380,6 +385,7 @@ public final class BluetoothInputDevice implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); if (mService != null && isEnabled()) { @@ -397,6 +403,7 @@ public final class BluetoothInputDevice implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); if (mService != null && isEnabled()) { @@ -414,6 +421,7 @@ public final class BluetoothInputDevice implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getState(" + device + ")"); if (mService != null && isEnabled() && isValidDevice(device)) { @@ -432,7 +440,7 @@ public final class BluetoothInputDevice implements BluetoothProfile { * Set priority of the profile * * <p> The device should already be paired. - * Priority can be one of {@link #PRIORITY_ON} or + * Priority can be one of {@link #PRIORITY_ON} or * {@link #PRIORITY_OFF}, * * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} @@ -446,9 +454,9 @@ public final class BluetoothInputDevice implements BluetoothProfile { public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); if (mService != null && isEnabled() && isValidDevice(device)) { - if (priority != BluetoothProfile.PRIORITY_OFF && - priority != BluetoothProfile.PRIORITY_ON) { - return false; + if (priority != BluetoothProfile.PRIORITY_OFF + && priority != BluetoothProfile.PRIORITY_ON) { + return false; } try { return mService.setPriority(device, priority); @@ -494,9 +502,11 @@ public final class BluetoothInputDevice implements BluetoothProfile { mService = IBluetoothInputDevice.Stub.asInterface(Binder.allowBlocking(service)); if (mServiceListener != null) { - mServiceListener.onServiceConnected(BluetoothProfile.INPUT_DEVICE, BluetoothInputDevice.this); + mServiceListener.onServiceConnected(BluetoothProfile.INPUT_DEVICE, + BluetoothInputDevice.this); } } + public void onServiceDisconnected(ComponentName className) { if (DBG) Log.d(TAG, "Proxy object disconnected"); mService = null; @@ -507,15 +517,15 @@ public final class BluetoothInputDevice implements BluetoothProfile { }; private boolean isEnabled() { - if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; - return false; + if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; + return false; } private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; + if (device == null) return false; - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; + return false; } @@ -525,8 +535,7 @@ public final class BluetoothInputDevice implements BluetoothProfile { * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. * * @param device Remote Bluetooth Device - * @return false on immediate error, - * true otherwise + * @return false on immediate error, true otherwise * @hide */ public boolean virtualUnplug(BluetoothDevice device) { @@ -546,15 +555,14 @@ public final class BluetoothInputDevice implements BluetoothProfile { } /** - * Send Get_Protocol_Mode command to the connected HID input device. - * - * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. - * - * @param device Remote Bluetooth Device - * @return false on immediate error, - *true otherwise - * @hide - */ + * Send Get_Protocol_Mode command to the connected HID input device. + * + * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. + * + * @param device Remote Bluetooth Device + * @return false on immediate error, true otherwise + * @hide + */ public boolean getProtocolMode(BluetoothDevice device) { if (VDBG) log("getProtocolMode(" + device + ")"); if (mService != null && isEnabled() && isValidDevice(device)) { @@ -566,7 +574,7 @@ public final class BluetoothInputDevice implements BluetoothProfile { } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return false; } /** @@ -575,8 +583,7 @@ public final class BluetoothInputDevice implements BluetoothProfile { * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. * * @param device Remote Bluetooth Device - * @return false on immediate error, - * true otherwise + * @return false on immediate error, true otherwise * @hide */ public boolean setProtocolMode(BluetoothDevice device, int protocolMode) { @@ -602,12 +609,16 @@ public final class BluetoothInputDevice implements BluetoothProfile { * @param reportType Report type * @param reportId Report ID * @param bufferSize Report receiving buffer size - * @return false on immediate error, - * true otherwise + * @return false on immediate error, true otherwise * @hide */ - public boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) { - if (VDBG) log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId + "bufferSize=" + bufferSize); + public boolean getReport(BluetoothDevice device, byte reportType, byte reportId, + int bufferSize) { + if (VDBG) { + log( + "getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId + + "bufferSize=" + bufferSize); + } if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.getReport(device, reportType, reportId, bufferSize); @@ -628,8 +639,7 @@ public final class BluetoothInputDevice implements BluetoothProfile { * @param device Remote Bluetooth Device * @param reportType Report type * @param report Report receiving buffer size - * @return false on immediate error, - * true otherwise + * @return false on immediate error, true otherwise * @hide */ public boolean setReport(BluetoothDevice device, byte reportType, String report) { @@ -653,8 +663,7 @@ public final class BluetoothInputDevice implements BluetoothProfile { * * @param device Remote Bluetooth Device * @param report Report to send - * @return false on immediate error, - * true otherwise + * @return false on immediate error, true otherwise * @hide */ public boolean sendData(BluetoothDevice device, String report) { @@ -677,8 +686,7 @@ public final class BluetoothInputDevice implements BluetoothProfile { * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. * * @param device Remote Bluetooth Device - * @return false on immediate error, - * true otherwise + * @return false on immediate error, true otherwise * @hide */ public boolean getIdleTime(BluetoothDevice device) { @@ -702,8 +710,7 @@ public final class BluetoothInputDevice implements BluetoothProfile { * * @param device Remote Bluetooth Device * @param idleTime Idle time to be set on HID Device - * @return false on immediate error, - * true otherwise + * @return false on immediate error, true otherwise * @hide */ public boolean setIdleTime(BluetoothDevice device, byte idleTime) { @@ -721,6 +728,6 @@ public final class BluetoothInputDevice implements BluetoothProfile { } private static void log(String msg) { - Log.d(TAG, msg); + Log.d(TAG, msg); } } diff --git a/core/java/android/bluetooth/BluetoothInputHost.java b/core/java/android/bluetooth/BluetoothInputHost.java index 68d105f1155d..15303dc79448 100644 --- a/core/java/android/bluetooth/BluetoothInputHost.java +++ b/core/java/android/bluetooth/BluetoothInputHost.java @@ -26,8 +26,8 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.Log; -import java.util.Arrays; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -43,9 +43,9 @@ public final class BluetoothInputHost implements BluetoothProfile { * * <p>This intent will have 3 extras: * <ul> - * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> - * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> * </ul> * * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of @@ -57,13 +57,12 @@ public final class BluetoothInputHost implements BluetoothProfile { */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CONNECTION_STATE_CHANGED = - "android.bluetooth.inputhost.profile.action.CONNECTION_STATE_CHANGED"; + "android.bluetooth.inputhost.profile.action.CONNECTION_STATE_CHANGED"; /** * Constants representing device subclass. * - * @see #registerApp(String, String, String, byte, byte[], - * BluetoothHidDeviceCallback) + * @see #registerApp(String, String, String, byte, byte[], BluetoothHidDeviceCallback) */ public static final byte SUBCLASS1_NONE = (byte) 0x00; public static final byte SUBCLASS1_KEYBOARD = (byte) 0x40; @@ -118,7 +117,8 @@ public final class BluetoothInputHost implements BluetoothProfile { private BluetoothAdapter mAdapter; - private static class BluetoothHidDeviceCallbackWrapper extends IBluetoothHidDeviceCallback.Stub { + private static class BluetoothHidDeviceCallbackWrapper extends + IBluetoothHidDeviceCallback.Stub { private BluetoothHidDeviceCallback mCallback; @@ -163,37 +163,44 @@ public final class BluetoothInputHost implements BluetoothProfile { } } - final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = - new IBluetoothStateChangeCallback.Stub() { - - public void onBluetoothStateChange(boolean up) { - Log.d(TAG, "onBluetoothStateChange: up=" + up); - synchronized (mConnection) { - if (!up) { - Log.d(TAG,"Unbinding service..."); - if (mService != null) { - mService = null; - try { - mContext.unbindService(mConnection); - } catch (IllegalArgumentException e) { - Log.e(TAG,"onBluetoothStateChange: could not unbind service:", e); + private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + new IBluetoothStateChangeCallback.Stub() { + + public void onBluetoothStateChange(boolean up) { + Log.d(TAG, "onBluetoothStateChange: up=" + up); + synchronized (mConnection) { + if (!up) { + Log.d(TAG, "Unbinding service..."); + if (mService != null) { + mService = null; + try { + mContext.unbindService(mConnection); + } catch (IllegalArgumentException e) { + Log.e(TAG, "onBluetoothStateChange: could not unbind service:", + e); + } + } + } else { + try { + if (mService == null) { + Log.d(TAG, "Binding HID Device service..."); + doBind(); + } + } catch (IllegalStateException e) { + Log.e(TAG, + "onBluetoothStateChange: could not bind to HID Dev " + + "service: ", + e); + } catch (SecurityException e) { + Log.e(TAG, + "onBluetoothStateChange: could not bind to HID Dev " + + "service: ", + e); + } } } - } else { - try { - if (mService == null) { - Log.d(TAG,"Binding HID Device service..."); - doBind(); - } - } catch (IllegalStateException e) { - Log.e(TAG,"onBluetoothStateChange: could not bind to HID Dev service: ", e); - } catch (SecurityException e) { - Log.e(TAG,"onBluetoothStateChange: could not bind to HID Dev service: ", e); - } } - } - } - }; + }; private ServiceConnection mConnection = new ServiceConnection() { @@ -204,7 +211,7 @@ public final class BluetoothInputHost implements BluetoothProfile { if (mServiceListener != null) { mServiceListener.onServiceConnected(BluetoothProfile.INPUT_HOST, - BluetoothInputHost.this); + BluetoothInputHost.this); } } @@ -269,9 +276,9 @@ public final class BluetoothInputHost implements BluetoothProfile { try { mContext.unbindService(mConnection); } catch (IllegalArgumentException e) { - Log.e(TAG,"close: could not unbind HID Dev service: ", e); + Log.e(TAG, "close: could not unbind HID Dev service: ", e); } - } + } } mServiceListener = null; @@ -280,6 +287,7 @@ public final class BluetoothInputHost implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public List<BluetoothDevice> getConnectedDevices() { Log.v(TAG, "getConnectedDevices()"); @@ -299,6 +307,7 @@ public final class BluetoothInputHost implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { Log.v(TAG, "getDevicesMatchingConnectionStates(): states=" + Arrays.toString(states)); @@ -318,6 +327,7 @@ public final class BluetoothInputHost implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public int getConnectionState(BluetoothDevice device) { Log.v(TAG, "getConnectionState(): device=" + device); @@ -341,14 +351,11 @@ public final class BluetoothInputHost implements BluetoothProfile { * should be unregistered using * {@link #unregisterApp(BluetoothHidDeviceAppConfiguration)}. * - * @param sdp {@link BluetoothHidDeviceAppSdpSettings} object of - * HID Device SDP record. - * @param inQos {@link BluetoothHidDeviceAppQosSettings} object of - * Incoming QoS Settings. - * @param outQos {@link BluetoothHidDeviceAppQosSettings} object of - * Outgoing QoS Settings. - * @param callback {@link BluetoothHidDeviceCallback} object to which - * callback messages will be sent. + * @param sdp {@link BluetoothHidDeviceAppSdpSettings} object of HID Device SDP record. + * @param inQos {@link BluetoothHidDeviceAppQosSettings} object of Incoming QoS Settings. + * @param outQos {@link BluetoothHidDeviceAppQosSettings} object of Outgoing QoS Settings. + * @param callback {@link BluetoothHidDeviceCallback} object to which callback messages will be + * sent. * @return */ public boolean registerApp(BluetoothHidDeviceAppSdpSettings sdp, @@ -366,9 +373,9 @@ public final class BluetoothInputHost implements BluetoothProfile { if (mService != null) { try { BluetoothHidDeviceAppConfiguration config = - new BluetoothHidDeviceAppConfiguration(); + new BluetoothHidDeviceAppConfiguration(); BluetoothHidDeviceCallbackWrapper cbw = - new BluetoothHidDeviceCallbackWrapper(callback); + new BluetoothHidDeviceCallbackWrapper(callback); result = mService.registerApp(config, sdp, inQos, outQos, cbw); } catch (RemoteException e) { Log.e(TAG, e.toString()); @@ -385,11 +392,10 @@ public final class BluetoothInputHost implements BluetoothProfile { * new connections will be allowed until registered again using * {@link #registerApp(String, String, String, byte, byte[], BluetoothHidDeviceCallback)} * - * @param config {@link BluetoothHidDeviceAppConfiguration} object as - * obtained from - * {@link BluetoothHidDeviceCallback#onAppStatusChanged(BluetoothDevice, - * BluetoothHidDeviceAppConfiguration, boolean)} - * + * @param config {@link BluetoothHidDeviceAppConfiguration} object as obtained from {@link + * BluetoothHidDeviceCallback#onAppStatusChanged(BluetoothDevice, + * BluetoothHidDeviceAppConfiguration, + * boolean)} * @return */ public boolean unregisterApp(BluetoothHidDeviceAppConfiguration config) { @@ -413,8 +419,8 @@ public final class BluetoothInputHost implements BluetoothProfile { /** * Sends report to remote host using interrupt channel. * - * @param id Report Id, as defined in descriptor. Can be 0 in case Report Id - * are not defined in descriptor. + * @param id Report Id, as defined in descriptor. Can be 0 in case Report Id are not defined in + * descriptor. * @param data Report data, not including Report Id. * @return */ diff --git a/core/java/android/bluetooth/BluetoothInputStream.java b/core/java/android/bluetooth/BluetoothInputStream.java index 03af95337c50..8eb79b248d64 100644 --- a/core/java/android/bluetooth/BluetoothInputStream.java +++ b/core/java/android/bluetooth/BluetoothInputStream.java @@ -51,15 +51,14 @@ import java.io.InputStream; * stream is detected or an exception is thrown. * * @return the byte read or -1 if the end of stream has been reached. - * @throws IOException - * if the stream is closed or another IOException occurs. + * @throws IOException if the stream is closed or another IOException occurs. * @since Android 1.5 */ public int read() throws IOException { - byte b[] = new byte[1]; + byte[] b = new byte[1]; int ret = mSocket.read(b, 0, 1); if (ret == 1) { - return (int)b[0] & 0xff; + return (int) b[0] & 0xff; } else { return -1; } @@ -69,21 +68,14 @@ import java.io.InputStream; * Reads at most {@code length} bytes from this stream and stores them in * the byte array {@code b} starting at {@code offset}. * - * @param b - * the byte array in which to store the bytes read. - * @param offset - * the initial position in {@code buffer} to store the bytes - * read from this stream. - * @param length - * the maximum number of bytes to store in {@code b}. - * @return the number of bytes actually read or -1 if the end of the stream - * has been reached. - * @throws IndexOutOfBoundsException - * if {@code offset < 0} or {@code length < 0}, or if - * {@code offset + length} is greater than the length of - * {@code b}. - * @throws IOException - * if the stream is closed or another IOException occurs. + * @param b the byte array in which to store the bytes read. + * @param offset the initial position in {@code buffer} to store the bytes read from this + * stream. + * @param length the maximum number of bytes to store in {@code b}. + * @return the number of bytes actually read or -1 if the end of the stream has been reached. + * @throws IndexOutOfBoundsException if {@code offset < 0} or {@code length < 0}, or if {@code + * offset + length} is greater than the length of {@code b}. + * @throws IOException if the stream is closed or another IOException occurs. * @since Android 1.5 */ public int read(byte[] b, int offset, int length) throws IOException { diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java index bacce800620b..7e3bb05fe024 100644 --- a/core/java/android/bluetooth/BluetoothManager.java +++ b/core/java/android/bluetooth/BluetoothManager.java @@ -86,17 +86,16 @@ public final class BluetoothManager { * * @param device Remote bluetooth device. * @param profile GATT or GATT_SERVER - * @return State of the profile connection. One of - * {@link BluetoothProfile#STATE_CONNECTED}, {@link BluetoothProfile#STATE_CONNECTING}, - * {@link BluetoothProfile#STATE_DISCONNECTED}, - * {@link BluetoothProfile#STATE_DISCONNECTING} + * @return State of the profile connection. One of {@link BluetoothProfile#STATE_CONNECTED}, + * {@link BluetoothProfile#STATE_CONNECTING}, {@link BluetoothProfile#STATE_DISCONNECTED}, + * {@link BluetoothProfile#STATE_DISCONNECTING} */ @RequiresPermission(Manifest.permission.BLUETOOTH) public int getConnectionState(BluetoothDevice device, int profile) { - if (DBG) Log.d(TAG,"getConnectionState()"); + if (DBG) Log.d(TAG, "getConnectionState()"); List<BluetoothDevice> connectedDevices = getConnectedDevices(profile); - for(BluetoothDevice connectedDevice : connectedDevices) { + for (BluetoothDevice connectedDevice : connectedDevices) { if (device.equals(connectedDevice)) { return BluetoothProfile.STATE_CONNECTED; } @@ -120,7 +119,7 @@ public final class BluetoothManager { */ @RequiresPermission(Manifest.permission.BLUETOOTH) public List<BluetoothDevice> getConnectedDevices(int profile) { - if (DBG) Log.d(TAG,"getConnectedDevices"); + if (DBG) Log.d(TAG, "getConnectedDevices"); if (profile != BluetoothProfile.GATT && profile != BluetoothProfile.GATT_SERVER) { throw new IllegalArgumentException("Profile not supported: " + profile); } @@ -133,16 +132,15 @@ public final class BluetoothManager { if (iGatt == null) return connectedDevices; connectedDevices = iGatt.getDevicesMatchingConnectionStates( - new int[] { BluetoothProfile.STATE_CONNECTED }); + new int[]{BluetoothProfile.STATE_CONNECTED}); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } return connectedDevices; } /** - * * Get a list of devices that match any of the given connection * states. * @@ -155,15 +153,14 @@ public final class BluetoothManager { * to know the state of the local adapter. * * @param profile GATT or GATT_SERVER - * @param states Array of states. States can be one of - * {@link BluetoothProfile#STATE_CONNECTED}, {@link BluetoothProfile#STATE_CONNECTING}, - * {@link BluetoothProfile#STATE_DISCONNECTED}, - * {@link BluetoothProfile#STATE_DISCONNECTING}, + * @param states Array of states. States can be one of {@link BluetoothProfile#STATE_CONNECTED}, + * {@link BluetoothProfile#STATE_CONNECTING}, {@link BluetoothProfile#STATE_DISCONNECTED}, + * {@link BluetoothProfile#STATE_DISCONNECTING}, * @return List of devices. The list will be empty on error. */ @RequiresPermission(Manifest.permission.BLUETOOTH) public List<BluetoothDevice> getDevicesMatchingConnectionStates(int profile, int[] states) { - if (DBG) Log.d(TAG,"getDevicesMatchingConnectionStates"); + if (DBG) Log.d(TAG, "getDevicesMatchingConnectionStates"); if (profile != BluetoothProfile.GATT && profile != BluetoothProfile.GATT_SERVER) { throw new IllegalArgumentException("Profile not supported: " + profile); @@ -177,7 +174,7 @@ public final class BluetoothManager { if (iGatt == null) return devices; devices = iGatt.getDevicesMatchingConnectionStates(states); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } return devices; @@ -189,14 +186,15 @@ public final class BluetoothManager { * as the results of any other GATT server operations. * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer * to conduct GATT server operations. + * * @param context App context * @param callback GATT server callback handler that will receive asynchronous callbacks. * @return BluetoothGattServer instance */ public BluetoothGattServer openGattServer(Context context, - BluetoothGattServerCallback callback) { + BluetoothGattServerCallback callback) { - return (openGattServer (context, callback, BluetoothDevice.TRANSPORT_AUTO)); + return (openGattServer(context, callback, BluetoothDevice.TRANSPORT_AUTO)); } /** @@ -205,16 +203,17 @@ public final class BluetoothManager { * as the results of any other GATT server operations. * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer * to conduct GATT server operations. + * * @param context App context * @param callback GATT server callback handler that will receive asynchronous callbacks. - * @param transport preferred transport for GATT connections to remote dual-mode devices - * {@link BluetoothDevice#TRANSPORT_AUTO} or - * {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE} + * @param transport preferred transport for GATT connections to remote dual-mode devices {@link + * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link + * BluetoothDevice#TRANSPORT_LE} * @return BluetoothGattServer instance * @hide */ public BluetoothGattServer openGattServer(Context context, - BluetoothGattServerCallback callback,int transport) { + BluetoothGattServerCallback callback, int transport) { if (context == null || callback == null) { throw new IllegalArgumentException("null parameter: " + context + " " + callback); } @@ -229,11 +228,11 @@ public final class BluetoothManager { Log.e(TAG, "Fail to get GATT Server connection"); return null; } - BluetoothGattServer mGattServer = new BluetoothGattServer(iGatt,transport); + BluetoothGattServer mGattServer = new BluetoothGattServer(iGatt, transport); Boolean regStatus = mGattServer.registerCallback(callback); - return regStatus? mGattServer : null; + return regStatus ? mGattServer : null; } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); return null; } } diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java index 2e73051ee610..26a9106f49f5 100644 --- a/core/java/android/bluetooth/BluetoothMap.java +++ b/core/java/android/bluetooth/BluetoothMap.java @@ -16,19 +16,23 @@ package android.bluetooth; -import java.util.List; -import java.util.ArrayList; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.os.*; +import android.os.Binder; +import android.os.IBinder; +import android.os.RemoteException; import android.util.Log; +import java.util.ArrayList; +import java.util.List; + /** * This class provides the APIs to control the Bluetooth MAP * Profile. - *@hide + * + * @hide */ public final class BluetoothMap implements BluetoothProfile { @@ -37,7 +41,7 @@ public final class BluetoothMap implements BluetoothProfile { private static final boolean VDBG = false; public static final String ACTION_CONNECTION_STATE_CHANGED = - "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED"; + "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED"; private IBluetoothMap mService; private final Context mContext; @@ -45,41 +49,41 @@ public final class BluetoothMap implements BluetoothProfile { private BluetoothAdapter mAdapter; /** There was an error trying to obtain the state */ - public static final int STATE_ERROR = -1; + public static final int STATE_ERROR = -1; public static final int RESULT_FAILURE = 0; public static final int RESULT_SUCCESS = 1; /** Connection canceled before completion. */ public static final int RESULT_CANCELED = 2; - final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { public void onBluetoothStateChange(boolean up) { if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); if (!up) { - if (VDBG) Log.d(TAG,"Unbinding service..."); + if (VDBG) Log.d(TAG, "Unbinding service..."); synchronized (mConnection) { try { mService = null; mContext.unbindService(mConnection); } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } else { synchronized (mConnection) { try { if (mService == null) { - if (VDBG) Log.d(TAG,"Binding service..."); + if (VDBG) Log.d(TAG, "Binding service..."); doBind(); } } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } } - }; + }; /** * Create a BluetoothMap proxy object. @@ -94,7 +98,7 @@ public final class BluetoothMap implements BluetoothProfile { try { mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } doBind(); @@ -132,7 +136,7 @@ public final class BluetoothMap implements BluetoothProfile { try { mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); } catch (Exception e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -142,7 +146,7 @@ public final class BluetoothMap implements BluetoothProfile { mService = null; mContext.unbindService(mConnection); } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } @@ -151,15 +155,18 @@ public final class BluetoothMap implements BluetoothProfile { /** * Get the current state of the BluetoothMap service. - * @return One of the STATE_ return codes, or STATE_ERROR if this proxy - * object is currently not connected to the Map service. + * + * @return One of the STATE_ return codes, or STATE_ERROR if this proxy object is currently not + * connected to the Map service. */ public int getState() { if (VDBG) log("getState()"); if (mService != null) { try { return mService.getState(); - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); @@ -169,16 +176,18 @@ public final class BluetoothMap implements BluetoothProfile { /** * Get the currently connected remote Bluetooth device (PCE). - * @return The remote Bluetooth device, or null if not in connected or - * connecting state, or if this proxy object is not connected to - * the Map service. + * + * @return The remote Bluetooth device, or null if not in connected or connecting state, or if + * this proxy object is not connected to the Map service. */ public BluetoothDevice getClient() { if (VDBG) log("getClient()"); if (mService != null) { try { return mService.getClient(); - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); @@ -196,7 +205,9 @@ public final class BluetoothMap implements BluetoothProfile { if (mService != null) { try { return mService.isConnected(device); - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); @@ -217,18 +228,16 @@ public final class BluetoothMap implements BluetoothProfile { * Initiate disconnect. * * @param device Remote Bluetooth Device - * @return false on error, - * true otherwise + * @return false on error, true otherwise */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.disconnect(device); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return false; } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -240,18 +249,19 @@ public final class BluetoothMap implements BluetoothProfile { * This is a simple heuristic that tries to guess if a device with the * given class bits might support Map. It is not accurate for all * devices. It tries to err on the side of false positives. + * * @return True if this device might support Map. */ public static boolean doesClassMatchSink(BluetoothClass btClass) { // TODO optimize the rule switch (btClass.getDeviceClass()) { - case BluetoothClass.Device.COMPUTER_DESKTOP: - case BluetoothClass.Device.COMPUTER_LAPTOP: - case BluetoothClass.Device.COMPUTER_SERVER: - case BluetoothClass.Device.COMPUTER_UNCATEGORIZED: - return true; - default: - return false; + case BluetoothClass.Device.COMPUTER_DESKTOP: + case BluetoothClass.Device.COMPUTER_LAPTOP: + case BluetoothClass.Device.COMPUTER_SERVER: + case BluetoothClass.Device.COMPUTER_UNCATEGORIZED: + return true; + default: + return false; } } @@ -300,8 +310,7 @@ public final class BluetoothMap implements BluetoothProfile { */ public int getConnectionState(BluetoothDevice device) { if (DBG) log("getConnectionState(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.getConnectionState(device); } catch (RemoteException e) { @@ -317,7 +326,7 @@ public final class BluetoothMap implements BluetoothProfile { * Set priority of the profile * * <p> The device should already be paired. - * Priority can be one of {@link #PRIORITY_ON} or + * Priority can be one of {@link #PRIORITY_ON} or * {@link #PRIORITY_OFF}, * * @param device Paired bluetooth device @@ -326,11 +335,10 @@ public final class BluetoothMap implements BluetoothProfile { */ public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { - if (priority != BluetoothProfile.PRIORITY_OFF && - priority != BluetoothProfile.PRIORITY_ON) { - return false; + if (mService != null && isEnabled() && isValidDevice(device)) { + if (priority != BluetoothProfile.PRIORITY_OFF + && priority != BluetoothProfile.PRIORITY_ON) { + return false; } try { return mService.setPriority(device, priority); @@ -355,8 +363,7 @@ public final class BluetoothMap implements BluetoothProfile { */ public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.getPriority(device); } catch (RemoteException e) { @@ -376,6 +383,7 @@ public final class BluetoothMap implements BluetoothProfile { mServiceListener.onServiceConnected(BluetoothProfile.MAP, BluetoothMap.this); } } + public void onServiceDisconnected(ComponentName className) { if (DBG) log("Proxy object disconnected"); mService = null; @@ -389,17 +397,18 @@ public final class BluetoothMap implements BluetoothProfile { Log.d(TAG, msg); } - private boolean isEnabled() { + private boolean isEnabled() { BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) return true; log("Bluetooth is Not enabled"); return false; } + private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; + if (device == null) return false; - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; + return false; } diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java index ccab3cdf0b6f..3e0c36548c41 100644 --- a/core/java/android/bluetooth/BluetoothMapClient.java +++ b/core/java/android/bluetooth/BluetoothMapClient.java @@ -72,7 +72,7 @@ public final class BluetoothMapClient implements BluetoothProfile { /** Connection canceled before completion. */ public static final int RESULT_CANCELED = 2; - final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { public void onBluetoothStateChange(boolean up) { if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); @@ -216,8 +216,7 @@ public final class BluetoothMapClient implements BluetoothProfile { */ public boolean disconnect(BluetoothDevice device) { if (DBG) Log.d(TAG, "disconnect(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.disconnect(device); } catch (RemoteException e) { @@ -276,8 +275,7 @@ public final class BluetoothMapClient implements BluetoothProfile { @Override public int getConnectionState(BluetoothDevice device) { if (DBG) Log.d(TAG, "getConnectionState(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.getConnectionState(device); } catch (RemoteException e) { @@ -300,10 +298,9 @@ public final class BluetoothMapClient implements BluetoothProfile { */ public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) Log.d(TAG, "setPriority(" + device + ", " + priority + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { - if (priority != BluetoothProfile.PRIORITY_OFF && - priority != BluetoothProfile.PRIORITY_ON) { + if (mService != null && isEnabled() && isValidDevice(device)) { + if (priority != BluetoothProfile.PRIORITY_OFF + && priority != BluetoothProfile.PRIORITY_ON) { return false; } try { @@ -329,8 +326,7 @@ public final class BluetoothMapClient implements BluetoothProfile { */ public int getPriority(BluetoothDevice device) { if (VDBG) Log.d(TAG, "getPriority(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.getPriority(device); } catch (RemoteException e) { @@ -347,10 +343,10 @@ public final class BluetoothMapClient implements BluetoothProfile { * * Send an SMS message to either the contacts primary number or the telephone number specified. * - * @param device Bluetooth device - * @param contacts Uri[] of the contacts - * @param message Message to be sent - * @param sentIntent intent issued when message is sent + * @param device Bluetooth device + * @param contacts Uri[] of the contacts + * @param message Message to be sent + * @param sentIntent intent issued when message is sent * @param deliveredIntent intent issued when message is delivered * @return true if the message is enqueued, false on error */ @@ -393,7 +389,7 @@ public final class BluetoothMapClient implements BluetoothProfile { mService = IBluetoothMapClient.Stub.asInterface(service); if (mServiceListener != null) { mServiceListener.onServiceConnected(BluetoothProfile.MAP_CLIENT, - BluetoothMapClient.this); + BluetoothMapClient.this); } } diff --git a/core/java/android/bluetooth/BluetoothMasInstance.java b/core/java/android/bluetooth/BluetoothMasInstance.java index 4459e2c44bdc..7a31328eaf02 100644 --- a/core/java/android/bluetooth/BluetoothMasInstance.java +++ b/core/java/android/bluetooth/BluetoothMasInstance.java @@ -36,7 +36,7 @@ public final class BluetoothMasInstance implements Parcelable { @Override public boolean equals(Object o) { if (o instanceof BluetoothMasInstance) { - return mId == ((BluetoothMasInstance)o).mId; + return mId == ((BluetoothMasInstance) o).mId; } return false; } @@ -48,25 +48,28 @@ public final class BluetoothMasInstance implements Parcelable { @Override public String toString() { - return Integer.toString(mId) + ":" + mName + ":" + mChannel + ":" + - Integer.toHexString(mMsgTypes); + return Integer.toString(mId) + ":" + mName + ":" + mChannel + ":" + + Integer.toHexString(mMsgTypes); } + @Override public int describeContents() { return 0; } public static final Parcelable.Creator<BluetoothMasInstance> CREATOR = new Parcelable.Creator<BluetoothMasInstance>() { - public BluetoothMasInstance createFromParcel(Parcel in) { - return new BluetoothMasInstance(in.readInt(), in.readString(), - in.readInt(), in.readInt()); - } - public BluetoothMasInstance[] newArray(int size) { - return new BluetoothMasInstance[size]; - } - }; + public BluetoothMasInstance createFromParcel(Parcel in) { + return new BluetoothMasInstance(in.readInt(), in.readString(), + in.readInt(), in.readInt()); + } + public BluetoothMasInstance[] newArray(int size) { + return new BluetoothMasInstance[size]; + } + }; + + @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(mId); out.writeString(mName); @@ -75,10 +78,10 @@ public final class BluetoothMasInstance implements Parcelable { } public static final class MessageType { - public static final int EMAIL = 0x01; - public static final int SMS_GSM = 0x02; + public static final int EMAIL = 0x01; + public static final int SMS_GSM = 0x02; public static final int SMS_CDMA = 0x04; - public static final int MMS = 0x08; + public static final int MMS = 0x08; } public int getId() { diff --git a/core/java/android/bluetooth/BluetoothOutputStream.java b/core/java/android/bluetooth/BluetoothOutputStream.java index 117dd47c1ab1..dfec4e102fd4 100644 --- a/core/java/android/bluetooth/BluetoothOutputStream.java +++ b/core/java/android/bluetooth/BluetoothOutputStream.java @@ -44,15 +44,13 @@ import java.io.OutputStream; * Writes a single byte to this stream. Only the least significant byte of * the integer {@code oneByte} is written to the stream. * - * @param oneByte - * the byte to be written. - * @throws IOException - * if an error occurs while writing to this stream. + * @param oneByte the byte to be written. + * @throws IOException if an error occurs while writing to this stream. * @since Android 1.0 */ public void write(int oneByte) throws IOException { - byte b[] = new byte[1]; - b[0] = (byte)oneByte; + byte[] b = new byte[1]; + b[0] = (byte) oneByte; mSocket.write(b, 0, 1); } @@ -60,19 +58,12 @@ import java.io.OutputStream; * Writes {@code count} bytes from the byte array {@code buffer} starting * at position {@code offset} to this stream. * - * @param b - * the buffer to be written. - * @param offset - * the start position in {@code buffer} from where to get bytes. - * @param count - * the number of bytes from {@code buffer} to write to this - * stream. - * @throws IOException - * if an error occurs while writing to this stream. - * @throws IndexOutOfBoundsException - * if {@code offset < 0} or {@code count < 0}, or if - * {@code offset + count} is bigger than the length of - * {@code buffer}. + * @param b the buffer to be written. + * @param offset the start position in {@code buffer} from where to get bytes. + * @param count the number of bytes from {@code buffer} to write to this stream. + * @throws IOException if an error occurs while writing to this stream. + * @throws IndexOutOfBoundsException if {@code offset < 0} or {@code count < 0}, or if {@code + * offset + count} is bigger than the length of {@code buffer}. * @since Android 1.0 */ public void write(byte[] b, int offset, int count) throws IOException { @@ -84,15 +75,16 @@ import java.io.OutputStream; } mSocket.write(b, offset, count); } + /** * Wait until the data in sending queue is emptied. A polling version * for flush implementation. Use it to ensure the writing data afterwards will * be packed in the new RFCOMM frame. - * @throws IOException - * if an i/o error occurs. + * + * @throws IOException if an i/o error occurs. * @since Android 4.2.3 */ - public void flush() throws IOException { + public void flush() throws IOException { mSocket.flush(); } } diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java index 2a026a91e8e6..63e83d22178d 100644 --- a/core/java/android/bluetooth/BluetoothPan.java +++ b/core/java/android/bluetooth/BluetoothPan.java @@ -34,12 +34,13 @@ import java.util.List; * This class provides the APIs to control the Bluetooth Pan * Profile. * - *<p>BluetoothPan is a proxy object for controlling the Bluetooth + * <p>BluetoothPan is a proxy object for controlling the Bluetooth * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get * the BluetoothPan proxy object. * - *<p>Each method is protected with its appropriate permission. - *@hide + * <p>Each method is protected with its appropriate permission. + * + * @hide */ public final class BluetoothPan implements BluetoothProfile { private static final String TAG = "BluetoothPan"; @@ -52,11 +53,11 @@ public final class BluetoothPan implements BluetoothProfile { * * <p>This intent will have 4 extras: * <ul> - * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> - * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> - * <li> {@link #EXTRA_LOCAL_ROLE} - Which local role the remote device is - * bound to. </li> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * <li> {@link #EXTRA_LOCAL_ROLE} - Which local role the remote device is + * bound to. </li> * </ul> * * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of @@ -70,7 +71,7 @@ public final class BluetoothPan implements BluetoothProfile { */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CONNECTION_STATE_CHANGED = - "android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED"; + "android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED"; /** * Extra for {@link #ACTION_CONNECTION_STATE_CHANGED} intent @@ -94,6 +95,7 @@ public final class BluetoothPan implements BluetoothProfile { /** * Return codes for the connect and disconnect Bluez / Dbus calls. + * * @hide */ public static final int PAN_DISCONNECT_FAILED_NOT_CONNECTED = 1000; @@ -126,7 +128,6 @@ public final class BluetoothPan implements BluetoothProfile { /** * Create a BluetoothPan proxy object for interacting with the local * Bluetooth Service which handles the Pan profile - * */ /*package*/ BluetoothPan(Context context, ServiceListener l) { mContext = context; @@ -135,7 +136,7 @@ public final class BluetoothPan implements BluetoothProfile { try { mAdapter.getBluetoothManager().registerStateChangeCallback(mStateChangeCallback); } catch (RemoteException re) { - Log.w(TAG,"Unable to register BluetoothStateChangeCallback",re); + Log.w(TAG, "Unable to register BluetoothStateChangeCallback", re); } if (VDBG) Log.d(TAG, "BluetoothPan() call bindService"); doBind(); @@ -161,7 +162,7 @@ public final class BluetoothPan implements BluetoothProfile { try { mgr.unregisterStateChangeCallback(mStateChangeCallback); } catch (RemoteException re) { - Log.w(TAG,"Unable to unregister BluetoothStateChangeCallback",re); + Log.w(TAG, "Unable to unregister BluetoothStateChangeCallback", re); } } @@ -171,7 +172,7 @@ public final class BluetoothPan implements BluetoothProfile { mPanService = null; mContext.unbindService(mConnection); } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } @@ -182,38 +183,41 @@ public final class BluetoothPan implements BluetoothProfile { close(); } - final private IBluetoothStateChangeCallback mStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { - - @Override - public void onBluetoothStateChange(boolean on) { - // Handle enable request to bind again. - Log.d(TAG, "onBluetoothStateChange on: " + on); - if (on) { - try { - if (mPanService == null) { - if (VDBG) Log.d(TAG, "onBluetoothStateChange calling doBind()"); - doBind(); + private final IBluetoothStateChangeCallback mStateChangeCallback = + new IBluetoothStateChangeCallback.Stub() { + + @Override + public void onBluetoothStateChange(boolean on) { + // Handle enable request to bind again. + Log.d(TAG, "onBluetoothStateChange on: " + on); + if (on) { + try { + if (mPanService == null) { + if (VDBG) Log.d(TAG, "onBluetoothStateChange calling doBind()"); + doBind(); + } + + } catch (IllegalStateException e) { + Log.e(TAG, "onBluetoothStateChange: could not bind to PAN service: ", + e); + + } catch (SecurityException e) { + Log.e(TAG, "onBluetoothStateChange: could not bind to PAN service: ", + e); + } + } else { + if (VDBG) Log.d(TAG, "Unbinding service..."); + synchronized (mConnection) { + try { + mPanService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG, "", re); + } + } } - - } catch (IllegalStateException e) { - Log.e(TAG,"onBluetoothStateChange: could not bind to PAN service: ", e); - - } catch (SecurityException e) { - Log.e(TAG,"onBluetoothStateChange: could not bind to PAN service: ", e); } - } else { - if (VDBG) Log.d(TAG,"Unbinding service..."); - synchronized (mConnection) { - try { - mPanService = null; - mContext.unbindService(mConnection); - } catch (Exception re) { - Log.e(TAG,"",re); - } - } - } - } - }; + }; /** * Initiate connection to a profile of the remote bluetooth device. @@ -229,14 +233,12 @@ public final class BluetoothPan implements BluetoothProfile { * permission. * * @param device Remote Bluetooth Device - * @return false on immediate error, - * true otherwise + * @return false on immediate error, true otherwise * @hide */ public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); - if (mPanService != null && isEnabled() && - isValidDevice(device)) { + if (mPanService != null && isEnabled() && isValidDevice(device)) { try { return mPanService.connect(device); } catch (RemoteException e) { @@ -270,14 +272,12 @@ public final class BluetoothPan implements BluetoothProfile { * permission. * * @param device Remote Bluetooth Device - * @return false on immediate error, - * true otherwise + * @return false on immediate error, true otherwise * @hide */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - if (mPanService != null && isEnabled() && - isValidDevice(device)) { + if (mPanService != null && isEnabled() && isValidDevice(device)) { try { return mPanService.disconnect(device); } catch (RemoteException e) { @@ -292,6 +292,7 @@ public final class BluetoothPan implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); if (mPanService != null && isEnabled()) { @@ -309,6 +310,7 @@ public final class BluetoothPan implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); if (mPanService != null && isEnabled()) { @@ -326,10 +328,11 @@ public final class BluetoothPan implements BluetoothProfile { /** * {@inheritDoc} */ + @Override public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getState(" + device + ")"); if (mPanService != null && isEnabled() - && isValidDevice(device)) { + && isValidDevice(device)) { try { return mPanService.getConnectionState(device); } catch (RemoteException e) { @@ -373,9 +376,10 @@ public final class BluetoothPan implements BluetoothProfile { if (mServiceListener != null) { mServiceListener.onServiceConnected(BluetoothProfile.PAN, - BluetoothPan.this); + BluetoothPan.this); } } + public void onServiceDisconnected(ComponentName className) { if (DBG) Log.d(TAG, "BluetoothPAN Proxy object disconnected"); mPanService = null; @@ -386,18 +390,18 @@ public final class BluetoothPan implements BluetoothProfile { }; private boolean isEnabled() { - if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; - return false; + if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; + return false; } private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; + if (device == null) return false; - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; + return false; } private static void log(String msg) { - Log.d(TAG, msg); + Log.d(TAG, msg); } } diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java index dc01fc7a9496..78b7c7b7a70b 100644 --- a/core/java/android/bluetooth/BluetoothPbap.java +++ b/core/java/android/bluetooth/BluetoothPbap.java @@ -20,8 +20,8 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.os.RemoteException; import android.os.IBinder; +import android.os.RemoteException; import android.util.Log; /** @@ -55,17 +55,18 @@ public class BluetoothPbap { /** int extra for PBAP_STATE_CHANGED_ACTION */ public static final String PBAP_STATE = - "android.bluetooth.pbap.intent.PBAP_STATE"; + "android.bluetooth.pbap.intent.PBAP_STATE"; /** int extra for PBAP_STATE_CHANGED_ACTION */ public static final String PBAP_PREVIOUS_STATE = - "android.bluetooth.pbap.intent.PBAP_PREVIOUS_STATE"; + "android.bluetooth.pbap.intent.PBAP_PREVIOUS_STATE"; - /** Indicates the state of a pbap connection state has changed. - * This intent will always contain PBAP_STATE, PBAP_PREVIOUS_STATE and - * BluetoothIntent.ADDRESS extras. + /** + * Indicates the state of a pbap connection state has changed. + * This intent will always contain PBAP_STATE, PBAP_PREVIOUS_STATE and + * BluetoothIntent.ADDRESS extras. */ public static final String PBAP_STATE_CHANGED_ACTION = - "android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED"; + "android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED"; private IBluetoothPbap mService; private final Context mContext; @@ -73,13 +74,13 @@ public class BluetoothPbap { private BluetoothAdapter mAdapter; /** There was an error trying to obtain the state */ - public static final int STATE_ERROR = -1; + public static final int STATE_ERROR = -1; /** No client currently connected */ public static final int STATE_DISCONNECTED = 0; /** Connection attempt in progress */ - public static final int STATE_CONNECTING = 1; + public static final int STATE_CONNECTING = 1; /** Client is currently connected */ - public static final int STATE_CONNECTED = 2; + public static final int STATE_CONNECTED = 2; public static final int RESULT_FAILURE = 0; public static final int RESULT_SUCCESS = 1; @@ -109,34 +110,34 @@ public class BluetoothPbap { public void onServiceDisconnected(); } - final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { public void onBluetoothStateChange(boolean up) { if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); if (!up) { - if (VDBG) Log.d(TAG,"Unbinding service..."); + if (VDBG) Log.d(TAG, "Unbinding service..."); synchronized (mConnection) { try { mService = null; mContext.unbindService(mConnection); } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } else { synchronized (mConnection) { try { if (mService == null) { - if (VDBG) Log.d(TAG,"Binding service..."); + if (VDBG) Log.d(TAG, "Binding service..."); doBind(); } } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } } - }; + }; /** * Create a BluetoothPbap proxy object. @@ -150,7 +151,7 @@ public class BluetoothPbap { try { mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } doBind(); @@ -188,7 +189,7 @@ public class BluetoothPbap { try { mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); } catch (Exception e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -198,7 +199,7 @@ public class BluetoothPbap { mService = null; mContext.unbindService(mConnection); } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } @@ -207,15 +208,18 @@ public class BluetoothPbap { /** * Get the current state of the BluetoothPbap service. - * @return One of the STATE_ return codes, or STATE_ERROR if this proxy - * object is currently not connected to the Pbap service. + * + * @return One of the STATE_ return codes, or STATE_ERROR if this proxy object is currently not + * connected to the Pbap service. */ public int getState() { if (VDBG) log("getState()"); if (mService != null) { try { return mService.getState(); - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); @@ -225,16 +229,18 @@ public class BluetoothPbap { /** * Get the currently connected remote Bluetooth device (PCE). - * @return The remote Bluetooth device, or null if not in connected or - * connecting state, or if this proxy object is not connected to - * the Pbap service. + * + * @return The remote Bluetooth device, or null if not in connected or connecting state, or if + * this proxy object is not connected to the Pbap service. */ public BluetoothDevice getClient() { if (VDBG) log("getClient()"); if (mService != null) { try { return mService.getClient(); - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); @@ -252,7 +258,9 @@ public class BluetoothPbap { if (mService != null) { try { return mService.isConnected(device); - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); @@ -271,7 +279,9 @@ public class BluetoothPbap { try { mService.disconnect(); return true; - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); @@ -284,18 +294,19 @@ public class BluetoothPbap { * This is a simple heuristic that tries to guess if a device with the * given class bits might support PBAP. It is not accurate for all * devices. It tries to err on the side of false positives. + * * @return True if this device might support PBAP. */ public static boolean doesClassMatchSink(BluetoothClass btClass) { // TODO optimize the rule switch (btClass.getDeviceClass()) { - case BluetoothClass.Device.COMPUTER_DESKTOP: - case BluetoothClass.Device.COMPUTER_LAPTOP: - case BluetoothClass.Device.COMPUTER_SERVER: - case BluetoothClass.Device.COMPUTER_UNCATEGORIZED: - return true; - default: - return false; + case BluetoothClass.Device.COMPUTER_DESKTOP: + case BluetoothClass.Device.COMPUTER_LAPTOP: + case BluetoothClass.Device.COMPUTER_SERVER: + case BluetoothClass.Device.COMPUTER_UNCATEGORIZED: + return true; + default: + return false; } } @@ -307,6 +318,7 @@ public class BluetoothPbap { mServiceListener.onServiceConnected(BluetoothPbap.this); } } + public void onServiceDisconnected(ComponentName className) { if (DBG) log("Proxy object disconnected"); mService = null; diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java index 9f00e1aaa3a1..b9b372c84843 100644 --- a/core/java/android/bluetooth/BluetoothPbapClient.java +++ b/core/java/android/bluetooth/BluetoothPbapClient.java @@ -16,20 +16,22 @@ package android.bluetooth; -import java.util.List; -import java.util.ArrayList; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.os.RemoteException; import android.os.Binder; import android.os.IBinder; +import android.os.RemoteException; import android.util.Log; +import java.util.ArrayList; +import java.util.List; + /** * This class provides the APIs to control the Bluetooth PBAP Client Profile. - *@hide + * + * @hide */ public final class BluetoothPbapClient implements BluetoothProfile { @@ -38,7 +40,7 @@ public final class BluetoothPbapClient implements BluetoothProfile { private static final boolean VDBG = false; public static final String ACTION_CONNECTION_STATE_CHANGED = - "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED"; + "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED"; private IBluetoothPbapClient mService; private final Context mContext; @@ -46,14 +48,14 @@ public final class BluetoothPbapClient implements BluetoothProfile { private BluetoothAdapter mAdapter; /** There was an error trying to obtain the state */ - public static final int STATE_ERROR = -1; + public static final int STATE_ERROR = -1; public static final int RESULT_FAILURE = 0; public static final int RESULT_SUCCESS = 1; /** Connection canceled before completion. */ public static final int RESULT_CANCELED = 2; - final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { public void onBluetoothStateChange(boolean up) { if (DBG) { @@ -61,14 +63,14 @@ public final class BluetoothPbapClient implements BluetoothProfile { } if (!up) { if (VDBG) { - Log.d(TAG,"Unbinding service..."); + Log.d(TAG, "Unbinding service..."); } synchronized (mConnection) { try { mService = null; mContext.unbindService(mConnection); } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } else { @@ -76,17 +78,17 @@ public final class BluetoothPbapClient implements BluetoothProfile { try { if (mService == null) { if (VDBG) { - Log.d(TAG,"Binding service..."); + Log.d(TAG, "Binding service..."); } doBind(); } } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } } - }; + }; /** * Create a BluetoothPbapClient proxy object. @@ -103,7 +105,7 @@ public final class BluetoothPbapClient implements BluetoothProfile { try { mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } doBind(); @@ -141,7 +143,7 @@ public final class BluetoothPbapClient implements BluetoothProfile { try { mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); } catch (Exception e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -151,7 +153,7 @@ public final class BluetoothPbapClient implements BluetoothProfile { mService = null; mContext.unbindService(mConnection); } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } @@ -163,9 +165,9 @@ public final class BluetoothPbapClient implements BluetoothProfile { * Upon successful connection to remote PBAP server the Client will * attempt to automatically download the users phonebook and call log. * - * @param device a remote device we want connect to - * @return <code>true</code> if command has been issued successfully; - * <code>false</code> otherwise; + * @param device a remote device we want connect to + * @return <code>true</code> if command has been issued successfully; <code>false</code> + * otherwise; */ public boolean connect(BluetoothDevice device) { if (DBG) { @@ -189,20 +191,19 @@ public final class BluetoothPbapClient implements BluetoothProfile { * Initiate disconnect. * * @param device Remote Bluetooth Device - * @return false on error, - * true otherwise + * @return false on error, true otherwise */ public boolean disconnect(BluetoothDevice device) { if (DBG) { - log("disconnect(" + device + ")" + new Exception() ); + log("disconnect(" + device + ")" + new Exception()); } if (mService != null && isEnabled() && isValidDevice(device)) { try { mService.disconnect(device); return true; } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return false; } } if (mService == null) { @@ -291,9 +292,11 @@ public final class BluetoothPbapClient implements BluetoothProfile { } mService = IBluetoothPbapClient.Stub.asInterface(Binder.allowBlocking(service)); if (mServiceListener != null) { - mServiceListener.onServiceConnected(BluetoothProfile.PBAP_CLIENT, BluetoothPbapClient.this); + mServiceListener.onServiceConnected(BluetoothProfile.PBAP_CLIENT, + BluetoothPbapClient.this); } } + public void onServiceDisconnected(ComponentName className) { if (DBG) { log("Proxy object disconnected"); @@ -319,20 +322,20 @@ public final class BluetoothPbapClient implements BluetoothProfile { } private boolean isValidDevice(BluetoothDevice device) { - if (device == null) { - return false; - } - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { - return true; - } - return false; + if (device == null) { + return false; + } + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { + return true; + } + return false; } /** * Set priority of the profile * * <p> The device should already be paired. - * Priority can be one of {@link #PRIORITY_ON} or + * Priority can be one of {@link #PRIORITY_ON} or * {@link #PRIORITY_OFF}, * * @param device Paired bluetooth device @@ -343,11 +346,10 @@ public final class BluetoothPbapClient implements BluetoothProfile { if (DBG) { log("setPriority(" + device + ", " + priority + ")"); } - if (mService != null && isEnabled() && - isValidDevice(device)) { - if (priority != BluetoothProfile.PRIORITY_OFF && - priority != BluetoothProfile.PRIORITY_ON) { - return false; + if (mService != null && isEnabled() && isValidDevice(device)) { + if (priority != BluetoothProfile.PRIORITY_OFF + && priority != BluetoothProfile.PRIORITY_ON) { + return false; } try { return mService.setPriority(device, priority); diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java index c5b58e97e528..bc8fa846087d 100644 --- a/core/java/android/bluetooth/BluetoothProfile.java +++ b/core/java/android/bluetooth/BluetoothProfile.java @@ -46,14 +46,14 @@ public interface BluetoothProfile { * Bluetooth device. */ public static final String EXTRA_PREVIOUS_STATE = - "android.bluetooth.profile.extra.PREVIOUS_STATE"; + "android.bluetooth.profile.extra.PREVIOUS_STATE"; /** The profile is in disconnected state */ - public static final int STATE_DISCONNECTED = 0; + public static final int STATE_DISCONNECTED = 0; /** The profile is in connecting state */ - public static final int STATE_CONNECTING = 1; + public static final int STATE_CONNECTING = 1; /** The profile is in connected state */ - public static final int STATE_CONNECTED = 2; + public static final int STATE_CONNECTED = 2; /** The profile is in disconnecting state */ public static final int STATE_DISCONNECTING = 3; @@ -74,18 +74,21 @@ public interface BluetoothProfile { /** * Input Device Profile + * * @hide */ public static final int INPUT_DEVICE = 4; /** * PAN Profile + * * @hide */ public static final int PAN = 5; /** * PBAP + * * @hide */ public static final int PBAP = 6; @@ -93,15 +96,16 @@ public interface BluetoothProfile { /** * GATT */ - static public final int GATT = 7; + public static final int GATT = 7; /** * GATT_SERVER */ - static public final int GATT_SERVER = 8; + public static final int GATT_SERVER = 8; /** * MAP Profile + * * @hide */ public static final int MAP = 9; @@ -114,43 +118,50 @@ public interface BluetoothProfile { /** * A2DP Sink Profile + * * @hide */ public static final int A2DP_SINK = 11; /** * AVRCP Controller Profile + * * @hide */ public static final int AVRCP_CONTROLLER = 12; /** * Headset Client - HFP HF Role + * * @hide */ public static final int HEADSET_CLIENT = 16; /** * PBAP Client + * * @hide */ public static final int PBAP_CLIENT = 17; /** * MAP Messaging Client Equipment (MCE) + * * @hide */ public static final int MAP_CLIENT = 18; /** * Input Host + * * @hide */ - static public final int INPUT_HOST = 19; + public static final int INPUT_HOST = 19; /** * Max profile ID. This value should be updated whenever a new profile is added to match * the largest value assigned to a profile. + * * @hide */ public static final int MAX_PROFILE_ID = 19; @@ -158,13 +169,15 @@ public interface BluetoothProfile { /** * Default priority for devices that we try to auto-connect to and * and allow incoming connections for the profile + * * @hide **/ public static final int PRIORITY_AUTO_CONNECT = 1000; /** - * Default priority for devices that allow incoming + * Default priority for devices that allow incoming * and outgoing connections for the profile + * * @hide **/ public static final int PRIORITY_ON = 100; @@ -172,14 +185,16 @@ public interface BluetoothProfile { /** * Default priority for devices that does not allow incoming * connections and outgoing connections for the profile. + * * @hide **/ public static final int PRIORITY_OFF = 0; /** * Default priority when not set or when the device is unpaired + * * @hide - * */ + */ public static final int PRIORITY_UNDEFINED = -1; /** @@ -199,9 +214,8 @@ public interface BluetoothProfile { * <p> If none of the devices match any of the given states, * an empty list will be returned. * - * @param states Array of states. States can be one of - * {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING}, - * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}, + * @param states Array of states. States can be one of {@link #STATE_CONNECTED}, {@link + * #STATE_CONNECTING}, {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}, * @return List of devices. The list will be empty on error. */ @RequiresPermission(Manifest.permission.BLUETOOTH) @@ -211,9 +225,8 @@ public interface BluetoothProfile { * Get the current connection state of the profile * * @param device Remote bluetooth device. - * @return State of the profile connection. One of - * {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING}, - * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING} + * @return State of the profile connection. One of {@link #STATE_CONNECTED}, {@link + * #STATE_CONNECTING}, {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING} */ @RequiresPermission(Manifest.permission.BLUETOOTH) public int getConnectionState(BluetoothDevice device); @@ -226,18 +239,18 @@ public interface BluetoothProfile { /** * Called to notify the client when the proxy object has been * connected to the service. - * @param profile - One of {@link #HEALTH}, {@link #HEADSET} or - * {@link #A2DP} - * @param proxy - One of {@link BluetoothHealth}, {@link BluetoothHeadset} or - * {@link BluetoothA2dp} + * + * @param profile - One of {@link #HEALTH}, {@link #HEADSET} or {@link #A2DP} + * @param proxy - One of {@link BluetoothHealth}, {@link BluetoothHeadset} or {@link + * BluetoothA2dp} */ public void onServiceConnected(int profile, BluetoothProfile proxy); /** * Called to notify the client that this proxy object has been * disconnected from the service. - * @param profile - One of {@link #HEALTH}, {@link #HEADSET} or - * {@link #A2DP} + * + * @param profile - One of {@link #HEALTH}, {@link #HEADSET} or {@link #A2DP} */ public void onServiceDisconnected(int profile); } diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java index 89c1bf8f9aa2..bcdf4938fe2f 100644 --- a/core/java/android/bluetooth/BluetoothSap.java +++ b/core/java/android/bluetooth/BluetoothSap.java @@ -16,19 +16,18 @@ package android.bluetooth; -import java.util.ArrayList; -import java.util.List; - import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.os.RemoteException; import android.os.Binder; import android.os.IBinder; -import android.os.ServiceManager; +import android.os.RemoteException; import android.util.Log; +import java.util.ArrayList; +import java.util.List; + /** * This class provides the APIs to control the Bluetooth SIM * Access Profile (SAP). @@ -38,6 +37,7 @@ import android.util.Log; * the BluetoothSap proxy object. * * <p>Each method is protected with its appropriate permission. + * * @hide */ public final class BluetoothSap implements BluetoothProfile { @@ -51,9 +51,9 @@ public final class BluetoothSap implements BluetoothProfile { * * <p>This intent will have 4 extras: * <ul> - * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> - * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> - * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> + * <li> {@link #EXTRA_STATE} - The current state of the profile. </li> + * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li> + * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li> * </ul> * * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of @@ -62,10 +62,11 @@ public final class BluetoothSap implements BluetoothProfile { * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to * receive. + * * @hide */ public static final String ACTION_CONNECTION_STATE_CHANGED = - "android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED"; + "android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED"; private IBluetoothSap mService; private final Context mContext; @@ -74,50 +75,53 @@ public final class BluetoothSap implements BluetoothProfile { /** * There was an error trying to obtain the state. + * * @hide */ public static final int STATE_ERROR = -1; /** * Connection state change succceeded. + * * @hide */ public static final int RESULT_SUCCESS = 1; /** * Connection canceled before completion. + * * @hide */ public static final int RESULT_CANCELED = 2; - final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { public void onBluetoothStateChange(boolean up) { if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); if (!up) { - if (VDBG) Log.d(TAG,"Unbinding service..."); + if (VDBG) Log.d(TAG, "Unbinding service..."); synchronized (mConnection) { try { mService = null; mContext.unbindService(mConnection); } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } else { synchronized (mConnection) { try { if (mService == null) { - if (VDBG) Log.d(TAG,"Binding service..."); + if (VDBG) Log.d(TAG, "Binding service..."); doBind(); } } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } } - }; + }; /** * Create a BluetoothSap proxy object. @@ -132,7 +136,7 @@ public final class BluetoothSap implements BluetoothProfile { try { mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } doBind(); @@ -163,6 +167,7 @@ public final class BluetoothSap implements BluetoothProfile { * Other public functions of BluetoothSap will return default error * results once close() has been called. Multiple invocations of close() * are ok. + * * @hide */ public synchronized void close() { @@ -171,7 +176,7 @@ public final class BluetoothSap implements BluetoothProfile { try { mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); } catch (Exception e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -181,7 +186,7 @@ public final class BluetoothSap implements BluetoothProfile { mService = null; mContext.unbindService(mConnection); } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } @@ -190,8 +195,9 @@ public final class BluetoothSap implements BluetoothProfile { /** * Get the current state of the BluetoothSap service. - * @return One of the STATE_ return codes, or STATE_ERROR if this proxy - * object is currently not connected to the Sap service. + * + * @return One of the STATE_ return codes, or STATE_ERROR if this proxy object is currently not + * connected to the Sap service. * @hide */ public int getState() { @@ -199,7 +205,9 @@ public final class BluetoothSap implements BluetoothProfile { if (mService != null) { try { return mService.getState(); - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); @@ -209,9 +217,9 @@ public final class BluetoothSap implements BluetoothProfile { /** * Get the currently connected remote Bluetooth device (PCE). - * @return The remote Bluetooth device, or null if not in connected or - * connecting state, or if this proxy object is not connected to - * the Sap service. + * + * @return The remote Bluetooth device, or null if not in connected or connecting state, or if + * this proxy object is not connected to the Sap service. * @hide */ public BluetoothDevice getClient() { @@ -219,7 +227,9 @@ public final class BluetoothSap implements BluetoothProfile { if (mService != null) { try { return mService.getClient(); - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); @@ -231,6 +241,7 @@ public final class BluetoothSap implements BluetoothProfile { * Returns true if the specified Bluetooth device is connected. * Returns false if not connected, or if this proxy object is not * currently connected to the Sap service. + * * @hide */ public boolean isConnected(BluetoothDevice device) { @@ -238,7 +249,9 @@ public final class BluetoothSap implements BluetoothProfile { if (mService != null) { try { return mService.isConnected(device); - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); @@ -249,6 +262,7 @@ public final class BluetoothSap implements BluetoothProfile { /** * Initiate connection. Initiation of outgoing connections is not * supported for SAP server. + * * @hide */ public boolean connect(BluetoothDevice device) { @@ -260,19 +274,17 @@ public final class BluetoothSap implements BluetoothProfile { * Initiate disconnect. * * @param device Remote Bluetooth Device - * @return false on error, - * true otherwise + * @return false on error, true otherwise * @hide */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.disconnect(device); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return false; } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -327,8 +339,7 @@ public final class BluetoothSap implements BluetoothProfile { */ public int getConnectionState(BluetoothDevice device) { if (DBG) log("getConnectionState(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.getConnectionState(device); } catch (RemoteException e) { @@ -352,11 +363,10 @@ public final class BluetoothSap implements BluetoothProfile { */ public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { - if (priority != BluetoothProfile.PRIORITY_OFF && - priority != BluetoothProfile.PRIORITY_ON) { - return false; + if (mService != null && isEnabled() && isValidDevice(device)) { + if (priority != BluetoothProfile.PRIORITY_OFF + && priority != BluetoothProfile.PRIORITY_ON) { + return false; } try { return mService.setPriority(device, priority); @@ -378,8 +388,7 @@ public final class BluetoothSap implements BluetoothProfile { */ public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.getPriority(device); } catch (RemoteException e) { @@ -399,6 +408,7 @@ public final class BluetoothSap implements BluetoothProfile { mServiceListener.onServiceConnected(BluetoothProfile.SAP, BluetoothSap.this); } } + public void onServiceDisconnected(ComponentName className) { if (DBG) log("Proxy object disconnected"); mService = null; @@ -415,19 +425,22 @@ public final class BluetoothSap implements BluetoothProfile { private boolean isEnabled() { BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) + if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) { return true; + } log("Bluetooth is Not enabled"); return false; } private boolean isValidDevice(BluetoothDevice device) { - if (device == null) - return false; + if (device == null) { + return false; + } - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) - return true; - return false; + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { + return true; + } + return false; } } diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java index 4860c9384051..58d090dc287b 100644 --- a/core/java/android/bluetooth/BluetoothServerSocket.java +++ b/core/java/android/bluetooth/BluetoothServerSocket.java @@ -75,12 +75,13 @@ public final class BluetoothServerSocket implements Closeable { /** * Construct a socket for incoming connections. - * @param type type of socket - * @param auth require the remote device to be authenticated + * + * @param type type of socket + * @param auth require the remote device to be authenticated * @param encrypt require the connection to be encrypted - * @param port remote port - * @throws IOException On error, for example Bluetooth not available, or - * insufficient privileges + * @param port remote port + * @throws IOException On error, for example Bluetooth not available, or insufficient + * privileges */ /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, int port) throws IOException { @@ -93,14 +94,15 @@ public final class BluetoothServerSocket implements Closeable { /** * Construct a socket for incoming connections. - * @param type type of socket - * @param auth require the remote device to be authenticated + * + * @param type type of socket + * @param auth require the remote device to be authenticated * @param encrypt require the connection to be encrypted - * @param port remote port - * @param mitm enforce man-in-the-middle protection for authentication. + * @param port remote port + * @param mitm enforce man-in-the-middle protection for authentication. * @param min16DigitPin enforce a minimum length of 16 digits for a sec mode 2 connection - * @throws IOException On error, for example Bluetooth not available, or - * insufficient privileges + * @throws IOException On error, for example Bluetooth not available, or insufficient + * privileges */ /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, int port, boolean mitm, boolean min16DigitPin) @@ -108,19 +110,20 @@ public final class BluetoothServerSocket implements Closeable { mChannel = port; mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, port, null, mitm, min16DigitPin); - if(port == BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { + if (port == BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { mSocket.setExcludeSdp(true); } } /** * Construct a socket for incoming connections. - * @param type type of socket - * @param auth require the remote device to be authenticated + * + * @param type type of socket + * @param auth require the remote device to be authenticated * @param encrypt require the connection to be encrypted - * @param uuid uuid - * @throws IOException On error, for example Bluetooth not available, or - * insufficient privileges + * @param uuid uuid + * @throws IOException On error, for example Bluetooth not available, or insufficient + * privileges */ /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, ParcelUuid uuid) throws IOException { @@ -136,9 +139,9 @@ public final class BluetoothServerSocket implements Closeable { * <p>Once this call returns, it can be called again to accept subsequent * incoming connections. * <p>{@link #close} can be used to abort this call from another thread. + * * @return a connected {@link BluetoothSocket} - * @throws IOException on error, for example this call was aborted, or - * timeout + * @throws IOException on error, for example this call was aborted, or timeout */ public BluetoothSocket accept() throws IOException { return accept(-1); @@ -150,9 +153,9 @@ public final class BluetoothServerSocket implements Closeable { * <p>Once this call returns, it can be called again to accept subsequent * incoming connections. * <p>{@link #close} can be used to abort this call from another thread. + * * @return a connected {@link BluetoothSocket} - * @throws IOException on error, for example this call was aborted, or - * timeout + * @throws IOException on error, for example this call was aborted, or timeout */ public BluetoothSocket accept(int timeout) throws IOException { return mSocket.accept(timeout); @@ -174,16 +177,19 @@ public final class BluetoothServerSocket implements Closeable { mSocket.close(); } - /*package*/ synchronized void setCloseHandler(Handler handler, int message) { + /*package*/ + synchronized void setCloseHandler(Handler handler, int message) { mHandler = handler; mMessage = message; } - /*package*/ void setServiceName(String ServiceName) { - mSocket.setServiceName(ServiceName); + + /*package*/ void setServiceName(String serviceName) { + mSocket.setServiceName(serviceName); } /** * Returns the channel on which this socket is bound. + * * @hide */ public int getChannel() { @@ -199,10 +205,10 @@ public final class BluetoothServerSocket implements Closeable { * The bind operation should be conducted through this class * and the resulting port should be kept in mChannel, and * not set from BluetoothAdapter. */ - if(mSocket != null) { - if(mSocket.getPort() != newChannel) { - Log.w(TAG,"The port set is different that the underlying port. mSocket.getPort(): " - + mSocket.getPort() + " requested newChannel: " + newChannel); + if (mSocket != null) { + if (mSocket.getPort() != newChannel) { + Log.w(TAG, "The port set is different that the underlying port. mSocket.getPort(): " + + mSocket.getPort() + " requested newChannel: " + newChannel); } } mChannel = newChannel; @@ -212,19 +218,16 @@ public final class BluetoothServerSocket implements Closeable { public String toString() { StringBuilder sb = new StringBuilder(); sb.append("ServerSocket: Type: "); - switch(mSocket.getConnectionType()) { - case BluetoothSocket.TYPE_RFCOMM: - { + switch (mSocket.getConnectionType()) { + case BluetoothSocket.TYPE_RFCOMM: { sb.append("TYPE_RFCOMM"); break; } - case BluetoothSocket.TYPE_L2CAP: - { + case BluetoothSocket.TYPE_L2CAP: { sb.append("TYPE_L2CAP"); break; } - case BluetoothSocket.TYPE_SCO: - { + case BluetoothSocket.TYPE_SCO: { sb.append("TYPE_SCO"); break; } diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java index 6bf6aa0a9efa..4035ee1beb8f 100644 --- a/core/java/android/bluetooth/BluetoothSocket.java +++ b/core/java/android/bluetooth/BluetoothSocket.java @@ -16,25 +16,23 @@ package android.bluetooth; -import android.os.ParcelUuid; +import android.net.LocalSocket; import android.os.ParcelFileDescriptor; +import android.os.ParcelUuid; import android.os.RemoteException; import android.util.Log; -import java.io.BufferedInputStream; import java.io.Closeable; import java.io.FileDescriptor; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.util.Arrays; import java.util.Locale; import java.util.UUID; -import android.net.LocalSocket; -import java.nio.Buffer; -import java.nio.ByteOrder; -import java.nio.ByteBuffer; /** * A connected or connecting Bluetooth socket. * @@ -106,9 +104,9 @@ public final class BluetoothSocket implements Closeable { /*package*/ static final int SEC_FLAG_ENCRYPT = 1; /*package*/ static final int SEC_FLAG_AUTH = 1 << 1; - /*package*/ static final int BTSOCK_FLAG_NO_SDP = 1 << 2; - /*package*/ static final int SEC_FLAG_AUTH_MITM = 1 << 3; - /*package*/ static final int SEC_FLAG_AUTH_16_DIGIT = 1 << 4; + /*package*/ static final int BTSOCK_FLAG_NO_SDP = 1 << 2; + /*package*/ static final int SEC_FLAG_AUTH_MITM = 1 << 3; + /*package*/ static final int SEC_FLAG_AUTH_16_DIGIT = 1 << 4; private final int mType; /* one of TYPE_RFCOMM etc */ private BluetoothDevice mDevice; /* remote device */ @@ -128,9 +126,9 @@ public final class BluetoothSocket implements Closeable { private int mPort; /* RFCOMM channel or L2CAP psm */ private int mFd; private String mServiceName; - private static int PROXY_CONNECTION_TIMEOUT = 5000; + private static final int PROXY_CONNECTION_TIMEOUT = 5000; - private static int SOCK_SIGNAL_SIZE = 20; + private static final int SOCK_SIGNAL_SIZE = 20; private ByteBuffer mL2capBuffer = null; private int mMaxTxPacketSize = 0; // The l2cap maximum packet size supported by the peer. @@ -151,15 +149,16 @@ public final class BluetoothSocket implements Closeable { /** * Construct a BluetoothSocket. - * @param type type of socket - * @param fd fd to use for connected socket, or -1 for a new socket - * @param auth require the remote device to be authenticated + * + * @param type type of socket + * @param fd fd to use for connected socket, or -1 for a new socket + * @param auth require the remote device to be authenticated * @param encrypt require the connection to be encrypted - * @param device remote device that this socket can connect to - * @param port remote port - * @param uuid SDP uuid - * @throws IOException On error, for example Bluetooth not available, or - * insufficient privileges + * @param device remote device that this socket can connect to + * @param port remote port + * @param uuid SDP uuid + * @throws IOException On error, for example Bluetooth not available, or insufficient + * privileges */ /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, BluetoothDevice device, int port, ParcelUuid uuid) throws IOException { @@ -168,21 +167,22 @@ public final class BluetoothSocket implements Closeable { /** * Construct a BluetoothSocket. - * @param type type of socket - * @param fd fd to use for connected socket, or -1 for a new socket - * @param auth require the remote device to be authenticated + * + * @param type type of socket + * @param fd fd to use for connected socket, or -1 for a new socket + * @param auth require the remote device to be authenticated * @param encrypt require the connection to be encrypted - * @param device remote device that this socket can connect to - * @param port remote port - * @param uuid SDP uuid - * @param mitm enforce man-in-the-middle protection. + * @param device remote device that this socket can connect to + * @param port remote port + * @param uuid SDP uuid + * @param mitm enforce man-in-the-middle protection. * @param min16DigitPin enforce a minimum length of 16 digits for a sec mode 2 connection - * @throws IOException On error, for example Bluetooth not available, or - * insufficient privileges + * @throws IOException On error, for example Bluetooth not available, or insufficient + * privileges */ /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, BluetoothDevice device, int port, ParcelUuid uuid, boolean mitm, boolean min16DigitPin) - throws IOException { + throws IOException { if (VDBG) Log.d(TAG, "Creating new BluetoothSocket of type: " + type); if (type == BluetoothSocket.TYPE_RFCOMM && uuid == null && fd == -1 && port != BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { @@ -190,9 +190,11 @@ public final class BluetoothSocket implements Closeable { throw new IOException("Invalid RFCOMM channel: " + port); } } - if (uuid != null) + if (uuid != null) { mUuid = uuid; - else mUuid = new ParcelUuid(new UUID(0, 0)); + } else { + mUuid = new ParcelUuid(new UUID(0, 0)); + } mType = type; mAuth = auth; mAuthMitm = mitm; @@ -214,6 +216,7 @@ public final class BluetoothSocket implements Closeable { mInputStream = new BluetoothInputStream(this); mOutputStream = new BluetoothOutputStream(this); } + private BluetoothSocket(BluetoothSocket s) { if (VDBG) Log.d(TAG, "Creating new Private BluetoothSocket of type: " + s.mType); mUuid = s.mUuid; @@ -231,12 +234,13 @@ public final class BluetoothSocket implements Closeable { mAuthMitm = s.mAuthMitm; mMin16DigitPin = s.mMin16DigitPin; } - private BluetoothSocket acceptSocket(String RemoteAddr) throws IOException { + + private BluetoothSocket acceptSocket(String remoteAddr) throws IOException { BluetoothSocket as = new BluetoothSocket(this); as.mSocketState = SocketState.CONNECTED; FileDescriptor[] fds = mSocket.getAncillaryFileDescriptors(); if (DBG) Log.d(TAG, "socket fd passed by stack fds: " + Arrays.toString(fds)); - if(fds == null || fds.length != 1) { + if (fds == null || fds.length != 1) { Log.e(TAG, "socket fd passed from stack failed, fds: " + Arrays.toString(fds)); as.close(); throw new IOException("bt socket acept failed"); @@ -246,20 +250,22 @@ public final class BluetoothSocket implements Closeable { as.mSocket = LocalSocket.createConnectedLocalSocket(fds[0]); as.mSocketIS = as.mSocket.getInputStream(); as.mSocketOS = as.mSocket.getOutputStream(); - as.mAddress = RemoteAddr; - as.mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(RemoteAddr); + as.mAddress = remoteAddr; + as.mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(remoteAddr); return as; } + /** * Construct a BluetoothSocket from address. Used by native code. - * @param type type of socket - * @param fd fd to use for connected socket, or -1 for a new socket - * @param auth require the remote device to be authenticated + * + * @param type type of socket + * @param fd fd to use for connected socket, or -1 for a new socket + * @param auth require the remote device to be authenticated * @param encrypt require the connection to be encrypted * @param address remote device that this socket can connect to - * @param port remote port - * @throws IOException On error, for example Bluetooth not available, or - * insufficient privileges + * @param port remote port + * @throws IOException On error, for example Bluetooth not available, or insufficient + * privileges */ private BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, String address, int port) throws IOException { @@ -275,23 +281,30 @@ public final class BluetoothSocket implements Closeable { super.finalize(); } } + private int getSecurityFlags() { int flags = 0; - if(mAuth) + if (mAuth) { flags |= SEC_FLAG_AUTH; - if(mEncrypt) + } + if (mEncrypt) { flags |= SEC_FLAG_ENCRYPT; - if(mExcludeSdp) + } + if (mExcludeSdp) { flags |= BTSOCK_FLAG_NO_SDP; - if(mAuthMitm) + } + if (mAuthMitm) { flags |= SEC_FLAG_AUTH_MITM; - if(mMin16DigitPin) + } + if (mMin16DigitPin) { flags |= SEC_FLAG_AUTH_16_DIGIT; + } return flags; } /** * Get the remote device this socket is connecting, or connected, to. + * * @return remote device */ public BluetoothDevice getRemoteDevice() { @@ -303,6 +316,7 @@ public final class BluetoothSocket implements Closeable { * <p>The input stream will be returned even if the socket is not yet * connected, but operations on that stream will throw IOException until * the associated socket is connected. + * * @return InputStream */ public InputStream getInputStream() throws IOException { @@ -314,6 +328,7 @@ public final class BluetoothSocket implements Closeable { * <p>The output stream will be returned even if the socket is not yet * connected, but operations on that stream will throw IOException until * the associated socket is connected. + * * @return OutputStream */ public OutputStream getOutputStream() throws IOException { @@ -323,8 +338,8 @@ public final class BluetoothSocket implements Closeable { /** * Get the connection status of this socket, ie, whether there is an active connection with * remote device. - * @return true if connected - * false if not connected + * + * @return true if connected false if not connected */ public boolean isConnected() { return mSocketState == SocketState.CONNECTED; @@ -349,6 +364,7 @@ public final class BluetoothSocket implements Closeable { * {@link BluetoothAdapter#cancelDiscovery()} even if it * did not directly request a discovery, just to be sure. * <p>{@link #close} can be used to abort this call from another thread. + * * @throws IOException on error, for example connection failure */ public void connect() throws IOException { @@ -361,8 +377,7 @@ public final class BluetoothSocket implements Closeable { if (bluetoothProxy == null) throw new IOException("Bluetooth is off"); mPfd = bluetoothProxy.connectSocket(mDevice, mType, mUuid, mPort, getSecurityFlags()); - synchronized(this) - { + synchronized (this) { if (DBG) Log.d(TAG, "connect(), SocketState: " + mSocketState + ", mPfd: " + mPfd); if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed"); if (mPfd == null) throw new IOException("bt socket connect failed"); @@ -372,14 +387,15 @@ public final class BluetoothSocket implements Closeable { mSocketOS = mSocket.getOutputStream(); } int channel = readInt(mSocketIS); - if (channel <= 0) + if (channel <= 0) { throw new IOException("bt socket connect failed"); + } mPort = channel; waitSocketSignal(mSocketIS); - synchronized(this) - { - if (mSocketState == SocketState.CLOSED) + synchronized (this) { + if (mSocketState == SocketState.CLOSED) { throw new IOException("bt socket closed"); + } mSocketState = SocketState.CONNECTED; } } catch (RemoteException e) { @@ -410,11 +426,12 @@ public final class BluetoothSocket implements Closeable { // read out port number try { - synchronized(this) { - if (DBG) Log.d(TAG, "bindListen(), SocketState: " + mSocketState + ", mPfd: " + - mPfd); - if(mSocketState != SocketState.INIT) return EBADFD; - if(mPfd == null) return -1; + synchronized (this) { + if (DBG) { + Log.d(TAG, "bindListen(), SocketState: " + mSocketState + ", mPfd: " + mPfd); + } + if (mSocketState != SocketState.INIT) return EBADFD; + if (mPfd == null) return -1; FileDescriptor fd = mPfd.getFileDescriptor(); if (fd == null) { Log.e(TAG, "bindListen(), null file descriptor"); @@ -429,9 +446,10 @@ public final class BluetoothSocket implements Closeable { } if (DBG) Log.d(TAG, "bindListen(), readInt mSocketIS: " + mSocketIS); int channel = readInt(mSocketIS); - synchronized(this) { - if(mSocketState == SocketState.INIT) + synchronized (this) { + if (mSocketState == SocketState.INIT) { mSocketState = SocketState.LISTENING; + } } if (DBG) Log.d(TAG, "channel: " + channel); if (mPort <= -1) { @@ -455,19 +473,21 @@ public final class BluetoothSocket implements Closeable { /*package*/ BluetoothSocket accept(int timeout) throws IOException { BluetoothSocket acceptedSocket; - if (mSocketState != SocketState.LISTENING) + if (mSocketState != SocketState.LISTENING) { throw new IOException("bt socket is not in listen state"); - if(timeout > 0) { + } + if (timeout > 0) { Log.d(TAG, "accept() set timeout (ms):" + timeout); - mSocket.setSoTimeout(timeout); + mSocket.setSoTimeout(timeout); } String RemoteAddr = waitSocketSignal(mSocketIS); - if(timeout > 0) + if (timeout > 0) { mSocket.setSoTimeout(0); - synchronized(this) - { - if (mSocketState != SocketState.LISTENING) + } + synchronized (this) { + if (mSocketState != SocketState.LISTENING) { throw new IOException("bt socket is not in listen state"); + } acceptedSocket = acceptSocket(RemoteAddr); //quick drop the reference of the file handle } @@ -478,12 +498,13 @@ public final class BluetoothSocket implements Closeable { if (VDBG) Log.d(TAG, "available: " + mSocketIS); return mSocketIS.available(); } + /** * Wait until the data in sending queue is emptied. A polling version * for flush implementation. Used to ensure the writing data afterwards will * be packed in new RFCOMM frame. - * @throws IOException - * if an i/o error occurs. + * + * @throws IOException if an i/o error occurs. */ /*package*/ void flush() throws IOException { if (mSocketOS == null) throw new IOException("flush is called on null OutputStream"); @@ -494,11 +515,12 @@ public final class BluetoothSocket implements Closeable { /*package*/ int read(byte[] b, int offset, int length) throws IOException { int ret = 0; if (VDBG) Log.d(TAG, "read in: " + mSocketIS + " len: " + length); - if(mType == TYPE_L2CAP) - { + if (mType == TYPE_L2CAP) { int bytesToRead = length; - if (VDBG) Log.v(TAG, "l2cap: read(): offset: " + offset + " length:" + length - + "mL2capBuffer= " + mL2capBuffer); + if (VDBG) { + Log.v(TAG, "l2cap: read(): offset: " + offset + " length:" + length + + "mL2capBuffer= " + mL2capBuffer); + } if (mL2capBuffer == null) { createL2capRxBuffer(); } @@ -511,16 +533,19 @@ public final class BluetoothSocket implements Closeable { if (bytesToRead > mL2capBuffer.remaining()) { bytesToRead = mL2capBuffer.remaining(); } - if(VDBG) Log.v(TAG, "get(): offset: " + offset - + " bytesToRead: " + bytesToRead); + if (VDBG) { + Log.v(TAG, "get(): offset: " + offset + + " bytesToRead: " + bytesToRead); + } mL2capBuffer.get(b, offset, bytesToRead); ret = bytesToRead; - }else { + } else { if (VDBG) Log.v(TAG, "default: read(): offset: " + offset + " length:" + length); ret = mSocketIS.read(b, offset, length); } - if (ret < 0) + if (ret < 0) { throw new IOException("bt socket closed, read return: " + ret); + } if (VDBG) Log.d(TAG, "read out: " + mSocketIS + " ret: " + ret); return ret; } @@ -532,48 +557,49 @@ public final class BluetoothSocket implements Closeable { // splitting the write into multiple smaller writes. // Rfcomm uses dynamic allocation, and should not have any bindings // to the actual message length. - if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length); - if (mType == TYPE_L2CAP) { - if(length <= mMaxTxPacketSize) { - mSocketOS.write(b, offset, length); - } else { - if(DBG) Log.w(TAG, "WARNING: Write buffer larger than L2CAP packet size!\n" + if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length); + if (mType == TYPE_L2CAP) { + if (length <= mMaxTxPacketSize) { + mSocketOS.write(b, offset, length); + } else { + if (DBG) { + Log.w(TAG, "WARNING: Write buffer larger than L2CAP packet size!\n" + "Packet will be divided into SDU packets of size " + mMaxTxPacketSize); - int tmpOffset = offset; - int bytesToWrite = length; - while (bytesToWrite > 0) { - int tmpLength = (bytesToWrite > mMaxTxPacketSize) - ? mMaxTxPacketSize - : bytesToWrite; - mSocketOS.write(b, tmpOffset, tmpLength); - tmpOffset += tmpLength; - bytesToWrite -= tmpLength; - } } - } else { - mSocketOS.write(b, offset, length); + int tmpOffset = offset; + int bytesToWrite = length; + while (bytesToWrite > 0) { + int tmpLength = (bytesToWrite > mMaxTxPacketSize) + ? mMaxTxPacketSize + : bytesToWrite; + mSocketOS.write(b, tmpOffset, tmpLength); + tmpOffset += tmpLength; + bytesToWrite -= tmpLength; + } } - // There is no good way to confirm since the entire process is asynchronous anyway - if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length); - return length; + } else { + mSocketOS.write(b, offset, length); + } + // There is no good way to confirm since the entire process is asynchronous anyway + if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length); + return length; } @Override public void close() throws IOException { - Log.d(TAG, "close() this: " + this + ", channel: " + mPort + - ", mSocketIS: " + mSocketIS + ", mSocketOS: " + mSocketOS + - "mSocket: " + mSocket + ", mSocketState: " + mSocketState); - if(mSocketState == SocketState.CLOSED) + Log.d(TAG, "close() this: " + this + ", channel: " + mPort + ", mSocketIS: " + mSocketIS + + ", mSocketOS: " + mSocketOS + "mSocket: " + mSocket + ", mSocketState: " + + mSocketState); + if (mSocketState == SocketState.CLOSED) { return; - else - { - synchronized(this) - { - if(mSocketState == SocketState.CLOSED) + } else { + synchronized (this) { + if (mSocketState == SocketState.CLOSED) { return; - mSocketState = SocketState.CLOSED; - if(mSocket != null) { + } + mSocketState = SocketState.CLOSED; + if (mSocket != null) { if (DBG) Log.d(TAG, "Closing mSocket: " + mSocket); mSocket.shutdownInput(); mSocket.shutdownOutput(); @@ -584,7 +610,7 @@ public final class BluetoothSocket implements Closeable { mPfd.close(); mPfd = null; } - } + } } } @@ -599,9 +625,10 @@ public final class BluetoothSocket implements Closeable { * Get the maximum supported Transmit packet size for the underlying transport. * Use this to optimize the writes done to the output socket, to avoid sending * half full packets. + * * @return the maximum supported Transmit packet size for the underlying transport. */ - public int getMaxTransmitPacketSize(){ + public int getMaxTransmitPacketSize() { return mMaxTxPacketSize; } @@ -610,14 +637,16 @@ public final class BluetoothSocket implements Closeable { * Use this to optimize the reads done on the input stream, as any call to read * will return a maximum of this amount of bytes - or for some transports a * multiple of this value. + * * @return the maximum supported Receive packet size for the underlying transport. */ - public int getMaxReceivePacketSize(){ + public int getMaxReceivePacketSize() { return mMaxRxPacketSize; } /** * Get the type of the underlying connection. + * * @return one of {@link #TYPE_RFCOMM}, {@link #TYPE_SCO} or {@link #TYPE_L2CAP} */ public int getConnectionType() { @@ -627,67 +656,77 @@ public final class BluetoothSocket implements Closeable { /** * Change if a SDP entry should be automatically created. * Must be called before calling .bind, for the call to have any effect. - * @param mExcludeSdp <li>TRUE - do not auto generate SDP record. - * <li>FALSE - default - auto generate SPP SDP record. + * + * @param excludeSdp <li>TRUE - do not auto generate SDP record. <li>FALSE - default - auto + * generate SPP SDP record. * @hide */ public void setExcludeSdp(boolean excludeSdp) { - this.mExcludeSdp = excludeSdp; + mExcludeSdp = excludeSdp; } - private String convertAddr(final byte[] addr) { + private String convertAddr(final byte[] addr) { return String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X", - addr[0] , addr[1], addr[2], addr[3] , addr[4], addr[5]); + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); } + private String waitSocketSignal(InputStream is) throws IOException { - byte [] sig = new byte[SOCK_SIGNAL_SIZE]; + byte[] sig = new byte[SOCK_SIGNAL_SIZE]; int ret = readAll(is, sig); - if (VDBG) Log.d(TAG, "waitSocketSignal read " + SOCK_SIGNAL_SIZE + - " bytes signal ret: " + ret); + if (VDBG) { + Log.d(TAG, "waitSocketSignal read " + SOCK_SIGNAL_SIZE + " bytes signal ret: " + ret); + } ByteBuffer bb = ByteBuffer.wrap(sig); /* the struct in native is decorated with __attribute__((packed)), hence this is possible */ bb.order(ByteOrder.nativeOrder()); int size = bb.getShort(); - if(size != SOCK_SIGNAL_SIZE) + if (size != SOCK_SIGNAL_SIZE) { throw new IOException("Connection failure, wrong signal size: " + size); - byte [] addr = new byte[6]; + } + byte[] addr = new byte[6]; bb.get(addr); int channel = bb.getInt(); int status = bb.getInt(); mMaxTxPacketSize = (bb.getShort() & 0xffff); // Convert to unsigned value mMaxRxPacketSize = (bb.getShort() & 0xffff); // Convert to unsigned value String RemoteAddr = convertAddr(addr); - if (VDBG) Log.d(TAG, "waitSocketSignal: sig size: " + size + ", remote addr: " - + RemoteAddr + ", channel: " + channel + ", status: " + status - + " MaxRxPktSize: " + mMaxRxPacketSize + " MaxTxPktSize: " + mMaxTxPacketSize); - if(status != 0) + if (VDBG) { + Log.d(TAG, "waitSocketSignal: sig size: " + size + ", remote addr: " + + RemoteAddr + ", channel: " + channel + ", status: " + status + + " MaxRxPktSize: " + mMaxRxPacketSize + " MaxTxPktSize: " + mMaxTxPacketSize); + } + if (status != 0) { throw new IOException("Connection failure, status: " + status); + } return RemoteAddr; } - private void createL2capRxBuffer(){ - if(mType == TYPE_L2CAP) { + private void createL2capRxBuffer() { + if (mType == TYPE_L2CAP) { // Allocate the buffer to use for reads. - if(VDBG) Log.v(TAG, " Creating mL2capBuffer: mMaxPacketSize: " + mMaxRxPacketSize); + if (VDBG) Log.v(TAG, " Creating mL2capBuffer: mMaxPacketSize: " + mMaxRxPacketSize); mL2capBuffer = ByteBuffer.wrap(new byte[mMaxRxPacketSize]); - if(VDBG) Log.v(TAG, "mL2capBuffer.remaining()" + mL2capBuffer.remaining()); + if (VDBG) Log.v(TAG, "mL2capBuffer.remaining()" + mL2capBuffer.remaining()); mL2capBuffer.limit(0); // Ensure we do a real read at the first read-request - if(VDBG) Log.v(TAG, "mL2capBuffer.remaining() after limit(0):" + - mL2capBuffer.remaining()); + if (VDBG) { + Log.v(TAG, "mL2capBuffer.remaining() after limit(0):" + mL2capBuffer.remaining()); + } } } private int readAll(InputStream is, byte[] b) throws IOException { int left = b.length; - while(left > 0) { + while (left > 0) { int ret = is.read(b, b.length - left, left); - if(ret <= 0) - throw new IOException("read failed, socket might closed or timeout, read ret: " - + ret); + if (ret <= 0) { + throw new IOException("read failed, socket might closed or timeout, read ret: " + + ret); + } left -= ret; - if(left != 0) - Log.w(TAG, "readAll() looping, read partial size: " + (b.length - left) + - ", expect size: " + b.length); + if (left != 0) { + Log.w(TAG, "readAll() looping, read partial size: " + (b.length - left) + + ", expect size: " + b.length); + } } return b.length; } @@ -704,7 +743,7 @@ public final class BluetoothSocket implements Closeable { private int fillL2capRxBuffer() throws IOException { mL2capBuffer.rewind(); int ret = mSocketIS.read(mL2capBuffer.array()); - if(ret == -1) { + if (ret == -1) { // reached end of stream - return -1 mL2capBuffer.limit(0); return -1; diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java index 243579a31ce0..5bfc54d267ca 100644 --- a/core/java/android/bluetooth/BluetoothUuid.java +++ b/core/java/android/bluetooth/BluetoothUuid.java @@ -25,9 +25,10 @@ import java.util.HashSet; import java.util.UUID; /** -* Static helper methods and constants to decode the ParcelUuid of remote devices. -* @hide -*/ + * Static helper methods and constants to decode the ParcelUuid of remote devices. + * + * @hide + */ public final class BluetoothUuid { /* See Bluetooth Assigned Numbers document - SDP section, to get the values of UUIDs @@ -76,9 +77,9 @@ public final class BluetoothUuid { ParcelUuid.fromString("00001133-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid MAS = ParcelUuid.fromString("00001132-0000-1000-8000-00805F9B34FB"); - public static final ParcelUuid SAP = + public static final ParcelUuid SAP = ParcelUuid.fromString("0000112D-0000-1000-8000-00805F9B34FB"); - + public static final ParcelUuid BASE_UUID = ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB"); @@ -90,8 +91,8 @@ public final class BluetoothUuid { public static final int UUID_BYTES_128_BIT = 16; public static final ParcelUuid[] RESERVED_UUIDS = { - AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget, - ObexObjectPush, PANU, NAP, MAP, MNS, MAS, SAP}; + AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget, + ObexObjectPush, PANU, NAP, MAP, MNS, MAS, SAP}; public static boolean isAudioSource(ParcelUuid uuid) { return uuid.equals(AudioSource); @@ -136,15 +137,19 @@ public final class BluetoothUuid { public static boolean isBnep(ParcelUuid uuid) { return uuid.equals(BNEP); } + public static boolean isMap(ParcelUuid uuid) { return uuid.equals(MAP); } + public static boolean isMns(ParcelUuid uuid) { return uuid.equals(MNS); } + public static boolean isMas(ParcelUuid uuid) { return uuid.equals(MAS); } + public static boolean isSap(ParcelUuid uuid) { return uuid.equals(SAP); } @@ -156,13 +161,15 @@ public final class BluetoothUuid { * @param uuid */ public static boolean isUuidPresent(ParcelUuid[] uuidArray, ParcelUuid uuid) { - if ((uuidArray == null || uuidArray.length == 0) && uuid == null) + if ((uuidArray == null || uuidArray.length == 0) && uuid == null) { return true; + } - if (uuidArray == null) + if (uuidArray == null) { return false; + } - for (ParcelUuid element: uuidArray) { + for (ParcelUuid element : uuidArray) { if (element.equals(uuid)) return true; } return false; @@ -173,21 +180,20 @@ public final class BluetoothUuid { * * @param uuidA - List of ParcelUuids * @param uuidB - List of ParcelUuids - * */ public static boolean containsAnyUuid(ParcelUuid[] uuidA, ParcelUuid[] uuidB) { if (uuidA == null && uuidB == null) return true; if (uuidA == null) { - return uuidB.length == 0 ? true : false; + return uuidB.length == 0; } if (uuidB == null) { - return uuidA.length == 0 ? true : false; + return uuidA.length == 0; } - HashSet<ParcelUuid> uuidSet = new HashSet<ParcelUuid> (Arrays.asList(uuidA)); - for (ParcelUuid uuid: uuidB) { + HashSet<ParcelUuid> uuidSet = new HashSet<ParcelUuid>(Arrays.asList(uuidA)); + for (ParcelUuid uuid : uuidB) { if (uuidSet.contains(uuid)) return true; } return false; @@ -199,19 +205,18 @@ public final class BluetoothUuid { * * @param uuidA - Array of ParcelUuidsA * @param uuidB - Array of ParcelUuidsB - * */ public static boolean containsAllUuids(ParcelUuid[] uuidA, ParcelUuid[] uuidB) { if (uuidA == null && uuidB == null) return true; if (uuidA == null) { - return uuidB.length == 0 ? true : false; + return uuidB.length == 0; } if (uuidB == null) return true; - HashSet<ParcelUuid> uuidSet = new HashSet<ParcelUuid> (Arrays.asList(uuidA)); - for (ParcelUuid uuid: uuidB) { + HashSet<ParcelUuid> uuidSet = new HashSet<ParcelUuid>(Arrays.asList(uuidA)); + for (ParcelUuid uuid : uuidB) { if (!uuidSet.contains(uuid)) return false; } return true; @@ -221,13 +226,14 @@ public final class BluetoothUuid { * Extract the Service Identifier or the actual uuid from the Parcel Uuid. * For example, if 0000110B-0000-1000-8000-00805F9B34FB is the parcel Uuid, * this function will return 110B + * * @param parcelUuid * @return the service identifier. */ public static int getServiceIdentifierFromParcelUuid(ParcelUuid parcelUuid) { UUID uuid = parcelUuid.getUuid(); long value = (uuid.getMostSignificantBits() & 0x0000FFFF00000000L) >>> 32; - return (int)value; + return (int) value; } /** @@ -244,8 +250,8 @@ public final class BluetoothUuid { throw new IllegalArgumentException("uuidBytes cannot be null"); } int length = uuidBytes.length; - if (length != UUID_BYTES_16_BIT && length != UUID_BYTES_32_BIT && - length != UUID_BYTES_128_BIT) { + if (length != UUID_BYTES_16_BIT && length != UUID_BYTES_32_BIT + && length != UUID_BYTES_128_BIT) { throw new IllegalArgumentException("uuidBytes length invalid - " + length); } @@ -264,7 +270,7 @@ public final class BluetoothUuid { shortUuid = uuidBytes[0] & 0xFF; shortUuid += (uuidBytes[1] & 0xFF) << 8; } else { - shortUuid = uuidBytes[0] & 0xFF ; + shortUuid = uuidBytes[0] & 0xFF; shortUuid += (uuidBytes[1] & 0xFF) << 8; shortUuid += (uuidBytes[2] & 0xFF) << 16; shortUuid += (uuidBytes[3] & 0xFF) << 24; @@ -275,8 +281,8 @@ public final class BluetoothUuid { } /** - * Parse UUID to bytes. The returned value is shortest representation, a 16-bit, 32-bit or 128-bit UUID, - * Note returned value is little endian (Bluetooth). + * Parse UUID to bytes. The returned value is shortest representation, a 16-bit, 32-bit or + * 128-bit UUID, Note returned value is little endian (Bluetooth). * * @param uuid uuid to parse. * @return shortest representation of {@code uuid} as bytes. @@ -290,18 +296,18 @@ public final class BluetoothUuid { if (is16BitUuid(uuid)) { byte[] uuidBytes = new byte[UUID_BYTES_16_BIT]; int uuidVal = getServiceIdentifierFromParcelUuid(uuid); - uuidBytes[0] = (byte)(uuidVal & 0xFF); - uuidBytes[1] = (byte)((uuidVal & 0xFF00) >> 8); + uuidBytes[0] = (byte) (uuidVal & 0xFF); + uuidBytes[1] = (byte) ((uuidVal & 0xFF00) >> 8); return uuidBytes; } if (is32BitUuid(uuid)) { byte[] uuidBytes = new byte[UUID_BYTES_32_BIT]; int uuidVal = getServiceIdentifierFromParcelUuid(uuid); - uuidBytes[0] = (byte)(uuidVal & 0xFF); - uuidBytes[1] = (byte)((uuidVal & 0xFF00) >> 8); - uuidBytes[2] = (byte)((uuidVal & 0xFF0000) >> 16); - uuidBytes[3] = (byte)((uuidVal & 0xFF000000) >> 24); + uuidBytes[0] = (byte) (uuidVal & 0xFF); + uuidBytes[1] = (byte) ((uuidVal & 0xFF00) >> 8); + uuidBytes[2] = (byte) ((uuidVal & 0xFF0000) >> 16); + uuidBytes[3] = (byte) ((uuidVal & 0xFF000000) >> 24); return uuidBytes; } diff --git a/core/java/android/bluetooth/OobData.java b/core/java/android/bluetooth/OobData.java index 9e87230c686e..d63257286975 100644 --- a/core/java/android/bluetooth/OobData.java +++ b/core/java/android/bluetooth/OobData.java @@ -19,8 +19,6 @@ package android.bluetooth; import android.os.Parcel; import android.os.Parcelable; -import android.util.Log; - /** * Out Of Band Data for Bluetooth device pairing. * @@ -30,13 +28,13 @@ import android.util.Log; * @hide */ public class OobData implements Parcelable { - private byte[] leBluetoothDeviceAddress; - private byte[] securityManagerTk; - private byte[] leSecureConnectionsConfirmation; - private byte[] leSecureConnectionsRandom; + private byte[] mLeBluetoothDeviceAddress; + private byte[] mSecurityManagerTk; + private byte[] mLeSecureConnectionsConfirmation; + private byte[] mLeSecureConnectionsRandom; public byte[] getLeBluetoothDeviceAddress() { - return leBluetoothDeviceAddress; + return mLeBluetoothDeviceAddress; } /** @@ -45,11 +43,11 @@ public class OobData implements Parcelable { * a detailed description. */ public void setLeBluetoothDeviceAddress(byte[] leBluetoothDeviceAddress) { - this.leBluetoothDeviceAddress = leBluetoothDeviceAddress; + mLeBluetoothDeviceAddress = leBluetoothDeviceAddress; } public byte[] getSecurityManagerTk() { - return securityManagerTk; + return mSecurityManagerTk; } /** @@ -58,48 +56,50 @@ public class OobData implements Parcelable { * Part A 1.8 for a detailed description. */ public void setSecurityManagerTk(byte[] securityManagerTk) { - this.securityManagerTk = securityManagerTk; + mSecurityManagerTk = securityManagerTk; } public byte[] getLeSecureConnectionsConfirmation() { - return leSecureConnectionsConfirmation; + return mLeSecureConnectionsConfirmation; } public void setLeSecureConnectionsConfirmation(byte[] leSecureConnectionsConfirmation) { - this.leSecureConnectionsConfirmation = leSecureConnectionsConfirmation; + mLeSecureConnectionsConfirmation = leSecureConnectionsConfirmation; } public byte[] getLeSecureConnectionsRandom() { - return leSecureConnectionsRandom; + return mLeSecureConnectionsRandom; } public void setLeSecureConnectionsRandom(byte[] leSecureConnectionsRandom) { - this.leSecureConnectionsRandom = leSecureConnectionsRandom; + mLeSecureConnectionsRandom = leSecureConnectionsRandom; } - public OobData() { } + public OobData() { + } private OobData(Parcel in) { - leBluetoothDeviceAddress = in.createByteArray(); - securityManagerTk = in.createByteArray(); - leSecureConnectionsConfirmation = in.createByteArray(); - leSecureConnectionsRandom = in.createByteArray(); + mLeBluetoothDeviceAddress = in.createByteArray(); + mSecurityManagerTk = in.createByteArray(); + mLeSecureConnectionsConfirmation = in.createByteArray(); + mLeSecureConnectionsRandom = in.createByteArray(); } + @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel out, int flags) { - out.writeByteArray(leBluetoothDeviceAddress); - out.writeByteArray(securityManagerTk); - out.writeByteArray(leSecureConnectionsConfirmation); - out.writeByteArray(leSecureConnectionsRandom); + out.writeByteArray(mLeBluetoothDeviceAddress); + out.writeByteArray(mSecurityManagerTk); + out.writeByteArray(mLeSecureConnectionsConfirmation); + out.writeByteArray(mLeSecureConnectionsRandom); } - public static final Parcelable.Creator<OobData> CREATOR - = new Parcelable.Creator<OobData>() { + public static final Parcelable.Creator<OobData> CREATOR = + new Parcelable.Creator<OobData>() { public OobData createFromParcel(Parcel in) { return new OobData(in); } @@ -108,4 +108,4 @@ public class OobData implements Parcelable { return new OobData[size]; } }; -}
\ No newline at end of file +} diff --git a/core/java/android/bluetooth/SdpMasRecord.java b/core/java/android/bluetooth/SdpMasRecord.java index fa164c0fa9d0..72d49380b713 100644 --- a/core/java/android/bluetooth/SdpMasRecord.java +++ b/core/java/android/bluetooth/SdpMasRecord.java @@ -26,38 +26,41 @@ public class SdpMasRecord implements Parcelable { private final int mSupportedFeatures; private final int mSupportedMessageTypes; private final String mServiceName; + + /** Message type */ public static final class MessageType { - public static final int EMAIL = 0x01; - public static final int SMS_GSM = 0x02; + public static final int EMAIL = 0x01; + public static final int SMS_GSM = 0x02; public static final int SMS_CDMA = 0x04; - public static final int MMS = 0x08; + public static final int MMS = 0x08; } - public SdpMasRecord(int mas_instance_id, - int l2cap_psm, - int rfcomm_channel_number, - int profile_version, - int supported_features, - int supported_message_types, - String service_name){ - this.mMasInstanceId = mas_instance_id; - this.mL2capPsm = l2cap_psm; - this.mRfcommChannelNumber = rfcomm_channel_number; - this.mProfileVersion = profile_version; - this.mSupportedFeatures = supported_features; - this.mSupportedMessageTypes = supported_message_types; - this.mServiceName = service_name; + public SdpMasRecord(int masInstanceId, + int l2capPsm, + int rfcommChannelNumber, + int profileVersion, + int supportedFeatures, + int supportedMessageTypes, + String serviceName) { + mMasInstanceId = masInstanceId; + mL2capPsm = l2capPsm; + mRfcommChannelNumber = rfcommChannelNumber; + mProfileVersion = profileVersion; + mSupportedFeatures = supportedFeatures; + mSupportedMessageTypes = supportedMessageTypes; + mServiceName = serviceName; } - public SdpMasRecord(Parcel in){ - this.mMasInstanceId = in.readInt(); - this.mL2capPsm = in.readInt(); - this.mRfcommChannelNumber = in.readInt(); - this.mProfileVersion = in.readInt(); - this.mSupportedFeatures = in.readInt(); - this.mSupportedMessageTypes = in.readInt(); - this.mServiceName = in.readString(); + public SdpMasRecord(Parcel in) { + mMasInstanceId = in.readInt(); + mL2capPsm = in.readInt(); + mRfcommChannelNumber = in.readInt(); + mProfileVersion = in.readInt(); + mSupportedFeatures = in.readInt(); + mSupportedMessageTypes = in.readInt(); + mServiceName = in.readString(); } + @Override public int describeContents() { // TODO Auto-generated method stub @@ -87,50 +90,49 @@ public class SdpMasRecord implements Parcelable { public int getSupportedMessageTypes() { return mSupportedMessageTypes; } - + public boolean msgSupported(int msg) { return (mSupportedMessageTypes & msg) != 0; } - + public String getServiceName() { return mServiceName; } @Override public void writeToParcel(Parcel dest, int flags) { - - dest.writeInt(this.mMasInstanceId); - dest.writeInt(this.mL2capPsm); - dest.writeInt(this.mRfcommChannelNumber); - dest.writeInt(this.mProfileVersion); - dest.writeInt(this.mSupportedFeatures); - dest.writeInt(this.mSupportedMessageTypes); - dest.writeString(this.mServiceName); - + dest.writeInt(mMasInstanceId); + dest.writeInt(mL2capPsm); + dest.writeInt(mRfcommChannelNumber); + dest.writeInt(mProfileVersion); + dest.writeInt(mSupportedFeatures); + dest.writeInt(mSupportedMessageTypes); + dest.writeString(mServiceName); } + @Override - public String toString(){ + public String toString() { String ret = "Bluetooth MAS SDP Record:\n"; - if(mMasInstanceId != -1){ + if (mMasInstanceId != -1) { ret += "Mas Instance Id: " + mMasInstanceId + "\n"; } - if(mRfcommChannelNumber != -1){ + if (mRfcommChannelNumber != -1) { ret += "RFCOMM Chan Number: " + mRfcommChannelNumber + "\n"; } - if(mL2capPsm != -1){ + if (mL2capPsm != -1) { ret += "L2CAP PSM: " + mL2capPsm + "\n"; } - if(mServiceName != null){ + if (mServiceName != null) { ret += "Service Name: " + mServiceName + "\n"; } - if(mProfileVersion != -1){ + if (mProfileVersion != -1) { ret += "Profile version: " + mProfileVersion + "\n"; } - if(mSupportedMessageTypes != -1){ + if (mSupportedMessageTypes != -1) { ret += "Supported msg types: " + mSupportedMessageTypes + "\n"; } - if(mSupportedFeatures != -1){ + if (mSupportedFeatures != -1) { ret += "Supported features: " + mSupportedFeatures + "\n"; } return ret; @@ -140,6 +142,7 @@ public class SdpMasRecord implements Parcelable { public SdpMasRecord createFromParcel(Parcel in) { return new SdpMasRecord(in); } + public SdpRecord[] newArray(int size) { return new SdpRecord[size]; } diff --git a/core/java/android/bluetooth/SdpMnsRecord.java b/core/java/android/bluetooth/SdpMnsRecord.java index c02bb5a18417..a781d5df7dd0 100644 --- a/core/java/android/bluetooth/SdpMnsRecord.java +++ b/core/java/android/bluetooth/SdpMnsRecord.java @@ -25,25 +25,26 @@ public class SdpMnsRecord implements Parcelable { private final int mProfileVersion; private final String mServiceName; - public SdpMnsRecord(int l2cap_psm, - int rfcomm_channel_number, - int profile_version, - int supported_features, - String service_name){ - this.mL2capPsm = l2cap_psm; - this.mRfcommChannelNumber = rfcomm_channel_number; - this.mSupportedFeatures = supported_features; - this.mServiceName = service_name; - this.mProfileVersion = profile_version; + public SdpMnsRecord(int l2capPsm, + int rfcommChannelNumber, + int profileVersion, + int supportedFeatures, + String serviceName) { + mL2capPsm = l2capPsm; + mRfcommChannelNumber = rfcommChannelNumber; + mSupportedFeatures = supportedFeatures; + mServiceName = serviceName; + mProfileVersion = profileVersion; } - public SdpMnsRecord(Parcel in){ - this.mRfcommChannelNumber = in.readInt(); - this.mL2capPsm = in.readInt(); - this.mServiceName = in.readString(); - this.mSupportedFeatures = in.readInt(); - this.mProfileVersion = in.readInt(); + public SdpMnsRecord(Parcel in) { + mRfcommChannelNumber = in.readInt(); + mL2capPsm = in.readInt(); + mServiceName = in.readString(); + mSupportedFeatures = in.readInt(); + mProfileVersion = in.readInt(); } + @Override public int describeContents() { // TODO Auto-generated method stub @@ -80,23 +81,23 @@ public class SdpMnsRecord implements Parcelable { dest.writeInt(mProfileVersion); } - public String toString(){ + public String toString() { String ret = "Bluetooth MNS SDP Record:\n"; - if(mRfcommChannelNumber != -1){ + if (mRfcommChannelNumber != -1) { ret += "RFCOMM Chan Number: " + mRfcommChannelNumber + "\n"; } - if(mL2capPsm != -1){ + if (mL2capPsm != -1) { ret += "L2CAP PSM: " + mL2capPsm + "\n"; } - if(mServiceName != null){ + if (mServiceName != null) { ret += "Service Name: " + mServiceName + "\n"; } - if(mSupportedFeatures != -1){ + if (mSupportedFeatures != -1) { ret += "Supported features: " + mSupportedFeatures + "\n"; } - if(mProfileVersion != -1){ - ret += "Profile_version: " + mProfileVersion+"\n"; + if (mProfileVersion != -1) { + ret += "Profile_version: " + mProfileVersion + "\n"; } return ret; } @@ -105,6 +106,7 @@ public class SdpMnsRecord implements Parcelable { public SdpMnsRecord createFromParcel(Parcel in) { return new SdpMnsRecord(in); } + public SdpMnsRecord[] newArray(int size) { return new SdpMnsRecord[size]; } diff --git a/core/java/android/bluetooth/SdpOppOpsRecord.java b/core/java/android/bluetooth/SdpOppOpsRecord.java index e0e4007a215c..e30745b89821 100644 --- a/core/java/android/bluetooth/SdpOppOpsRecord.java +++ b/core/java/android/bluetooth/SdpOppOpsRecord.java @@ -14,14 +14,15 @@ */ package android.bluetooth; -import java.util.Arrays; - import android.os.Parcel; import android.os.Parcelable; +import java.util.Arrays; + /** * Data representation of a Object Push Profile Server side SDP record. */ + /** @hide */ public class SdpOppOpsRecord implements Parcelable { @@ -34,11 +35,11 @@ public class SdpOppOpsRecord implements Parcelable { public SdpOppOpsRecord(String serviceName, int rfcommChannel, int l2capPsm, int version, byte[] formatsList) { super(); - this.mServiceName = serviceName; - this.mRfcommChannel = rfcommChannel; - this.mL2capPsm = l2capPsm; - this.mProfileVersion = version; - this.mFormatsList = formatsList; + mServiceName = serviceName; + mRfcommChannel = rfcommChannel; + mL2capPsm = l2capPsm; + mProfileVersion = version; + mFormatsList = formatsList; } public String getServiceName() { @@ -67,18 +68,18 @@ public class SdpOppOpsRecord implements Parcelable { return 0; } - public SdpOppOpsRecord(Parcel in){ - this.mRfcommChannel = in.readInt(); - this.mL2capPsm = in.readInt(); - this.mProfileVersion = in.readInt(); - this.mServiceName = in.readString(); + public SdpOppOpsRecord(Parcel in) { + mRfcommChannel = in.readInt(); + mL2capPsm = in.readInt(); + mProfileVersion = in.readInt(); + mServiceName = in.readString(); int arrayLength = in.readInt(); - if(arrayLength > 0) { + if (arrayLength > 0) { byte[] bytes = new byte[arrayLength]; in.readByteArray(bytes); - this.mFormatsList = bytes; + mFormatsList = bytes; } else { - this.mFormatsList = null; + mFormatsList = null; } } @@ -88,7 +89,7 @@ public class SdpOppOpsRecord implements Parcelable { dest.writeInt(mL2capPsm); dest.writeInt(mProfileVersion); dest.writeString(mServiceName); - if(mFormatsList!= null && mFormatsList.length > 0) { + if (mFormatsList != null && mFormatsList.length > 0) { dest.writeInt(mFormatsList.length); dest.writeByteArray(mFormatsList); } else { @@ -96,7 +97,8 @@ public class SdpOppOpsRecord implements Parcelable { } } - public String toString(){ + @Override + public String toString() { StringBuilder sb = new StringBuilder("Bluetooth OPP Server SDP Record:\n"); sb.append(" RFCOMM Chan Number: ").append(mRfcommChannel); sb.append("\n L2CAP PSM: ").append(mL2capPsm); @@ -110,6 +112,7 @@ public class SdpOppOpsRecord implements Parcelable { public SdpOppOpsRecord createFromParcel(Parcel in) { return new SdpOppOpsRecord(in); } + public SdpOppOpsRecord[] newArray(int size) { return new SdpOppOpsRecord[size]; } diff --git a/core/java/android/bluetooth/SdpPseRecord.java b/core/java/android/bluetooth/SdpPseRecord.java index 2c159ccb83c1..72249d0585c6 100644 --- a/core/java/android/bluetooth/SdpPseRecord.java +++ b/core/java/android/bluetooth/SdpPseRecord.java @@ -27,28 +27,29 @@ public class SdpPseRecord implements Parcelable { private final int mSupportedRepositories; private final String mServiceName; - public SdpPseRecord(int l2cap_psm, - int rfcomm_channel_number, - int profile_version, - int supported_features, - int supported_repositories, - String service_name){ - this.mL2capPsm = l2cap_psm; - this.mRfcommChannelNumber = rfcomm_channel_number; - this.mProfileVersion = profile_version; - this.mSupportedFeatures = supported_features; - this.mSupportedRepositories = supported_repositories; - this.mServiceName = service_name; + public SdpPseRecord(int l2capPsm, + int rfcommChannelNumber, + int profileVersion, + int supportedFeatures, + int supportedRepositories, + String serviceName) { + mL2capPsm = l2capPsm; + mRfcommChannelNumber = rfcommChannelNumber; + mProfileVersion = profileVersion; + mSupportedFeatures = supportedFeatures; + mSupportedRepositories = supportedRepositories; + mServiceName = serviceName; } - public SdpPseRecord(Parcel in){ - this.mRfcommChannelNumber = in.readInt(); - this.mL2capPsm = in.readInt(); - this.mProfileVersion = in.readInt(); - this.mSupportedFeatures = in.readInt(); - this.mSupportedRepositories = in.readInt(); - this.mServiceName = in.readString(); + public SdpPseRecord(Parcel in) { + mRfcommChannelNumber = in.readInt(); + mL2capPsm = in.readInt(); + mProfileVersion = in.readInt(); + mSupportedFeatures = in.readInt(); + mSupportedRepositories = in.readInt(); + mServiceName = in.readString(); } + @Override public int describeContents() { // TODO Auto-generated method stub @@ -78,6 +79,7 @@ public class SdpPseRecord implements Parcelable { public int getSupportedRepositories() { return mSupportedRepositories; } + @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mRfcommChannelNumber); @@ -89,25 +91,26 @@ public class SdpPseRecord implements Parcelable { } - public String toString(){ + @Override + public String toString() { String ret = "Bluetooth MNS SDP Record:\n"; - if(mRfcommChannelNumber != -1){ + if (mRfcommChannelNumber != -1) { ret += "RFCOMM Chan Number: " + mRfcommChannelNumber + "\n"; } - if(mL2capPsm != -1){ + if (mL2capPsm != -1) { ret += "L2CAP PSM: " + mL2capPsm + "\n"; } - if(mProfileVersion != -1){ + if (mProfileVersion != -1) { ret += "profile version: " + mProfileVersion + "\n"; } - if(mServiceName != null){ + if (mServiceName != null) { ret += "Service Name: " + mServiceName + "\n"; } - if(mSupportedFeatures != -1){ + if (mSupportedFeatures != -1) { ret += "Supported features: " + mSupportedFeatures + "\n"; } - if(mSupportedRepositories != -1){ + if (mSupportedRepositories != -1) { ret += "Supported repositories: " + mSupportedRepositories + "\n"; } @@ -118,6 +121,7 @@ public class SdpPseRecord implements Parcelable { public SdpPseRecord createFromParcel(Parcel in) { return new SdpPseRecord(in); } + public SdpPseRecord[] newArray(int size) { return new SdpPseRecord[size]; } diff --git a/core/java/android/bluetooth/SdpRecord.java b/core/java/android/bluetooth/SdpRecord.java index 6f1065e38d26..730862ec6f91 100644 --- a/core/java/android/bluetooth/SdpRecord.java +++ b/core/java/android/bluetooth/SdpRecord.java @@ -21,7 +21,7 @@ import android.os.Parcelable; import java.util.Arrays; /** @hide */ -public class SdpRecord implements Parcelable{ +public class SdpRecord implements Parcelable { private final byte[] mRawData; private final int mRawSize; @@ -32,15 +32,15 @@ public class SdpRecord implements Parcelable{ + ", rawSize=" + mRawSize + "]"; } - public SdpRecord(int size_record, byte[] record){ - this.mRawData = record; - this.mRawSize = size_record; + public SdpRecord(int sizeRecord, byte[] record) { + mRawData = record; + mRawSize = sizeRecord; } - public SdpRecord(Parcel in){ - this.mRawSize = in.readInt(); - this.mRawData = new byte[mRawSize]; - in.readByteArray(this.mRawData); + public SdpRecord(Parcel in) { + mRawSize = in.readInt(); + mRawData = new byte[mRawSize]; + in.readByteArray(mRawData); } @@ -51,11 +51,12 @@ public class SdpRecord implements Parcelable{ @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(this.mRawSize); - dest.writeByteArray(this.mRawData); + dest.writeInt(mRawSize); + dest.writeByteArray(mRawData); } + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { public SdpRecord createFromParcel(Parcel in) { return new SdpRecord(in); diff --git a/core/java/android/bluetooth/SdpSapsRecord.java b/core/java/android/bluetooth/SdpSapsRecord.java index 84a29b92c00c..a1e2f7b51f35 100644 --- a/core/java/android/bluetooth/SdpSapsRecord.java +++ b/core/java/android/bluetooth/SdpSapsRecord.java @@ -25,23 +25,21 @@ public class SdpSapsRecord implements Parcelable { private final int mProfileVersion; private final String mServiceName; - public SdpSapsRecord(int rfcomm_channel_number, - int profile_version, - String service_name) { - this.mRfcommChannelNumber = rfcomm_channel_number; - this.mProfileVersion = profile_version; - this.mServiceName = service_name; + public SdpSapsRecord(int rfcommChannelNumber, int profileVersion, String serviceName) { + mRfcommChannelNumber = rfcommChannelNumber; + mProfileVersion = profileVersion; + mServiceName = serviceName; } public SdpSapsRecord(Parcel in) { - this.mRfcommChannelNumber = in.readInt(); - this.mProfileVersion = in.readInt(); - this.mServiceName = in.readString(); + mRfcommChannelNumber = in.readInt(); + mProfileVersion = in.readInt(); + mServiceName = in.readString(); } @Override public int describeContents() { - return 0; + return 0; } public int getRfcommCannelNumber() { @@ -58,9 +56,9 @@ public class SdpSapsRecord implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(this.mRfcommChannelNumber); - dest.writeInt(this.mProfileVersion); - dest.writeString(this.mServiceName); + dest.writeInt(mRfcommChannelNumber); + dest.writeInt(mProfileVersion); + dest.writeString(mServiceName); } @@ -84,6 +82,7 @@ public class SdpSapsRecord implements Parcelable { public SdpSapsRecord createFromParcel(Parcel in) { return new SdpSapsRecord(in); } + public SdpRecord[] newArray(int size) { return new SdpRecord[size]; } diff --git a/core/java/android/bluetooth/UidTraffic.java b/core/java/android/bluetooth/UidTraffic.java index 78013cc0cb02..cef362b3b573 100644 --- a/core/java/android/bluetooth/UidTraffic.java +++ b/core/java/android/bluetooth/UidTraffic.java @@ -20,6 +20,7 @@ import android.os.Parcelable; /** * Record of data traffic (in bytes) by an application identified by its UID. + * * @hide */ public class UidTraffic implements Cloneable, Parcelable { @@ -90,11 +91,8 @@ public class UidTraffic implements Cloneable, Parcelable { @Override public String toString() { - return "UidTraffic{" + - "mAppUid=" + mAppUid + - ", mRxBytes=" + mRxBytes + - ", mTxBytes=" + mTxBytes + - '}'; + return "UidTraffic{mAppUid=" + mAppUid + ", mRxBytes=" + mRxBytes + ", mTxBytes=" + + mTxBytes + '}'; } public static final Creator<UidTraffic> CREATOR = new Creator<UidTraffic>() { diff --git a/core/java/android/bluetooth/le/AdvertiseCallback.java b/core/java/android/bluetooth/le/AdvertiseCallback.java index 706f469dab0a..4fa8c4f2f539 100644 --- a/core/java/android/bluetooth/le/AdvertiseCallback.java +++ b/core/java/android/bluetooth/le/AdvertiseCallback.java @@ -58,7 +58,7 @@ public abstract class AdvertiseCallback { * that the advertising has been started successfully. * * @param settingsInEffect The actual settings used for advertising, which may be different from - * what has been requested. + * what has been requested. */ public void onStartSuccess(AdvertiseSettings settingsInEffect) { } @@ -67,7 +67,7 @@ public abstract class AdvertiseCallback { * Callback when advertising could not be started. * * @param errorCode Error code (see ADVERTISE_FAILED_* constants) for advertising start - * failures. + * failures. */ public void onStartFailure(int errorCode) { } diff --git a/core/java/android/bluetooth/le/AdvertiseData.java b/core/java/android/bluetooth/le/AdvertiseData.java index bde2d2f890f5..b65c31d1dcf7 100644 --- a/core/java/android/bluetooth/le/AdvertiseData.java +++ b/core/java/android/bluetooth/le/AdvertiseData.java @@ -118,11 +118,12 @@ public final class AdvertiseData implements Parcelable { return false; } AdvertiseData other = (AdvertiseData) obj; - return Objects.equals(mServiceUuids, other.mServiceUuids) && - BluetoothLeUtils.equals(mManufacturerSpecificData, other.mManufacturerSpecificData) && - BluetoothLeUtils.equals(mServiceData, other.mServiceData) && - mIncludeDeviceName == other.mIncludeDeviceName && - mIncludeTxPowerLevel == other.mIncludeTxPowerLevel; + return Objects.equals(mServiceUuids, other.mServiceUuids) + && BluetoothLeUtils.equals(mManufacturerSpecificData, + other.mManufacturerSpecificData) + && BluetoothLeUtils.equals(mServiceData, other.mServiceData) + && mIncludeDeviceName == other.mIncludeDeviceName + && mIncludeTxPowerLevel == other.mIncludeTxPowerLevel; } @Override @@ -160,12 +161,12 @@ public final class AdvertiseData implements Parcelable { public static final Parcelable.Creator<AdvertiseData> CREATOR = new Creator<AdvertiseData>() { - @Override + @Override public AdvertiseData[] newArray(int size) { return new AdvertiseData[size]; } - @Override + @Override public AdvertiseData createFromParcel(Parcel in) { Builder builder = new Builder(); ArrayList<ParcelUuid> uuids = in.createTypedArrayList(ParcelUuid.CREATOR); @@ -222,7 +223,7 @@ public final class AdvertiseData implements Parcelable { * @param serviceDataUuid 16-bit UUID of the service the data is associated with * @param serviceData Service data * @throws IllegalArgumentException If the {@code serviceDataUuid} or {@code serviceData} is - * empty. + * empty. */ public Builder addServiceData(ParcelUuid serviceDataUuid, byte[] serviceData) { if (serviceDataUuid == null || serviceData == null) { @@ -242,8 +243,8 @@ public final class AdvertiseData implements Parcelable { * * @param manufacturerId Manufacturer ID assigned by Bluetooth SIG. * @param manufacturerSpecificData Manufacturer specific data - * @throws IllegalArgumentException If the {@code manufacturerId} is negative or - * {@code manufacturerSpecificData} is null. + * @throws IllegalArgumentException If the {@code manufacturerId} is negative or {@code + * manufacturerSpecificData} is null. */ public Builder addManufacturerData(int manufacturerId, byte[] manufacturerSpecificData) { if (manufacturerId < 0) { diff --git a/core/java/android/bluetooth/le/AdvertiseSettings.java b/core/java/android/bluetooth/le/AdvertiseSettings.java index 62c68a45eb0e..35e232c7500b 100644 --- a/core/java/android/bluetooth/le/AdvertiseSettings.java +++ b/core/java/android/bluetooth/le/AdvertiseSettings.java @@ -86,7 +86,7 @@ public final class AdvertiseSettings implements Parcelable { private AdvertiseSettings(Parcel in) { mAdvertiseMode = in.readInt(); mAdvertiseTxPowerLevel = in.readInt(); - mAdvertiseConnectable = in.readInt() != 0 ? true : false; + mAdvertiseConnectable = in.readInt() != 0; mAdvertiseTimeoutMillis = in.readInt(); } @@ -121,9 +121,9 @@ public final class AdvertiseSettings implements Parcelable { @Override public String toString() { return "Settings [mAdvertiseMode=" + mAdvertiseMode - + ", mAdvertiseTxPowerLevel=" + mAdvertiseTxPowerLevel - + ", mAdvertiseConnectable=" + mAdvertiseConnectable - + ", mAdvertiseTimeoutMillis=" + mAdvertiseTimeoutMillis + "]"; + + ", mAdvertiseTxPowerLevel=" + mAdvertiseTxPowerLevel + + ", mAdvertiseConnectable=" + mAdvertiseConnectable + + ", mAdvertiseTimeoutMillis=" + mAdvertiseTimeoutMillis + "]"; } @Override @@ -141,12 +141,12 @@ public final class AdvertiseSettings implements Parcelable { public static final Parcelable.Creator<AdvertiseSettings> CREATOR = new Creator<AdvertiseSettings>() { - @Override + @Override public AdvertiseSettings[] newArray(int size) { return new AdvertiseSettings[size]; } - @Override + @Override public AdvertiseSettings createFromParcel(Parcel in) { return new AdvertiseSettings(in); } @@ -164,10 +164,10 @@ public final class AdvertiseSettings implements Parcelable { /** * Set advertise mode to control the advertising power and latency. * - * @param advertiseMode Bluetooth LE Advertising mode, can only be one of - * {@link AdvertiseSettings#ADVERTISE_MODE_LOW_POWER}, - * {@link AdvertiseSettings#ADVERTISE_MODE_BALANCED}, or - * {@link AdvertiseSettings#ADVERTISE_MODE_LOW_LATENCY}. + * @param advertiseMode Bluetooth LE Advertising mode, can only be one of {@link + * AdvertiseSettings#ADVERTISE_MODE_LOW_POWER}, + * {@link AdvertiseSettings#ADVERTISE_MODE_BALANCED}, + * or {@link AdvertiseSettings#ADVERTISE_MODE_LOW_LATENCY}. * @throws IllegalArgumentException If the advertiseMode is invalid. */ public Builder setAdvertiseMode(int advertiseMode) { @@ -183,10 +183,10 @@ public final class AdvertiseSettings implements Parcelable { * Set advertise TX power level to control the transmission power level for the advertising. * * @param txPowerLevel Transmission power of Bluetooth LE Advertising, can only be one of - * {@link AdvertiseSettings#ADVERTISE_TX_POWER_ULTRA_LOW}, - * {@link AdvertiseSettings#ADVERTISE_TX_POWER_LOW}, - * {@link AdvertiseSettings#ADVERTISE_TX_POWER_MEDIUM} or - * {@link AdvertiseSettings#ADVERTISE_TX_POWER_HIGH}. + * {@link AdvertiseSettings#ADVERTISE_TX_POWER_ULTRA_LOW}, {@link + * AdvertiseSettings#ADVERTISE_TX_POWER_LOW}, + * {@link AdvertiseSettings#ADVERTISE_TX_POWER_MEDIUM} + * or {@link AdvertiseSettings#ADVERTISE_TX_POWER_HIGH}. * @throws IllegalArgumentException If the {@code txPowerLevel} is invalid. */ public Builder setTxPowerLevel(int txPowerLevel) { @@ -201,8 +201,8 @@ public final class AdvertiseSettings implements Parcelable { /** * Set whether the advertisement type should be connectable or non-connectable. * - * @param connectable Controls whether the advertisment type will be connectable (true) - * or non-connectable (false). + * @param connectable Controls whether the advertisment type will be connectable (true) or + * non-connectable (false). */ public Builder setConnectable(boolean connectable) { mConnectable = connectable; @@ -211,14 +211,15 @@ public final class AdvertiseSettings implements Parcelable { /** * Limit advertising to a given amount of time. - * @param timeoutMillis Advertising time limit. May not exceed 180000 milliseconds. - * A value of 0 will disable the time limit. + * + * @param timeoutMillis Advertising time limit. May not exceed 180000 milliseconds. A value + * of 0 will disable the time limit. * @throws IllegalArgumentException If the provided timeout is over 180000 ms. */ public Builder setTimeout(int timeoutMillis) { if (timeoutMillis < 0 || timeoutMillis > LIMITED_ADVERTISING_MAX_MILLIS) { throw new IllegalArgumentException("timeoutMillis invalid (must be 0-" - + LIMITED_ADVERTISING_MAX_MILLIS + " milliseconds)"); + + LIMITED_ADVERTISING_MAX_MILLIS + " milliseconds)"); } mTimeoutMillis = timeoutMillis; return this; diff --git a/core/java/android/bluetooth/le/AdvertisingSet.java b/core/java/android/bluetooth/le/AdvertisingSet.java index 1bc211cb83a2..1df35e1e382f 100644 --- a/core/java/android/bluetooth/le/AdvertisingSet.java +++ b/core/java/android/bluetooth/le/AdvertisingSet.java @@ -19,7 +19,6 @@ package android.bluetooth.le; import android.bluetooth.BluetoothAdapter; import android.bluetooth.IBluetoothGatt; import android.bluetooth.IBluetoothManager; -import android.bluetooth.le.IAdvertisingSetCallback; import android.os.RemoteException; import android.util.Log; @@ -37,23 +36,23 @@ import android.util.Log; public final class AdvertisingSet { private static final String TAG = "AdvertisingSet"; - private final IBluetoothGatt gatt; - private int advertiserId; + private final IBluetoothGatt mGatt; + private int mAdvertiserId; /* package */ AdvertisingSet(int advertiserId, - IBluetoothManager bluetoothManager) { - this.advertiserId = advertiserId; + IBluetoothManager bluetoothManager) { + mAdvertiserId = advertiserId; try { - this.gatt = bluetoothManager.getBluetoothGatt(); + mGatt = bluetoothManager.getBluetoothGatt(); } catch (RemoteException e) { - Log.e(TAG, "Failed to get Bluetooth gatt - ", e); - throw new IllegalStateException("Failed to get Bluetooth"); + Log.e(TAG, "Failed to get Bluetooth gatt - ", e); + throw new IllegalStateException("Failed to get Bluetooth"); } } /* package */ void setAdvertiserId(int advertiserId) { - this.advertiserId = advertiserId; + mAdvertiserId = advertiserId; } /** @@ -63,18 +62,17 @@ public final class AdvertisingSet { * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} * * @param enable whether the advertising should be enabled (true), or disabled (false) - * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to - * 65535 (655,350 ms) + * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to 65535 + * (655,350 ms) * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the - * controller shall attempt to send prior to terminating the extended - * advertising, even if the duration has not expired. Valid range is - * from 1 to 255. + * controller shall attempt to send prior to terminating the extended advertising, even if the + * duration has not expired. Valid range is from 1 to 255. */ public void enableAdvertising(boolean enable, int duration, int maxExtendedAdvertisingEvents) { try { - gatt.enableAdvertisingSet(this.advertiserId, enable, duration, - maxExtendedAdvertisingEvents); + mGatt.enableAdvertisingSet(mAdvertiserId, enable, duration, + maxExtendedAdvertisingEvents); } catch (RemoteException e) { Log.e(TAG, "remote exception - ", e); } @@ -87,15 +85,14 @@ public final class AdvertisingSet { * <p> * Advertising data must be empty if non-legacy scannable advertising is used. * - * @param advertiseData Advertisement data to be broadcasted. Size must not exceed - * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the - * advertisement is connectable, three bytes will be added for flags. If the - * update takes place when the advertising set is enabled, the data can be - * maximum 251 bytes long. + * @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link + * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable, + * three bytes will be added for flags. If the update takes place when the advertising set is + * enabled, the data can be maximum 251 bytes long. */ public void setAdvertisingData(AdvertiseData advertiseData) { try { - gatt.setAdvertisingData(this.advertiserId, advertiseData); + mGatt.setAdvertisingData(mAdvertiserId, advertiseData); } catch (RemoteException e) { Log.e(TAG, "remote exception - ", e); } @@ -107,13 +104,12 @@ public final class AdvertisingSet { * is delivered through {@code callback.onScanResponseDataSet()}. * * @param scanResponse Scan response associated with the advertisement data. Size must not - * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the - * update takes place when the advertising set is enabled, the data can be - * maximum 251 bytes long. + * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the update takes place + * when the advertising set is enabled, the data can be maximum 251 bytes long. */ public void setScanResponseData(AdvertiseData scanResponse) { try { - gatt.setScanResponseData(this.advertiserId, scanResponse); + mGatt.setScanResponseData(mAdvertiserId, scanResponse); } catch (RemoteException e) { Log.e(TAG, "remote exception - ", e); } @@ -128,7 +124,7 @@ public final class AdvertisingSet { */ public void setAdvertisingParameters(AdvertisingSetParameters parameters) { try { - gatt.setAdvertisingParameters(this.advertiserId, parameters); + mGatt.setAdvertisingParameters(mAdvertiserId, parameters); } catch (RemoteException e) { Log.e(TAG, "remote exception - ", e); } @@ -141,7 +137,7 @@ public final class AdvertisingSet { */ public void setPeriodicAdvertisingParameters(PeriodicAdvertisingParameters parameters) { try { - gatt.setPeriodicAdvertisingParameters(this.advertiserId, parameters); + mGatt.setPeriodicAdvertisingParameters(mAdvertiserId, parameters); } catch (RemoteException e) { Log.e(TAG, "remote exception - ", e); } @@ -153,14 +149,13 @@ public final class AdvertisingSet { * immediately, the operation status is delivered through * {@code callback.onPeriodicAdvertisingDataSet()}. * - * @param periodicData Periodic advertising data. Size must not exceed - * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the - * update takes place when the periodic advertising is enabled for this set, - * the data can be maximum 251 bytes long. + * @param periodicData Periodic advertising data. Size must not exceed {@link + * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the update takes place when the + * periodic advertising is enabled for this set, the data can be maximum 251 bytes long. */ public void setPeriodicAdvertisingData(AdvertiseData periodicData) { try { - gatt.setPeriodicAdvertisingData(this.advertiserId, periodicData); + mGatt.setPeriodicAdvertisingData(mAdvertiserId, periodicData); } catch (RemoteException e) { Log.e(TAG, "remote exception - ", e); } @@ -170,11 +165,12 @@ public final class AdvertisingSet { * Used to enable/disable periodic advertising. This method returns immediately, the operation * status is delivered through {@code callback.onPeriodicAdvertisingEnable()}. * - * @param enable whether the periodic advertising should be enabled (true), or disabled (false). + * @param enable whether the periodic advertising should be enabled (true), or disabled + * (false). */ public void setPeriodicAdvertisingEnabled(boolean enable) { try { - gatt.setPeriodicAdvertisingEnable(this.advertiserId, enable); + mGatt.setPeriodicAdvertisingEnable(mAdvertiserId, enable); } catch (RemoteException e) { Log.e(TAG, "remote exception - ", e); } @@ -186,11 +182,12 @@ public final class AdvertisingSet { * should ever use it. * * This method requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission. + * * @hide */ - public void getOwnAddress(){ + public void getOwnAddress() { try { - gatt.getOwnAddress(this.advertiserId); + mGatt.getOwnAddress(mAdvertiserId); } catch (RemoteException e) { Log.e(TAG, "remote exception - ", e); } @@ -201,7 +198,7 @@ public final class AdvertisingSet { * * @hide */ - public int getAdvertiserId(){ - return advertiserId; + public int getAdvertiserId() { + return mAdvertiserId; } -}
\ No newline at end of file +} diff --git a/core/java/android/bluetooth/le/AdvertisingSetCallback.java b/core/java/android/bluetooth/le/AdvertisingSetCallback.java index c3c16a479e71..58a3696fc092 100644 --- a/core/java/android/bluetooth/le/AdvertisingSetCallback.java +++ b/core/java/android/bluetooth/le/AdvertisingSetCallback.java @@ -16,8 +16,6 @@ package android.bluetooth.le; -import android.bluetooth.BluetoothDevice; - /** * Bluetooth LE advertising set callbacks, used to deliver advertising operation * status. @@ -65,7 +63,8 @@ public abstract class AdvertisingSetCallback { * @param txPower tx power that will be used for this set. * @param status Status of the operation. */ - public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower, int status) {} + public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower, int status) { + } /** * Callback triggered in response to {@link BluetoothLeAdvertiser#stopAdvertisingSet} @@ -73,16 +72,19 @@ public abstract class AdvertisingSetCallback { * * @param advertisingSet The advertising set. */ - public void onAdvertisingSetStopped(AdvertisingSet advertisingSet) {} + public void onAdvertisingSetStopped(AdvertisingSet advertisingSet) { + } /** - * Callback triggered in response to {@link BluetoothLeAdvertiser#startAdvertisingSet} indicating - * result of the operation. If status is ADVERTISE_SUCCESS, then advertising set is advertising. + * Callback triggered in response to {@link BluetoothLeAdvertiser#startAdvertisingSet} + * indicating result of the operation. If status is ADVERTISE_SUCCESS, then advertising set is + * advertising. * * @param advertisingSet The advertising set. * @param status Status of the operation. */ - public void onAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enable, int status) {} + public void onAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enable, int status) { + } /** * Callback triggered in response to {@link AdvertisingSet#setAdvertisingData} indicating @@ -91,7 +93,8 @@ public abstract class AdvertisingSetCallback { * @param advertisingSet The advertising set. * @param status Status of the operation. */ - public void onAdvertisingDataSet(AdvertisingSet advertisingSet, int status) {} + public void onAdvertisingDataSet(AdvertisingSet advertisingSet, int status) { + } /** * Callback triggered in response to {@link AdvertisingSet#setAdvertisingData} indicating @@ -100,7 +103,8 @@ public abstract class AdvertisingSetCallback { * @param advertisingSet The advertising set. * @param status Status of the operation. */ - public void onScanResponseDataSet(AdvertisingSet advertisingSet, int status) {} + public void onScanResponseDataSet(AdvertisingSet advertisingSet, int status) { + } /** * Callback triggered in response to {@link AdvertisingSet#setAdvertisingParameters} @@ -111,7 +115,8 @@ public abstract class AdvertisingSetCallback { * @param status Status of the operation. */ public void onAdvertisingParametersUpdated(AdvertisingSet advertisingSet, - int txPower, int status) {} + int txPower, int status) { + } /** * Callback triggered in response to {@link AdvertisingSet#setPeriodicAdvertisingParameters} @@ -120,9 +125,8 @@ public abstract class AdvertisingSetCallback { * @param advertisingSet The advertising set. * @param status Status of the operation. */ - public void - onPeriodicAdvertisingParametersUpdated(AdvertisingSet advertisingSet, - int status) {} + public void onPeriodicAdvertisingParametersUpdated(AdvertisingSet advertisingSet, int status) { + } /** * Callback triggered in response to {@link AdvertisingSet#setPeriodicAdvertisingData} @@ -132,7 +136,8 @@ public abstract class AdvertisingSetCallback { * @param status Status of the operation. */ public void onPeriodicAdvertisingDataSet(AdvertisingSet advertisingSet, - int status) {} + int status) { + } /** * Callback triggered in response to {@link AdvertisingSet#setPeriodicAdvertisingEnabled} @@ -142,7 +147,8 @@ public abstract class AdvertisingSetCallback { * @param status Status of the operation. */ public void onPeriodicAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enable, - int status) {} + int status) { + } /** * Callback triggered in response to {@link AdvertisingSet#getOwnAddress()} @@ -153,5 +159,6 @@ public abstract class AdvertisingSetCallback { * @param address advertising set bluetooth address. * @hide */ - public void onOwnAddressRead(AdvertisingSet advertisingSet, int addressType, String address) {} -}
\ No newline at end of file + public void onOwnAddressRead(AdvertisingSet advertisingSet, int addressType, String address) { + } +} diff --git a/core/java/android/bluetooth/le/AdvertisingSetParameters.java b/core/java/android/bluetooth/le/AdvertisingSetParameters.java index e9747d8205bf..0c0291eb0ed3 100644 --- a/core/java/android/bluetooth/le/AdvertisingSetParameters.java +++ b/core/java/android/bluetooth/le/AdvertisingSetParameters.java @@ -31,9 +31,9 @@ import android.os.Parcelable; public final class AdvertisingSetParameters implements Parcelable { /** - * Advertise on low frequency, around every 1000ms. This is the default and - * preferred advertising mode as it consumes the least power. - */ + * Advertise on low frequency, around every 1000ms. This is the default and + * preferred advertising mode as it consumes the least power. + */ public static final int INTERVAL_HIGH = 1600; /** @@ -97,156 +97,174 @@ public final class AdvertisingSetParameters implements Parcelable { */ private static final int LIMITED_ADVERTISING_MAX_MILLIS = 180 * 1000; - private final boolean isLegacy; - private final boolean isAnonymous; - private final boolean includeTxPower; - private final int primaryPhy; - private final int secondaryPhy; - private final boolean connectable; - private final boolean scannable; - private final int interval; - private final int txPowerLevel; + private final boolean mIsLegacy; + private final boolean mIsAnonymous; + private final boolean mIncludeTxPower; + private final int mPrimaryPhy; + private final int mSecondaryPhy; + private final boolean mConnectable; + private final boolean mScannable; + private final int mInterval; + private final int mTxPowerLevel; private AdvertisingSetParameters(boolean connectable, boolean scannable, boolean isLegacy, - boolean isAnonymous, boolean includeTxPower, - int primaryPhy, int secondaryPhy, - int interval, int txPowerLevel) { - this.connectable = connectable; - this.scannable = scannable; - this.isLegacy = isLegacy; - this.isAnonymous = isAnonymous; - this.includeTxPower = includeTxPower; - this.primaryPhy = primaryPhy; - this.secondaryPhy = secondaryPhy; - this.interval = interval; - this.txPowerLevel = txPowerLevel; + boolean isAnonymous, boolean includeTxPower, + int primaryPhy, int secondaryPhy, + int interval, int txPowerLevel) { + mConnectable = connectable; + mScannable = scannable; + mIsLegacy = isLegacy; + mIsAnonymous = isAnonymous; + mIncludeTxPower = includeTxPower; + mPrimaryPhy = primaryPhy; + mSecondaryPhy = secondaryPhy; + mInterval = interval; + mTxPowerLevel = txPowerLevel; } private AdvertisingSetParameters(Parcel in) { - connectable = in.readInt() != 0 ? true : false; - scannable = in.readInt() != 0 ? true : false; - isLegacy = in.readInt() != 0 ? true : false; - isAnonymous = in.readInt() != 0 ? true : false; - includeTxPower = in.readInt() != 0 ? true : false; - primaryPhy = in.readInt(); - secondaryPhy = in.readInt(); - interval = in.readInt(); - txPowerLevel = in.readInt(); + mConnectable = in.readInt() != 0; + mScannable = in.readInt() != 0; + mIsLegacy = in.readInt() != 0; + mIsAnonymous = in.readInt() != 0; + mIncludeTxPower = in.readInt() != 0; + mPrimaryPhy = in.readInt(); + mSecondaryPhy = in.readInt(); + mInterval = in.readInt(); + mTxPowerLevel = in.readInt(); } /** * Returns whether the advertisement will be connectable. */ - public boolean isConnectable() { return connectable; } + public boolean isConnectable() { + return mConnectable; + } /** * Returns whether the advertisement will be scannable. */ - public boolean isScannable() { return scannable; } + public boolean isScannable() { + return mScannable; + } /** * Returns whether the legacy advertisement will be used. */ - public boolean isLegacy() { return isLegacy; } + public boolean isLegacy() { + return mIsLegacy; + } /** * Returns whether the advertisement will be anonymous. */ - public boolean isAnonymous() { return isAnonymous; } + public boolean isAnonymous() { + return mIsAnonymous; + } /** * Returns whether the TX Power will be included. */ - public boolean includeTxPower() { return includeTxPower; } + public boolean includeTxPower() { + return mIncludeTxPower; + } /** * Returns the primary advertising phy. */ - public int getPrimaryPhy() { return primaryPhy; } + public int getPrimaryPhy() { + return mPrimaryPhy; + } /** * Returns the secondary advertising phy. */ - public int getSecondaryPhy() { return secondaryPhy; } + public int getSecondaryPhy() { + return mSecondaryPhy; + } /** * Returns the advertising interval. */ - public int getInterval() { return interval; } + public int getInterval() { + return mInterval; + } /** * Returns the TX power level for advertising. */ - public int getTxPowerLevel() { return txPowerLevel; } + public int getTxPowerLevel() { + return mTxPowerLevel; + } @Override public String toString() { - return "AdvertisingSetParameters [connectable=" + connectable - + ", isLegacy=" + isLegacy - + ", isAnonymous=" + isAnonymous - + ", includeTxPower=" + includeTxPower - + ", primaryPhy=" + primaryPhy - + ", secondaryPhy=" + secondaryPhy - + ", interval=" + interval - + ", txPowerLevel=" + txPowerLevel + "]"; + return "AdvertisingSetParameters [connectable=" + mConnectable + + ", isLegacy=" + mIsLegacy + + ", isAnonymous=" + mIsAnonymous + + ", includeTxPower=" + mIncludeTxPower + + ", primaryPhy=" + mPrimaryPhy + + ", secondaryPhy=" + mSecondaryPhy + + ", interval=" + mInterval + + ", txPowerLevel=" + mTxPowerLevel + "]"; } @Override public int describeContents() { - return 0; + return 0; } @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(connectable ? 1 : 0); - dest.writeInt(scannable ? 1 : 0); - dest.writeInt(isLegacy ? 1 : 0); - dest.writeInt(isAnonymous ? 1 : 0); - dest.writeInt(includeTxPower ? 1 : 0); - dest.writeInt(primaryPhy); - dest.writeInt(secondaryPhy); - dest.writeInt(interval); - dest.writeInt(txPowerLevel); + dest.writeInt(mConnectable ? 1 : 0); + dest.writeInt(mScannable ? 1 : 0); + dest.writeInt(mIsLegacy ? 1 : 0); + dest.writeInt(mIsAnonymous ? 1 : 0); + dest.writeInt(mIncludeTxPower ? 1 : 0); + dest.writeInt(mPrimaryPhy); + dest.writeInt(mSecondaryPhy); + dest.writeInt(mInterval); + dest.writeInt(mTxPowerLevel); } public static final Parcelable.Creator<AdvertisingSetParameters> CREATOR = - new Creator<AdvertisingSetParameters>() { - @Override - public AdvertisingSetParameters[] newArray(int size) { - return new AdvertisingSetParameters[size]; - } - - @Override - public AdvertisingSetParameters createFromParcel(Parcel in) { - return new AdvertisingSetParameters(in); - } - }; + new Creator<AdvertisingSetParameters>() { + @Override + public AdvertisingSetParameters[] newArray(int size) { + return new AdvertisingSetParameters[size]; + } + + @Override + public AdvertisingSetParameters createFromParcel(Parcel in) { + return new AdvertisingSetParameters(in); + } + }; /** * Builder class for {@link AdvertisingSetParameters}. */ public static final class Builder { - - private boolean connectable = false; - private boolean scannable = false; - private boolean isLegacy = false; - private boolean isAnonymous = false; - private boolean includeTxPower = false; - private int primaryPhy = BluetoothDevice.PHY_LE_1M; - private int secondaryPhy = BluetoothDevice.PHY_LE_1M; - private int interval = INTERVAL_LOW; - private int txPowerLevel = TX_POWER_MEDIUM; + private boolean mConnectable = false; + private boolean mScannable = false; + private boolean mIsLegacy = false; + private boolean mIsAnonymous = false; + private boolean mIncludeTxPower = false; + private int mPrimaryPhy = BluetoothDevice.PHY_LE_1M; + private int mSecondaryPhy = BluetoothDevice.PHY_LE_1M; + private int mInterval = INTERVAL_LOW; + private int mTxPowerLevel = TX_POWER_MEDIUM; /** * Set whether the advertisement type should be connectable or * non-connectable. * Legacy advertisements can be both connectable and scannable. Non-legacy * advertisements can be only scannable or only connectable. - * @param connectable Controls whether the advertisement type will be - * connectable (true) or non-connectable (false). + * + * @param connectable Controls whether the advertisement type will be connectable (true) or + * non-connectable (false). */ public Builder setConnectable(boolean connectable) { - this.connectable = connectable; + mConnectable = connectable; return this; } @@ -254,11 +272,12 @@ public final class AdvertisingSetParameters implements Parcelable { * Set whether the advertisement type should be scannable. * Legacy advertisements can be both connectable and scannable. Non-legacy * advertisements can be only scannable or only connectable. - * @param scannable Controls whether the advertisement type will be - * scannable (true) or non-scannable (false). + * + * @param scannable Controls whether the advertisement type will be scannable (true) or + * non-scannable (false). */ public Builder setScannable(boolean scannable) { - this.scannable = scannable; + mScannable = scannable; return this; } @@ -269,7 +288,7 @@ public final class AdvertisingSetParameters implements Parcelable { * @param isLegacy whether legacy advertising mode should be used. */ public Builder setLegacyMode(boolean isLegacy) { - this.isLegacy = isLegacy; + mIsLegacy = isLegacy; return this; } @@ -282,7 +301,7 @@ public final class AdvertisingSetParameters implements Parcelable { * @param isAnonymous whether anonymous advertising should be used. */ public Builder setAnonymous(boolean isAnonymous) { - this.isAnonymous = isAnonymous; + mIsAnonymous = isAnonymous; return this; } @@ -291,11 +310,10 @@ public final class AdvertisingSetParameters implements Parcelable { * * This is used only if legacy mode is not used. * - * @param includeTxPower whether TX power should be included in extended - * header + * @param includeTxPower whether TX power should be included in extended header */ public Builder setIncludeTxPower(boolean includeTxPower) { - this.includeTxPower = includeTxPower; + mIncludeTxPower = includeTxPower; return this; } @@ -306,17 +324,17 @@ public final class AdvertisingSetParameters implements Parcelable { * * Use {@link BluetoothAdapter#isLeCodedPhySupported} to determine if LE Coded PHY is * supported on this device. - * @param primaryPhy Primary advertising physical channel, can only be - * {@link BluetoothDevice#PHY_LE_1M} or - * {@link BluetoothDevice#PHY_LE_CODED}. + * + * @param primaryPhy Primary advertising physical channel, can only be {@link + * BluetoothDevice#PHY_LE_1M} or {@link BluetoothDevice#PHY_LE_CODED}. * @throws IllegalArgumentException If the primaryPhy is invalid. */ public Builder setPrimaryPhy(int primaryPhy) { - if (primaryPhy != BluetoothDevice.PHY_LE_1M && - primaryPhy != BluetoothDevice.PHY_LE_CODED) { - throw new IllegalArgumentException("bad primaryPhy " + primaryPhy); + if (primaryPhy != BluetoothDevice.PHY_LE_1M + && primaryPhy != BluetoothDevice.PHY_LE_CODED) { + throw new IllegalArgumentException("bad primaryPhy " + primaryPhy); } - this.primaryPhy = primaryPhy; + mPrimaryPhy = primaryPhy; return this; } @@ -329,95 +347,91 @@ public final class AdvertisingSetParameters implements Parcelable { * {@link BluetoothAdapter#isLe2MPhySupported} to determine if LE Coded PHY or 2M PHY is * supported on this device. * - * @param secondaryPhy Secondary advertising physical channel, can only be - * one of {@link BluetoothDevice#PHY_LE_1M}, - * {@link BluetoothDevice#PHY_LE_2M} or - * {@link BluetoothDevice#PHY_LE_CODED}. + * @param secondaryPhy Secondary advertising physical channel, can only be one of {@link + * BluetoothDevice#PHY_LE_1M}, {@link BluetoothDevice#PHY_LE_2M} or {@link + * BluetoothDevice#PHY_LE_CODED}. * @throws IllegalArgumentException If the secondaryPhy is invalid. */ public Builder setSecondaryPhy(int secondaryPhy) { - if (secondaryPhy != BluetoothDevice.PHY_LE_1M && - secondaryPhy != BluetoothDevice.PHY_LE_2M && - secondaryPhy != BluetoothDevice.PHY_LE_CODED) { - throw new IllegalArgumentException("bad secondaryPhy " + secondaryPhy); + if (secondaryPhy != BluetoothDevice.PHY_LE_1M + && secondaryPhy != BluetoothDevice.PHY_LE_2M + && secondaryPhy != BluetoothDevice.PHY_LE_CODED) { + throw new IllegalArgumentException("bad secondaryPhy " + secondaryPhy); } - this.secondaryPhy = secondaryPhy; + mSecondaryPhy = secondaryPhy; return this; } /** * Set advertising interval. * - * @param interval Bluetooth LE Advertising interval, in 0.625ms unit. Valid - * range is from 160 (100ms) to 16777215 (10,485.759375 s). - * Recommended values are: - * {@link AdvertisingSetParameters#INTERVAL_LOW}, - * {@link AdvertisingSetParameters#INTERVAL_MEDIUM}, or - * {@link AdvertisingSetParameters#INTERVAL_HIGH}. + * @param interval Bluetooth LE Advertising interval, in 0.625ms unit. Valid range is from + * 160 (100ms) to 16777215 (10,485.759375 s). Recommended values are: {@link + * AdvertisingSetParameters#INTERVAL_LOW}, {@link AdvertisingSetParameters#INTERVAL_MEDIUM}, + * or {@link AdvertisingSetParameters#INTERVAL_HIGH}. * @throws IllegalArgumentException If the interval is invalid. */ public Builder setInterval(int interval) { if (interval < INTERVAL_MIN || interval > INTERVAL_MAX) { - throw new IllegalArgumentException("unknown interval " + interval); + throw new IllegalArgumentException("unknown interval " + interval); } - this.interval = interval; + mInterval = interval; return this; } /** * Set the transmission power level for the advertising. - * @param txPowerLevel Transmission power of Bluetooth LE Advertising, in - * dBm. The valid range is [-127, 1] Recommended values are: - * {@link AdvertisingSetParameters#TX_POWER_ULTRA_LOW}, - * {@link AdvertisingSetParameters#TX_POWER_LOW}, - * {@link AdvertisingSetParameters#TX_POWER_MEDIUM}, or - * {@link AdvertisingSetParameters#TX_POWER_HIGH}. * + * @param txPowerLevel Transmission power of Bluetooth LE Advertising, in dBm. The valid + * range is [-127, 1] Recommended values are: + * {@link AdvertisingSetParameters#TX_POWER_ULTRA_LOW}, + * {@link AdvertisingSetParameters#TX_POWER_LOW}, + * {@link AdvertisingSetParameters#TX_POWER_MEDIUM}, + * or {@link AdvertisingSetParameters#TX_POWER_HIGH}. * @throws IllegalArgumentException If the {@code txPowerLevel} is invalid. */ public Builder setTxPowerLevel(int txPowerLevel) { if (txPowerLevel < TX_POWER_MIN || txPowerLevel > TX_POWER_MAX) { - throw new IllegalArgumentException("unknown txPowerLevel " + - txPowerLevel); + throw new IllegalArgumentException("unknown txPowerLevel " + txPowerLevel); } - this.txPowerLevel = txPowerLevel; + mTxPowerLevel = txPowerLevel; return this; } /** * Build the {@link AdvertisingSetParameters} object. + * * @throws IllegalStateException if invalid combination of parameters is used. */ public AdvertisingSetParameters build() { - if (isLegacy) { - if (isAnonymous) { + if (mIsLegacy) { + if (mIsAnonymous) { throw new IllegalArgumentException("Legacy advertising can't be anonymous"); } - if (connectable == true && scannable == false) { + if (mConnectable && !mScannable) { throw new IllegalStateException( - "Legacy advertisement can't be connectable and non-scannable"); + "Legacy advertisement can't be connectable and non-scannable"); } - if (includeTxPower) { + if (mIncludeTxPower) { throw new IllegalStateException( - "Legacy advertising can't include TX power level in header"); + "Legacy advertising can't include TX power level in header"); } } else { - if (connectable && scannable) { + if (mConnectable && mScannable) { throw new IllegalStateException( - "Advertising can't be both connectable and scannable"); + "Advertising can't be both connectable and scannable"); } - if (isAnonymous && connectable) { + if (mIsAnonymous && mConnectable) { throw new IllegalStateException( - "Advertising can't be both connectable and anonymous"); + "Advertising can't be both connectable and anonymous"); } } - return new AdvertisingSetParameters(connectable, scannable, isLegacy, isAnonymous, - includeTxPower, primaryPhy, - secondaryPhy, interval, txPowerLevel); + return new AdvertisingSetParameters(mConnectable, mScannable, mIsLegacy, mIsAnonymous, + mIncludeTxPower, mPrimaryPhy, mSecondaryPhy, mInterval, mTxPowerLevel); } } -}
\ No newline at end of file +} diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java index dfd5996c6a00..0fb4ba1a8765 100644 --- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java +++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java @@ -18,7 +18,6 @@ package android.bluetooth.le; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothUuid; import android.bluetooth.IBluetoothGatt; import android.bluetooth.IBluetoothManager; @@ -31,7 +30,6 @@ import android.util.Log; import java.util.Collections; import java.util.HashMap; import java.util.Map; -import java.util.UUID; /** * This class provides a way to perform Bluetooth LE advertise operations, such as starting and @@ -117,8 +115,8 @@ public final class BluetoothLeAdvertiser { throw new IllegalArgumentException("callback cannot be null"); } boolean isConnectable = settings.isConnectable(); - if (totalBytes(advertiseData, isConnectable) > MAX_LEGACY_ADVERTISING_DATA_BYTES || - totalBytes(scanResponse, false) > MAX_LEGACY_ADVERTISING_DATA_BYTES) { + if (totalBytes(advertiseData, isConnectable) > MAX_LEGACY_ADVERTISING_DATA_BYTES + || totalBytes(scanResponse, false) > MAX_LEGACY_ADVERTISING_DATA_BYTES) { postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE); return; } @@ -152,13 +150,13 @@ public final class BluetoothLeAdvertiser { int duration = 0; int timeoutMillis = settings.getTimeout(); if (timeoutMillis > 0) { - duration = (timeoutMillis < 10) ? 1 : timeoutMillis/10; + duration = (timeoutMillis < 10) ? 1 : timeoutMillis / 10; } AdvertisingSetCallback wrapped = wrapOldCallback(callback, settings); mLegacyAdvertisers.put(callback, wrapped); startAdvertisingSet(parameters.build(), advertiseData, scanResponse, null, null, - duration, 0, wrapped); + duration, 0, wrapped); } } @@ -166,7 +164,7 @@ public final class BluetoothLeAdvertiser { return new AdvertisingSetCallback() { @Override public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower, - int status) { + int status) { if (status != AdvertisingSetCallback.ADVERTISE_SUCCESS) { postStartFailure(callback, status); return; @@ -178,10 +176,10 @@ public final class BluetoothLeAdvertiser { /* Legacy advertiser is disabled on timeout */ @Override public void onAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enabled, - int status) { - if (enabled == true) { - Log.e(TAG, "Legacy advertiser should be only disabled on timeout," + - " but was enabled!"); + int status) { + if (enabled) { + Log.e(TAG, "Legacy advertiser should be only disabled on timeout," + + " but was enabled!"); return; } @@ -218,28 +216,28 @@ public final class BluetoothLeAdvertiser { * method returns immediately, the operation status is delivered through * {@code callback.onAdvertisingSetStarted()}. * <p> + * * @param parameters advertising set parameters. - * @param advertiseData Advertisement data to be broadcasted. Size must not exceed - * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the - * advertisement is connectable, three bytes will be added for flags. + * @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link + * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable, + * three bytes will be added for flags. * @param scanResponse Scan response associated with the advertisement data. Size must not - * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. + * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will - * not be started. - * @param periodicData Periodic advertising data. Size must not exceed - * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. + * not be started. + * @param periodicData Periodic advertising data. Size must not exceed {@link + * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. * @param callback Callback for advertising set. * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable - * size, or unsupported advertising PHY is selected, or when attempt to use - * Periodic Advertising feature is made when it's not supported by the - * controller. + * size, or unsupported advertising PHY is selected, or when attempt to use Periodic Advertising + * feature is made when it's not supported by the controller. */ public void startAdvertisingSet(AdvertisingSetParameters parameters, - AdvertiseData advertiseData, AdvertiseData scanResponse, - PeriodicAdvertisingParameters periodicParameters, - AdvertiseData periodicData, AdvertisingSetCallback callback) { - startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters, - periodicData, 0, 0, callback, new Handler(Looper.getMainLooper())); + AdvertiseData advertiseData, AdvertiseData scanResponse, + PeriodicAdvertisingParameters periodicParameters, + AdvertiseData periodicData, AdvertisingSetCallback callback) { + startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters, + periodicData, 0, 0, callback, new Handler(Looper.getMainLooper())); } /** @@ -247,30 +245,30 @@ public final class BluetoothLeAdvertiser { * method returns immediately, the operation status is delivered through * {@code callback.onAdvertisingSetStarted()}. * <p> + * * @param parameters advertising set parameters. - * @param advertiseData Advertisement data to be broadcasted. Size must not exceed - * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the - * advertisement is connectable, three bytes will be added for flags. + * @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link + * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable, + * three bytes will be added for flags. * @param scanResponse Scan response associated with the advertisement data. Size must not - * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. + * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will - * not be started. - * @param periodicData Periodic advertising data. Size must not exceed - * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. + * not be started. + * @param periodicData Periodic advertising data. Size must not exceed {@link + * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. * @param callback Callback for advertising set. * @param handler thread upon which the callbacks will be invoked. * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable - * size, or unsupported advertising PHY is selected, or when attempt to use - * Periodic Advertising feature is made when it's not supported by the - * controller. + * size, or unsupported advertising PHY is selected, or when attempt to use Periodic Advertising + * feature is made when it's not supported by the controller. */ public void startAdvertisingSet(AdvertisingSetParameters parameters, - AdvertiseData advertiseData, AdvertiseData scanResponse, - PeriodicAdvertisingParameters periodicParameters, - AdvertiseData periodicData, AdvertisingSetCallback callback, - Handler handler) { + AdvertiseData advertiseData, AdvertiseData scanResponse, + PeriodicAdvertisingParameters periodicParameters, + AdvertiseData periodicData, AdvertisingSetCallback callback, + Handler handler) { startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters, - periodicData, 0, 0, callback, handler); + periodicData, 0, 0, callback, handler); } /** @@ -278,37 +276,36 @@ public final class BluetoothLeAdvertiser { * method returns immediately, the operation status is delivered through * {@code callback.onAdvertisingSetStarted()}. * <p> + * * @param parameters advertising set parameters. - * @param advertiseData Advertisement data to be broadcasted. Size must not exceed - * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the - * advertisement is connectable, three bytes will be added for flags. + * @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link + * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable, + * three bytes will be added for flags. * @param scanResponse Scan response associated with the advertisement data. Size must not - * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. + * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will - * not be started. - * @param periodicData Periodic advertising data. Size must not exceed - * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. - * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to - * 65535 (655,350 ms). 0 means advertising should continue until stopped. + * not be started. + * @param periodicData Periodic advertising data. Size must not exceed {@link + * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. + * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to 65535 + * (655,350 ms). 0 means advertising should continue until stopped. * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the - * controller shall attempt to send prior to terminating the extended - * advertising, even if the duration has not expired. Valid range is - * from 1 to 255. 0 means no maximum. + * controller shall attempt to send prior to terminating the extended advertising, even if the + * duration has not expired. Valid range is from 1 to 255. 0 means no maximum. * @param callback Callback for advertising set. * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable - * size, or unsupported advertising PHY is selected, or when attempt to use - * Periodic Advertising feature is made when it's not supported by the - * controller. + * size, or unsupported advertising PHY is selected, or when attempt to use Periodic Advertising + * feature is made when it's not supported by the controller. */ public void startAdvertisingSet(AdvertisingSetParameters parameters, - AdvertiseData advertiseData, AdvertiseData scanResponse, - PeriodicAdvertisingParameters periodicParameters, - AdvertiseData periodicData, int duration, - int maxExtendedAdvertisingEvents, - AdvertisingSetCallback callback) { + AdvertiseData advertiseData, AdvertiseData scanResponse, + PeriodicAdvertisingParameters periodicParameters, + AdvertiseData periodicData, int duration, + int maxExtendedAdvertisingEvents, + AdvertisingSetCallback callback) { startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters, - periodicData, duration, maxExtendedAdvertisingEvents, callback, - new Handler(Looper.getMainLooper())); + periodicData, duration, maxExtendedAdvertisingEvents, callback, + new Handler(Looper.getMainLooper())); } /** @@ -316,39 +313,39 @@ public final class BluetoothLeAdvertiser { * method returns immediately, the operation status is delivered through * {@code callback.onAdvertisingSetStarted()}. * <p> + * * @param parameters Advertising set parameters. - * @param advertiseData Advertisement data to be broadcasted. Size must not exceed - * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the - * advertisement is connectable, three bytes will be added for flags. + * @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link + * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable, + * three bytes will be added for flags. * @param scanResponse Scan response associated with the advertisement data. Size must not - * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength} + * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength} * @param periodicParameters Periodic advertisng parameters. If null, periodic advertising will - * not be started. - * @param periodicData Periodic advertising data. Size must not exceed - * {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength} - * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to - * 65535 (655,350 ms). 0 means advertising should continue until stopped. + * not be started. + * @param periodicData Periodic advertising data. Size must not exceed {@link + * BluetoothAdapter#getLeMaximumAdvertisingDataLength} + * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to 65535 + * (655,350 ms). 0 means advertising should continue until stopped. * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the - * controller shall attempt to send prior to terminating the extended - * advertising, even if the duration has not expired. Valid range is - * from 1 to 255. 0 means no maximum. + * controller shall attempt to send prior to terminating the extended advertising, even if the + * duration has not expired. Valid range is from 1 to 255. 0 means no maximum. * @param callback Callback for advertising set. * @param handler Thread upon which the callbacks will be invoked. * @throws IllegalArgumentException When any of the data parameter exceed the maximum allowable - * size, or unsupported advertising PHY is selected, or when attempt to use - * Periodic Advertising feature is made when it's not supported by the - * controller, or when maxExtendedAdvertisingEvents is used on a controller - * that doesn't support the LE Extended Advertising + * size, or unsupported advertising PHY is selected, or when attempt to use Periodic Advertising + * feature is made when it's not supported by the controller, or when + * maxExtendedAdvertisingEvents is used on a controller that doesn't support the LE Extended + * Advertising */ public void startAdvertisingSet(AdvertisingSetParameters parameters, - AdvertiseData advertiseData, AdvertiseData scanResponse, - PeriodicAdvertisingParameters periodicParameters, - AdvertiseData periodicData, int duration, - int maxExtendedAdvertisingEvents, AdvertisingSetCallback callback, - Handler handler) { + AdvertiseData advertiseData, AdvertiseData scanResponse, + PeriodicAdvertisingParameters periodicParameters, + AdvertiseData periodicData, int duration, + int maxExtendedAdvertisingEvents, AdvertisingSetCallback callback, + Handler handler) { BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); if (callback == null) { - throw new IllegalArgumentException("callback cannot be null"); + throw new IllegalArgumentException("callback cannot be null"); } boolean isConnectable = parameters.isConnectable(); @@ -370,7 +367,7 @@ public final class BluetoothLeAdvertiser { } if ((sphy == BluetoothDevice.PHY_LE_CODED && !supportCodedPhy) - || (sphy == BluetoothDevice.PHY_LE_2M && !support2MPhy)) { + || (sphy == BluetoothDevice.PHY_LE_2M && !support2MPhy)) { throw new IllegalArgumentException("Unsupported secondary PHY selected"); } @@ -390,20 +387,20 @@ public final class BluetoothLeAdvertiser { boolean supportPeriodic = mBluetoothAdapter.isLePeriodicAdvertisingSupported(); if (periodicParameters != null && !supportPeriodic) { throw new IllegalArgumentException( - "Controller does not support LE Periodic Advertising"); + "Controller does not support LE Periodic Advertising"); } } if (maxExtendedAdvertisingEvents < 0 || maxExtendedAdvertisingEvents > 255) { throw new IllegalArgumentException( - "maxExtendedAdvertisingEvents out of range: " + maxExtendedAdvertisingEvents); + "maxExtendedAdvertisingEvents out of range: " + maxExtendedAdvertisingEvents); } - if (maxExtendedAdvertisingEvents != 0 && - !mBluetoothAdapter.isLePeriodicAdvertisingSupported()) { + if (maxExtendedAdvertisingEvents != 0 + && !mBluetoothAdapter.isLePeriodicAdvertisingSupported()) { throw new IllegalArgumentException( - "Can't use maxExtendedAdvertisingEvents with controller that don't support " + - "LE Extended Advertising"); + "Can't use maxExtendedAdvertisingEvents with controller that don't support " + + "LE Extended Advertising"); } if (duration < 0 || duration > 65535) { @@ -412,24 +409,28 @@ public final class BluetoothLeAdvertiser { IBluetoothGatt gatt; try { - gatt = mBluetoothManager.getBluetoothGatt(); + gatt = mBluetoothManager.getBluetoothGatt(); } catch (RemoteException e) { - Log.e(TAG, "Failed to get Bluetooth gatt - ", e); - throw new IllegalStateException("Failed to get Bluetooth"); + Log.e(TAG, "Failed to get Bluetooth gatt - ", e); + postStartSetFailure(handler, callback, + AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); + return; } IAdvertisingSetCallback wrapped = wrap(callback, handler); if (mCallbackWrappers.putIfAbsent(callback, wrapped) != null) { throw new IllegalArgumentException( - "callback instance already associated with advertising"); + "callback instance already associated with advertising"); } try { gatt.startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters, - periodicData, duration, maxExtendedAdvertisingEvents, wrapped); + periodicData, duration, maxExtendedAdvertisingEvents, wrapped); } catch (RemoteException e) { - Log.e(TAG, "Failed to start advertising set - ", e); - throw new IllegalStateException("Failed to start advertising set"); + Log.e(TAG, "Failed to start advertising set - ", e); + postStartSetFailure(handler, callback, + AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); + return; } } @@ -439,7 +440,7 @@ public final class BluetoothLeAdvertiser { */ public void stopAdvertisingSet(AdvertisingSetCallback callback) { if (callback == null) { - throw new IllegalArgumentException("callback cannot be null"); + throw new IllegalArgumentException("callback cannot be null"); } IAdvertisingSetCallback wrapped = mCallbackWrappers.remove(callback); @@ -451,9 +452,8 @@ public final class BluetoothLeAdvertiser { try { gatt = mBluetoothManager.getBluetoothGatt(); gatt.stopAdvertisingSet(wrapped); - } catch (RemoteException e) { + } catch (RemoteException e) { Log.e(TAG, "Failed to stop advertising - ", e); - throw new IllegalStateException("Failed to stop advertising"); } } @@ -488,18 +488,16 @@ public final class BluetoothLeAdvertiser { } // 16 bit service uuids are grouped into one field when doing advertising. if (num16BitUuids != 0) { - size += OVERHEAD_BYTES_PER_FIELD + - num16BitUuids * BluetoothUuid.UUID_BYTES_16_BIT; + size += OVERHEAD_BYTES_PER_FIELD + num16BitUuids * BluetoothUuid.UUID_BYTES_16_BIT; } // 32 bit service uuids are grouped into one field when doing advertising. if (num32BitUuids != 0) { - size += OVERHEAD_BYTES_PER_FIELD + - num32BitUuids * BluetoothUuid.UUID_BYTES_32_BIT; + size += OVERHEAD_BYTES_PER_FIELD + num32BitUuids * BluetoothUuid.UUID_BYTES_32_BIT; } // 128 bit service uuids are grouped into one field when doing advertising. if (num128BitUuids != 0) { - size += OVERHEAD_BYTES_PER_FIELD + - num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT; + size += OVERHEAD_BYTES_PER_FIELD + + num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT; } } for (ParcelUuid uuid : data.getServiceData().keySet()) { @@ -508,8 +506,8 @@ public final class BluetoothLeAdvertiser { + byteLength(data.getServiceData().get(uuid)); } for (int i = 0; i < data.getManufacturerSpecificData().size(); ++i) { - size += OVERHEAD_BYTES_PER_FIELD + MANUFACTURER_SPECIFIC_DATA_LENGTH + - byteLength(data.getManufacturerSpecificData().valueAt(i)); + size += OVERHEAD_BYTES_PER_FIELD + MANUFACTURER_SPECIFIC_DATA_LENGTH + + byteLength(data.getManufacturerSpecificData().valueAt(i)); } if (data.getIncludeTxPowerLevel()) { size += OVERHEAD_BYTES_PER_FIELD + 1; // tx power level value is one byte. @@ -538,7 +536,7 @@ public final class BluetoothLeAdvertiser { } AdvertisingSet advertisingSet = - new AdvertisingSet(advertiserId, mBluetoothManager); + new AdvertisingSet(advertiserId, mBluetoothManager); mAdvertisingSets.put(advertiserId, advertisingSet); callback.onAdvertisingSetStarted(advertisingSet, txPower, status); } @@ -648,6 +646,16 @@ public final class BluetoothLeAdvertiser { }; } + private void postStartSetFailure(Handler handler, final AdvertisingSetCallback callback, + final int error) { + handler.post(new Runnable() { + @Override + public void run() { + callback.onAdvertisingSetStarted(null, 0, error); + } + }); + } + private void postStartFailure(final AdvertiseCallback callback, final int error) { mHandler.post(new Runnable() { @Override diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java index e3bc78e5a2bb..c8ed7ef719d9 100644 --- a/core/java/android/bluetooth/le/BluetoothLeScanner.java +++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java @@ -62,8 +62,8 @@ public final class BluetoothLeScanner { * error. In case of error, {@link #EXTRA_ERROR_CODE} will contain the error code and this * extra will not be available. */ - public static final String EXTRA_LIST_SCAN_RESULT - = "android.bluetooth.le.extra.LIST_SCAN_RESULT"; + public static final String EXTRA_LIST_SCAN_RESULT = + "android.bluetooth.le.extra.LIST_SCAN_RESULT"; /** * Optional extra indicating the error code, if any. The error code will be one of the @@ -74,6 +74,7 @@ public final class BluetoothLeScanner { /** * Optional extra indicating the callback type, which will be one of * CALLBACK_TYPE_* constants in {@link ScanSettings}. + * * @see ScanCallback#onScanResult(int, ScanResult) */ public static final String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE"; @@ -162,13 +163,13 @@ public final class BluetoothLeScanner { * specify on behalf of which application(s) the work is being done. * * @param workSource {@link WorkSource} identifying the application(s) for which to blame for - * the scan. + * the scan. * @param callback Callback used to deliver scan results. * @hide */ @SystemApi @RequiresPermission(allOf = { - Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.UPDATE_DEVICE_STATS }) + Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.UPDATE_DEVICE_STATS}) public void startScanFromSource(final WorkSource workSource, final ScanCallback callback) { startScanFromSource(null, new ScanSettings.Builder().build(), workSource, callback); } @@ -180,22 +181,22 @@ public final class BluetoothLeScanner { * @param filters {@link ScanFilter}s for finding exact BLE devices. * @param settings Settings for the scan. * @param workSource {@link WorkSource} identifying the application(s) for which to blame for - * the scan. + * the scan. * @param callback Callback used to deliver scan results. * @hide */ @SystemApi @RequiresPermission(allOf = { - Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.UPDATE_DEVICE_STATS }) + Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.UPDATE_DEVICE_STATS}) public void startScanFromSource(List<ScanFilter> filters, ScanSettings settings, - final WorkSource workSource, final ScanCallback callback) { + final WorkSource workSource, final ScanCallback callback) { startScan(filters, settings, workSource, callback, null, null); } private int startScan(List<ScanFilter> filters, ScanSettings settings, - final WorkSource workSource, final ScanCallback callback, - final PendingIntent callbackIntent, - List<List<ResultStorageDescriptor>> resultStorages) { + final WorkSource workSource, final ScanCallback callback, + final PendingIntent callbackIntent, + List<List<ResultStorageDescriptor>> resultStorages) { BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); if (callback == null && callbackIntent == null) { throw new IllegalArgumentException("callback is null"); @@ -219,11 +220,11 @@ public final class BluetoothLeScanner { } if (!isSettingsConfigAllowedForScan(settings)) { return postCallbackErrorOrReturn(callback, - ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); + ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); } if (!isHardwareResourcesAvailableForScan(settings)) { return postCallbackErrorOrReturn(callback, - ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES); + ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES); } if (!isSettingsAndFilterComboAllowed(settings, filters)) { return postCallbackErrorOrReturn(callback, @@ -286,7 +287,7 @@ public final class BluetoothLeScanner { * will be delivered through the {@code callback}. * * @param callback Callback of the Bluetooth LE Scan, it has to be the same instance as the one - * used to start scan. + * used to start scan. */ public void flushPendingScanResults(ScanCallback callback) { BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); @@ -344,6 +345,7 @@ public final class BluetoothLeScanner { private List<List<ResultStorageDescriptor>> mResultStorages; // mLeHandle 0: not registered + // -2: registration failed because app is scanning to frequently // -1: scan stopped or registration failed // > 0: registered and scan started private int mScannerId; @@ -364,7 +366,7 @@ public final class BluetoothLeScanner { public void startRegistration() { synchronized (this) { // Scan stopped. - if (mScannerId == -1) return; + if (mScannerId == -1 || mScannerId == -2) return; try { mBluetoothGatt.registerScanner(this, mWorkSource); wait(REGISTRATION_CALLBACK_TIMEOUT_MILLIS); @@ -378,6 +380,10 @@ public final class BluetoothLeScanner { // Registration timed out or got exception, reset scannerId to -1 so no // subsequent operations can proceed. if (mScannerId == 0) mScannerId = -1; + + // If scanning too frequently, don't report anything to the app. + if (mScannerId == -2) return; + postCallbackError(mScanCallback, ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED); } @@ -419,8 +425,8 @@ public final class BluetoothLeScanner { */ @Override public void onScannerRegistered(int status, int scannerId) { - Log.d(TAG, "onScannerRegistered() - status=" + status + - " scannerId=" + scannerId + " mScannerId=" + mScannerId); + Log.d(TAG, "onScannerRegistered() - status=" + status + + " scannerId=" + scannerId + " mScannerId=" + mScannerId); synchronized (this) { if (status == BluetoothGatt.GATT_SUCCESS) { try { @@ -437,6 +443,9 @@ public final class BluetoothLeScanner { Log.e(TAG, "fail to start le scan: " + e); mScannerId = -1; } + } else if (status == ScanCallback.SCAN_FAILED_SCANNING_TOO_FREQUENTLY) { + // applicaiton was scanning too frequently + mScannerId = -2; } else { // registration failed mScannerId = -1; @@ -481,18 +490,18 @@ public final class BluetoothLeScanner { @Override public void onFoundOrLost(final boolean onFound, final ScanResult scanResult) { if (VDBG) { - Log.d(TAG, "onFoundOrLost() - onFound = " + onFound + - " " + scanResult.toString()); + Log.d(TAG, "onFoundOrLost() - onFound = " + onFound + " " + scanResult.toString()); } // Check null in case the scan has been stopped synchronized (this) { - if (mScannerId <= 0) + if (mScannerId <= 0) { return; + } } Handler handler = new Handler(Looper.getMainLooper()); handler.post(new Runnable() { - @Override + @Override public void run() { if (onFound) { mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_FIRST_MATCH, @@ -511,8 +520,9 @@ public final class BluetoothLeScanner { Log.d(TAG, "onScanManagerErrorCallback() - errorCode = " + errorCode); } synchronized (this) { - if (mScannerId <= 0) + if (mScannerId <= 0) { return; + } } postCallbackError(mScanCallback, errorCode); } @@ -550,11 +560,11 @@ public final class BluetoothLeScanner { } private boolean isSettingsAndFilterComboAllowed(ScanSettings settings, - List <ScanFilter> filterList) { + List<ScanFilter> filterList) { final int callbackType = settings.getCallbackType(); // If onlost/onfound is requested, a non-empty filter is expected if ((callbackType & (ScanSettings.CALLBACK_TYPE_FIRST_MATCH - | ScanSettings.CALLBACK_TYPE_MATCH_LOST)) != 0) { + | ScanSettings.CALLBACK_TYPE_MATCH_LOST)) != 0) { if (filterList == null) { return false; } @@ -572,8 +582,8 @@ public final class BluetoothLeScanner { if ((callbackType & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) != 0 || (callbackType & ScanSettings.CALLBACK_TYPE_MATCH_LOST) != 0) { // For onlost/onfound, we required hw support be available - return (mBluetoothAdapter.isOffloadedFilteringSupported() && - mBluetoothAdapter.isHardwareTrackingFiltersAvailable()); + return (mBluetoothAdapter.isOffloadedFilteringSupported() + && mBluetoothAdapter.isHardwareTrackingFiltersAvailable()); } return true; } diff --git a/core/java/android/bluetooth/le/BluetoothLeUtils.java b/core/java/android/bluetooth/le/BluetoothLeUtils.java index c40256b89069..6381f557c1b2 100644 --- a/core/java/android/bluetooth/le/BluetoothLeUtils.java +++ b/core/java/android/bluetooth/le/BluetoothLeUtils.java @@ -92,8 +92,8 @@ public class BluetoothLeUtils { // Keys are guaranteed in ascending order when indices are in ascending order. for (int i = 0; i < array.size(); ++i) { - if (array.keyAt(i) != otherArray.keyAt(i) || - !Arrays.equals(array.valueAt(i), otherArray.valueAt(i))) { + if (array.keyAt(i) != otherArray.keyAt(i) + || !Arrays.equals(array.valueAt(i), otherArray.valueAt(i))) { return false; } } @@ -128,11 +128,11 @@ public class BluetoothLeUtils { /** * Ensure Bluetooth is turned on. * - * @throws IllegalStateException If {@code adapter} is null or Bluetooth state is not - * {@link BluetoothAdapter#STATE_ON}. + * @throws IllegalStateException If {@code adapter} is null or Bluetooth state is not {@link + * BluetoothAdapter#STATE_ON}. */ static void checkAdapterStateOn(BluetoothAdapter adapter) { - if (adapter == null || !adapter.isLeEnabled()) {//adapter.getState() != BluetoothAdapter.STATE_ON) { + if (adapter == null || !adapter.isLeEnabled()) { throw new IllegalStateException("BT Adapter is not turned ON"); } } diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java b/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java index 364b575b4d8d..14ac911fcb7f 100644 --- a/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java +++ b/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java @@ -22,8 +22,8 @@ import android.bluetooth.BluetoothDevice; * Bluetooth LE periodic advertising callbacks, used to deliver periodic * advertising operation status. * - * @see PeriodicAdvertisingManager#createSync * @hide + * @see PeriodicAdvertisingManager#createSync */ public abstract class PeriodicAdvertisingCallback { @@ -40,7 +40,7 @@ public abstract class PeriodicAdvertisingCallback { public static final int SYNC_NO_RESPONSE = 1; /** - * Sync failed to be established because controller can't support more syncs. + * Sync failed to be established because controller can't support more syncs. */ public static final int SYNC_NO_RESOURCES = 2; @@ -51,28 +51,31 @@ public abstract class PeriodicAdvertisingCallback { * @param syncHandle handle used to identify this synchronization. * @param device remote device. * @param advertisingSid synchronized advertising set id. - * @param skip The number of periodic advertising packets that can be skipped - * after a successful receive in force. @see PeriodicAdvertisingManager#createSync - * @param timeout Synchronization timeout for the periodic advertising in force. One - * unit is 10ms. @see PeriodicAdvertisingManager#createSync + * @param skip The number of periodic advertising packets that can be skipped after a successful + * receive in force. @see PeriodicAdvertisingManager#createSync + * @param timeout Synchronization timeout for the periodic advertising in force. One unit is + * 10ms. @see PeriodicAdvertisingManager#createSync * @param timeout * @param status operation status. */ public void onSyncEstablished(int syncHandle, BluetoothDevice device, - int advertisingSid, int skip, int timeout, - int status) {} + int advertisingSid, int skip, int timeout, + int status) { + } /** * Callback when periodic advertising report is received. * * @param report periodic advertising report. */ - public void onPeriodicAdvertisingReport(PeriodicAdvertisingReport report) {} + public void onPeriodicAdvertisingReport(PeriodicAdvertisingReport report) { + } /** * Callback when periodic advertising synchronization was lost. * * @param syncHandle handle used to identify this synchronization. */ - public void onSyncLost(int syncHandle) {} + public void onSyncLost(int syncHandle) { + } } diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java b/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java index d9c2d8819a33..0f1a8e913ba8 100644 --- a/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java +++ b/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java @@ -24,6 +24,7 @@ import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.util.Log; + import java.util.IdentityHashMap; import java.util.Map; @@ -37,202 +38,207 @@ import java.util.Map; * <p> * <b>Note:</b> Most of the methods here require * {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. + * * @hide */ public final class PeriodicAdvertisingManager { - private static final String TAG = "PeriodicAdvertisingManager"; - - private static final int SKIP_MIN = 0; - private static final int SKIP_MAX = 499; - private static final int TIMEOUT_MIN = 10; - private static final int TIMEOUT_MAX = 16384; - - private static final int SYNC_STARTING = -1; - - private final IBluetoothManager mBluetoothManager; - private BluetoothAdapter mBluetoothAdapter; - - /* maps callback, to callback wrapper and sync handle */ - Map<PeriodicAdvertisingCallback, - IPeriodicAdvertisingCallback /* callbackWrapper */> callbackWrappers; - - /** - * Use {@link BluetoothAdapter#getBluetoothLeScanner()} instead. - * - * @param bluetoothManager BluetoothManager that conducts overall Bluetooth Management. - * @hide - */ - public PeriodicAdvertisingManager(IBluetoothManager bluetoothManager) { - mBluetoothManager = bluetoothManager; - mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - callbackWrappers = new IdentityHashMap<>(); - } - - /** - * Synchronize with periodic advertising pointed to by the {@code scanResult}. - * The {@code scanResult} used must contain a valid advertisingSid. First - * call to registerSync will use the {@code skip} and {@code timeout} provided. - * Subsequent calls from other apps, trying to sync with same set will reuse - * existing sync, thus {@code skip} and {@code timeout} values will not take - * effect. The values in effect will be returned in - * {@link PeriodicAdvertisingCallback#onSyncEstablished}. - * - * @param scanResult Scan result containing advertisingSid. - * @param skip The number of periodic advertising packets that can be skipped - * after a successful receive. Must be between 0 and 499. - * @param timeout Synchronization timeout for the periodic advertising. One - * unit is 10ms. Must be between 10 (100ms) and 16384 (163.84s). - * @param callback Callback used to deliver all operations status. - * @throws IllegalArgumentException if {@code scanResult} is null or {@code - * skip} is invalid or {@code timeout} is invalid or {@code callback} is null. - */ - public void registerSync(ScanResult scanResult, int skip, int timeout, - PeriodicAdvertisingCallback callback) { - registerSync(scanResult, skip, timeout, callback, null); - } - - /** - * Synchronize with periodic advertising pointed to by the {@code scanResult}. - * The {@code scanResult} used must contain a valid advertisingSid. First - * call to registerSync will use the {@code skip} and {@code timeout} provided. - * Subsequent calls from other apps, trying to sync with same set will reuse - * existing sync, thus {@code skip} and {@code timeout} values will not take - * effect. The values in effect will be returned in - * {@link PeriodicAdvertisingCallback#onSyncEstablished}. - * - * @param scanResult Scan result containing advertisingSid. - * @param skip The number of periodic advertising packets that can be skipped - * after a successful receive. Must be between 0 and 499. - * @param timeout Synchronization timeout for the periodic advertising. One - * unit is 10ms. Must be between 10 (100ms) and 16384 (163.84s). - * @param callback Callback used to deliver all operations status. - * @param handler thread upon which the callbacks will be invoked. - * @throws IllegalArgumentException if {@code scanResult} is null or {@code - * skip} is invalid or {@code timeout} is invalid or {@code callback} is null. - */ - public void registerSync(ScanResult scanResult, int skip, int timeout, - PeriodicAdvertisingCallback callback, Handler handler) { - if (callback == null) { - throw new IllegalArgumentException("callback can't be null"); - } + private static final String TAG = "PeriodicAdvertisingManager"; - if (scanResult == null) { - throw new IllegalArgumentException("scanResult can't be null"); - } + private static final int SKIP_MIN = 0; + private static final int SKIP_MAX = 499; + private static final int TIMEOUT_MIN = 10; + private static final int TIMEOUT_MAX = 16384; - if (scanResult.getAdvertisingSid() == ScanResult.SID_NOT_PRESENT) { - throw new IllegalArgumentException("scanResult must contain a valid sid"); - } + private static final int SYNC_STARTING = -1; - if (skip < SKIP_MIN || skip > SKIP_MAX) { - throw new IllegalArgumentException( - "timeout must be between " + TIMEOUT_MIN + " and " + TIMEOUT_MAX); - } + private final IBluetoothManager mBluetoothManager; + private BluetoothAdapter mBluetoothAdapter; - if (timeout < TIMEOUT_MIN || timeout > TIMEOUT_MAX) { - throw new IllegalArgumentException( - "timeout must be between " + TIMEOUT_MIN + " and " + TIMEOUT_MAX); - } + /* maps callback, to callback wrapper and sync handle */ + Map<PeriodicAdvertisingCallback, + IPeriodicAdvertisingCallback /* callbackWrapper */> mCallbackWrappers; - IBluetoothGatt gatt; - try { - gatt = mBluetoothManager.getBluetoothGatt(); - } catch (RemoteException e) { - Log.e(TAG, "Failed to get Bluetooth gatt - ", e); - callback.onSyncEstablished(0, scanResult.getDevice(), scanResult.getAdvertisingSid(), - skip, timeout, - PeriodicAdvertisingCallback.SYNC_NO_RESOURCES); - return; + /** + * Use {@link BluetoothAdapter#getBluetoothLeScanner()} instead. + * + * @param bluetoothManager BluetoothManager that conducts overall Bluetooth Management. + * @hide + */ + public PeriodicAdvertisingManager(IBluetoothManager bluetoothManager) { + mBluetoothManager = bluetoothManager; + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + mCallbackWrappers = new IdentityHashMap<>(); } - if (handler == null) - handler = new Handler(Looper.getMainLooper()); - - IPeriodicAdvertisingCallback wrapped = wrap(callback, handler); - callbackWrappers.put(callback, wrapped); - - try { - gatt.registerSync(scanResult, skip, timeout, wrapped); - } catch (RemoteException e) { - Log.e(TAG, "Failed to register sync - ", e); - return; - } - } - - /** - * Cancel pending attempt to create sync, or terminate existing sync. - * - * @param callback Callback used to deliver all operations status. - * @throws IllegalArgumentException if {@code callback} is null, or not a properly - * registered callback. - */ - public void unregisterSync(PeriodicAdvertisingCallback callback) { - if (callback == null) { - throw new IllegalArgumentException("callback can't be null"); + /** + * Synchronize with periodic advertising pointed to by the {@code scanResult}. + * The {@code scanResult} used must contain a valid advertisingSid. First + * call to registerSync will use the {@code skip} and {@code timeout} provided. + * Subsequent calls from other apps, trying to sync with same set will reuse + * existing sync, thus {@code skip} and {@code timeout} values will not take + * effect. The values in effect will be returned in + * {@link PeriodicAdvertisingCallback#onSyncEstablished}. + * + * @param scanResult Scan result containing advertisingSid. + * @param skip The number of periodic advertising packets that can be skipped after a successful + * receive. Must be between 0 and 499. + * @param timeout Synchronization timeout for the periodic advertising. One unit is 10ms. Must + * be between 10 (100ms) and 16384 (163.84s). + * @param callback Callback used to deliver all operations status. + * @throws IllegalArgumentException if {@code scanResult} is null or {@code skip} is invalid or + * {@code timeout} is invalid or {@code callback} is null. + */ + public void registerSync(ScanResult scanResult, int skip, int timeout, + PeriodicAdvertisingCallback callback) { + registerSync(scanResult, skip, timeout, callback, null); } - IBluetoothGatt gatt; - try { - gatt = mBluetoothManager.getBluetoothGatt(); - } catch (RemoteException e) { - Log.e(TAG, "Failed to get Bluetooth gatt - ", e); - return; + /** + * Synchronize with periodic advertising pointed to by the {@code scanResult}. + * The {@code scanResult} used must contain a valid advertisingSid. First + * call to registerSync will use the {@code skip} and {@code timeout} provided. + * Subsequent calls from other apps, trying to sync with same set will reuse + * existing sync, thus {@code skip} and {@code timeout} values will not take + * effect. The values in effect will be returned in + * {@link PeriodicAdvertisingCallback#onSyncEstablished}. + * + * @param scanResult Scan result containing advertisingSid. + * @param skip The number of periodic advertising packets that can be skipped after a successful + * receive. Must be between 0 and 499. + * @param timeout Synchronization timeout for the periodic advertising. One unit is 10ms. Must + * be between 10 (100ms) and 16384 (163.84s). + * @param callback Callback used to deliver all operations status. + * @param handler thread upon which the callbacks will be invoked. + * @throws IllegalArgumentException if {@code scanResult} is null or {@code skip} is invalid or + * {@code timeout} is invalid or {@code callback} is null. + */ + public void registerSync(ScanResult scanResult, int skip, int timeout, + PeriodicAdvertisingCallback callback, Handler handler) { + if (callback == null) { + throw new IllegalArgumentException("callback can't be null"); + } + + if (scanResult == null) { + throw new IllegalArgumentException("scanResult can't be null"); + } + + if (scanResult.getAdvertisingSid() == ScanResult.SID_NOT_PRESENT) { + throw new IllegalArgumentException("scanResult must contain a valid sid"); + } + + if (skip < SKIP_MIN || skip > SKIP_MAX) { + throw new IllegalArgumentException( + "timeout must be between " + TIMEOUT_MIN + " and " + TIMEOUT_MAX); + } + + if (timeout < TIMEOUT_MIN || timeout > TIMEOUT_MAX) { + throw new IllegalArgumentException( + "timeout must be between " + TIMEOUT_MIN + " and " + TIMEOUT_MAX); + } + + IBluetoothGatt gatt; + try { + gatt = mBluetoothManager.getBluetoothGatt(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to get Bluetooth gatt - ", e); + callback.onSyncEstablished(0, scanResult.getDevice(), scanResult.getAdvertisingSid(), + skip, timeout, + PeriodicAdvertisingCallback.SYNC_NO_RESOURCES); + return; + } + + if (handler == null) { + handler = new Handler(Looper.getMainLooper()); + } + + IPeriodicAdvertisingCallback wrapped = wrap(callback, handler); + mCallbackWrappers.put(callback, wrapped); + + try { + gatt.registerSync(scanResult, skip, timeout, wrapped); + } catch (RemoteException e) { + Log.e(TAG, "Failed to register sync - ", e); + return; + } } - IPeriodicAdvertisingCallback wrapper = callbackWrappers.remove(callback); - if (wrapper == null) { - throw new IllegalArgumentException("callback was not properly registered"); + /** + * Cancel pending attempt to create sync, or terminate existing sync. + * + * @param callback Callback used to deliver all operations status. + * @throws IllegalArgumentException if {@code callback} is null, or not a properly registered + * callback. + */ + public void unregisterSync(PeriodicAdvertisingCallback callback) { + if (callback == null) { + throw new IllegalArgumentException("callback can't be null"); + } + + IBluetoothGatt gatt; + try { + gatt = mBluetoothManager.getBluetoothGatt(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to get Bluetooth gatt - ", e); + return; + } + + IPeriodicAdvertisingCallback wrapper = mCallbackWrappers.remove(callback); + if (wrapper == null) { + throw new IllegalArgumentException("callback was not properly registered"); + } + + try { + gatt.unregisterSync(wrapper); + } catch (RemoteException e) { + Log.e(TAG, "Failed to cancel sync creation - ", e); + return; + } } - try { - gatt.unregisterSync(wrapper); - } catch (RemoteException e) { - Log.e(TAG, "Failed to cancel sync creation - ", e); - return; + private IPeriodicAdvertisingCallback wrap(PeriodicAdvertisingCallback callback, + Handler handler) { + return new IPeriodicAdvertisingCallback.Stub() { + public void onSyncEstablished(int syncHandle, BluetoothDevice device, + int advertisingSid, int skip, int timeout, int status) { + + handler.post(new Runnable() { + @Override + public void run() { + callback.onSyncEstablished(syncHandle, device, advertisingSid, skip, + timeout, + status); + + if (status != PeriodicAdvertisingCallback.SYNC_SUCCESS) { + // App can still unregister the sync until notified it failed. Remove + // callback + // after app was notifed. + mCallbackWrappers.remove(callback); + } + } + }); + } + + public void onPeriodicAdvertisingReport(PeriodicAdvertisingReport report) { + handler.post(new Runnable() { + @Override + public void run() { + callback.onPeriodicAdvertisingReport(report); + } + }); + } + + public void onSyncLost(int syncHandle) { + handler.post(new Runnable() { + @Override + public void run() { + callback.onSyncLost(syncHandle); + // App can still unregister the sync until notified it's lost. + // Remove callback after app was notifed. + mCallbackWrappers.remove(callback); + } + }); + } + }; } - } - - private IPeriodicAdvertisingCallback wrap(PeriodicAdvertisingCallback callback, Handler handler) { - return new IPeriodicAdvertisingCallback.Stub() { - public void onSyncEstablished(int syncHandle, BluetoothDevice device, - int advertisingSid, int skip, int timeout, int status) { - - handler.post(new Runnable() { - @Override - public void run() { - callback.onSyncEstablished(syncHandle, device, advertisingSid, skip, timeout, - status); - - if (status != PeriodicAdvertisingCallback.SYNC_SUCCESS) { - // App can still unregister the sync until notified it failed. Remove callback - // after app was notifed. - callbackWrappers.remove(callback); - } - } - }); - } - - public void onPeriodicAdvertisingReport(PeriodicAdvertisingReport report) { - handler.post(new Runnable() { - @Override - public void run() { - callback.onPeriodicAdvertisingReport(report); - } - }); - } - - public void onSyncLost(int syncHandle) { - handler.post(new Runnable() { - @Override - public void run() { - callback.onSyncLost(syncHandle); - // App can still unregister the sync until notified it's lost. Remove callback after - // app was notifed. - callbackWrappers.remove(callback); - } - }); - } - }; - } } diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java b/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java index cf8f08fddd99..e3a130c4b436 100644 --- a/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java +++ b/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java @@ -29,29 +29,33 @@ public final class PeriodicAdvertisingParameters implements Parcelable { private static final int INTERVAL_MIN = 80; private static final int INTERVAL_MAX = 65519; - private final boolean includeTxPower; - private final int interval; + private final boolean mIncludeTxPower; + private final int mInterval; private PeriodicAdvertisingParameters(boolean includeTxPower, int interval) { - this.includeTxPower = includeTxPower; - this.interval = interval; + mIncludeTxPower = includeTxPower; + mInterval = interval; } private PeriodicAdvertisingParameters(Parcel in) { - includeTxPower = in.readInt() != 0 ? true : false; - interval = in.readInt(); + mIncludeTxPower = in.readInt() != 0; + mInterval = in.readInt(); } /** * Returns whether the TX Power will be included. */ - public boolean getIncludeTxPower() { return includeTxPower; } + public boolean getIncludeTxPower() { + return mIncludeTxPower; + } /** * Returns the periodic advertising interval, in 1.25ms unit. * Valid values are from 80 (100ms) to 65519 (81.89875s). */ - public int getInterval() { return interval; } + public int getInterval() { + return mInterval; + } @Override public int describeContents() { @@ -60,34 +64,34 @@ public final class PeriodicAdvertisingParameters implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(includeTxPower ? 1 : 0); - dest.writeInt(interval); + dest.writeInt(mIncludeTxPower ? 1 : 0); + dest.writeInt(mInterval); } public static final Parcelable - .Creator<PeriodicAdvertisingParameters> CREATOR = - new Creator<PeriodicAdvertisingParameters>() { - @Override - public PeriodicAdvertisingParameters[] newArray(int size) { - return new PeriodicAdvertisingParameters[size]; - } - - @Override - public PeriodicAdvertisingParameters createFromParcel(Parcel in) { - return new PeriodicAdvertisingParameters(in); - } - }; + .Creator<PeriodicAdvertisingParameters> CREATOR = + new Creator<PeriodicAdvertisingParameters>() { + @Override + public PeriodicAdvertisingParameters[] newArray(int size) { + return new PeriodicAdvertisingParameters[size]; + } + + @Override + public PeriodicAdvertisingParameters createFromParcel(Parcel in) { + return new PeriodicAdvertisingParameters(in); + } + }; public static final class Builder { - private boolean includeTxPower = false; - private int interval = INTERVAL_MAX; + private boolean mIncludeTxPower = false; + private int mInterval = INTERVAL_MAX; /** * Whether the transmission power level should be included in the periodic * packet. */ public Builder setIncludeTxPower(boolean includeTxPower) { - this.includeTxPower = includeTxPower; + mIncludeTxPower = includeTxPower; return this; } @@ -95,14 +99,15 @@ public final class PeriodicAdvertisingParameters implements Parcelable { * Set advertising interval for periodic advertising, in 1.25ms unit. * Valid values are from 80 (100ms) to 65519 (81.89875s). * Value from range [interval, interval+20ms] will be picked as the actual value. + * * @throws IllegalArgumentException If the interval is invalid. */ public Builder setInterval(int interval) { if (interval < INTERVAL_MIN || interval > INTERVAL_MAX) { - throw new IllegalArgumentException("Invalid interval (must be " + INTERVAL_MIN + - "-" + INTERVAL_MAX + ")"); + throw new IllegalArgumentException("Invalid interval (must be " + INTERVAL_MIN + + "-" + INTERVAL_MAX + ")"); } - this.interval = interval; + mInterval = interval; return this; } @@ -110,7 +115,7 @@ public final class PeriodicAdvertisingParameters implements Parcelable { * Build the {@link AdvertisingSetParameters} object. */ public PeriodicAdvertisingParameters build() { - return new PeriodicAdvertisingParameters(includeTxPower, interval); + return new PeriodicAdvertisingParameters(mIncludeTxPower, mInterval); } } } diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java b/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java index 51b93cbd64dc..55c3a730a833 100644 --- a/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java +++ b/core/java/android/bluetooth/le/PeriodicAdvertisingReport.java @@ -24,6 +24,7 @@ import java.util.Objects; /** * PeriodicAdvertisingReport for Bluetooth LE synchronized advertising. + * * @hide */ public final class PeriodicAdvertisingReport implements Parcelable { @@ -39,29 +40,28 @@ public final class PeriodicAdvertisingReport implements Parcelable { */ public static final int DATA_INCOMPLETE_TRUNCATED = 2; - private int syncHandle; - private int txPower; - private int rssi; - private int dataStatus; + private int mSyncHandle; + private int mTxPower; + private int mRssi; + private int mDataStatus; // periodic advertising data. @Nullable - private ScanRecord data; + private ScanRecord mData; // Device timestamp when the result was last seen. - private long timestampNanos; + private long mTimestampNanos; /** * Constructor of periodic advertising result. - * */ public PeriodicAdvertisingReport(int syncHandle, int txPower, int rssi, - int dataStatus, ScanRecord data) { - this.syncHandle = syncHandle; - this.txPower = txPower; - this.rssi = rssi; - this.dataStatus = dataStatus; - this.data = data; + int dataStatus, ScanRecord data) { + mSyncHandle = syncHandle; + mTxPower = txPower; + mRssi = rssi; + mDataStatus = dataStatus; + mData = data; } private PeriodicAdvertisingReport(Parcel in) { @@ -70,25 +70,25 @@ public final class PeriodicAdvertisingReport implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(syncHandle); - dest.writeLong(txPower); - dest.writeInt(rssi); - dest.writeInt(dataStatus); - if (data != null) { + dest.writeInt(mSyncHandle); + dest.writeLong(mTxPower); + dest.writeInt(mRssi); + dest.writeInt(mDataStatus); + if (mData != null) { dest.writeInt(1); - dest.writeByteArray(data.getBytes()); + dest.writeByteArray(mData.getBytes()); } else { dest.writeInt(0); } } private void readFromParcel(Parcel in) { - syncHandle = in.readInt(); - txPower = in.readInt(); - rssi = in.readInt(); - dataStatus = in.readInt(); + mSyncHandle = in.readInt(); + mTxPower = in.readInt(); + mRssi = in.readInt(); + mDataStatus = in.readInt(); if (in.readInt() == 1) { - data = ScanRecord.parseFromBytes(in.createByteArray()); + mData = ScanRecord.parseFromBytes(in.createByteArray()); } } @@ -101,7 +101,7 @@ public final class PeriodicAdvertisingReport implements Parcelable { * Returns the synchronization handle. */ public int getSyncHandle() { - return syncHandle; + return mSyncHandle; } /** @@ -109,14 +109,14 @@ public final class PeriodicAdvertisingReport implements Parcelable { * of 127 means information was not available. */ public int getTxPower() { - return txPower; + return mTxPower; } /** * Returns the received signal strength in dBm. The valid range is [-127, 20]. */ public int getRssi() { - return rssi; + return mRssi; } /** @@ -124,7 +124,7 @@ public final class PeriodicAdvertisingReport implements Parcelable { * or {@link PeriodicAdvertisingReport#DATA_INCOMPLETE_TRUNCATED}. */ public int getDataStatus() { - return dataStatus; + return mDataStatus; } /** @@ -132,19 +132,19 @@ public final class PeriodicAdvertisingReport implements Parcelable { */ @Nullable public ScanRecord getData() { - return data; + return mData; } /** * Returns timestamp since boot when the scan record was observed. */ public long getTimestampNanos() { - return timestampNanos; + return mTimestampNanos; } @Override public int hashCode() { - return Objects.hash(syncHandle, txPower, rssi, dataStatus, data, timestampNanos); + return Objects.hash(mSyncHandle, mTxPower, mRssi, mDataStatus, mData, mTimestampNanos); } @Override @@ -156,30 +156,31 @@ public final class PeriodicAdvertisingReport implements Parcelable { return false; } PeriodicAdvertisingReport other = (PeriodicAdvertisingReport) obj; - return (syncHandle == other.syncHandle) && - (txPower == other.txPower) && - (rssi == other.rssi) && - (dataStatus == other.dataStatus) && - Objects.equals(data, other.data) && - (timestampNanos == other.timestampNanos); + return (mSyncHandle == other.mSyncHandle) + && (mTxPower == other.mTxPower) + && (mRssi == other.mRssi) + && (mDataStatus == other.mDataStatus) + && Objects.equals(mData, other.mData) + && (mTimestampNanos == other.mTimestampNanos); } @Override public String toString() { - return "PeriodicAdvertisingReport{syncHandle=" + syncHandle + - ", txPower=" + txPower + ", rssi=" + rssi + ", dataStatus=" + dataStatus + - ", data=" + Objects.toString(data) + ", timestampNanos=" + timestampNanos + '}'; + return "PeriodicAdvertisingReport{syncHandle=" + mSyncHandle + + ", txPower=" + mTxPower + ", rssi=" + mRssi + ", dataStatus=" + mDataStatus + + ", data=" + Objects.toString(mData) + ", timestampNanos=" + mTimestampNanos + '}'; } - public static final Parcelable.Creator<PeriodicAdvertisingReport> CREATOR = new Creator<PeriodicAdvertisingReport>() { - @Override - public PeriodicAdvertisingReport createFromParcel(Parcel source) { - return new PeriodicAdvertisingReport(source); - } - - @Override - public PeriodicAdvertisingReport[] newArray(int size) { - return new PeriodicAdvertisingReport[size]; - } - }; + public static final Parcelable.Creator<PeriodicAdvertisingReport> CREATOR = + new Creator<PeriodicAdvertisingReport>() { + @Override + public PeriodicAdvertisingReport createFromParcel(Parcel source) { + return new PeriodicAdvertisingReport(source); + } + + @Override + public PeriodicAdvertisingReport[] newArray(int size) { + return new PeriodicAdvertisingReport[size]; + } + }; } diff --git a/core/java/android/bluetooth/le/ResultStorageDescriptor.java b/core/java/android/bluetooth/le/ResultStorageDescriptor.java index 748f97d2bc79..63bdf69e727f 100644 --- a/core/java/android/bluetooth/le/ResultStorageDescriptor.java +++ b/core/java/android/bluetooth/le/ResultStorageDescriptor.java @@ -78,16 +78,16 @@ public final class ResultStorageDescriptor implements Parcelable { mLength = in.readInt(); } - public static final Parcelable.Creator<ResultStorageDescriptor> - CREATOR = new Creator<ResultStorageDescriptor>() { - @Override - public ResultStorageDescriptor createFromParcel(Parcel source) { - return new ResultStorageDescriptor(source); - } + public static final Parcelable.Creator<ResultStorageDescriptor> CREATOR = + new Creator<ResultStorageDescriptor>() { + @Override + public ResultStorageDescriptor createFromParcel(Parcel source) { + return new ResultStorageDescriptor(source); + } - @Override - public ResultStorageDescriptor[] newArray(int size) { - return new ResultStorageDescriptor[size]; - } - }; + @Override + public ResultStorageDescriptor[] newArray(int size) { + return new ResultStorageDescriptor[size]; + } + }; } diff --git a/core/java/android/bluetooth/le/ScanCallback.java b/core/java/android/bluetooth/le/ScanCallback.java index aff2e9095024..53d9310a1236 100644 --- a/core/java/android/bluetooth/le/ScanCallback.java +++ b/core/java/android/bluetooth/le/ScanCallback.java @@ -46,19 +46,25 @@ public abstract class ScanCallback { /** * Fails to start scan as it is out of hardware resources. + * * @hide */ public static final int SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES = 5; + /** + * Fails to start scan as application tries to scan too frequently. + * @hide + */ + public static final int SCAN_FAILED_SCANNING_TOO_FREQUENTLY = 6; + static final int NO_ERROR = 0; /** * Callback when a BLE advertisement has been found. * - * @param callbackType Determines how this callback was triggered. Could be one of - * {@link ScanSettings#CALLBACK_TYPE_ALL_MATCHES}, - * {@link ScanSettings#CALLBACK_TYPE_FIRST_MATCH} or - * {@link ScanSettings#CALLBACK_TYPE_MATCH_LOST} + * @param callbackType Determines how this callback was triggered. Could be one of {@link + * ScanSettings#CALLBACK_TYPE_ALL_MATCHES}, {@link ScanSettings#CALLBACK_TYPE_FIRST_MATCH} or + * {@link ScanSettings#CALLBACK_TYPE_MATCH_LOST} * @param result A Bluetooth LE scan result. */ public void onScanResult(int callbackType, ScanResult result) { diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java index 457096bf843e..c3fae7d470a3 100644 --- a/core/java/android/bluetooth/le/ScanFilter.java +++ b/core/java/android/bluetooth/le/ScanFilter.java @@ -71,7 +71,7 @@ public final class ScanFilter implements Parcelable { private final byte[] mManufacturerDataMask; /** @hide */ - public static final ScanFilter EMPTY = new ScanFilter.Builder().build() ; + public static final ScanFilter EMPTY = new ScanFilter.Builder().build(); private ScanFilter(String name, String deviceAddress, ParcelUuid uuid, @@ -145,70 +145,70 @@ public final class ScanFilter implements Parcelable { /** * A {@link android.os.Parcelable.Creator} to create {@link ScanFilter} from parcel. */ - public static final Creator<ScanFilter> - CREATOR = new Creator<ScanFilter>() { + public static final Creator<ScanFilter> CREATOR = + new Creator<ScanFilter>() { - @Override - public ScanFilter[] newArray(int size) { - return new ScanFilter[size]; - } - - @Override - public ScanFilter createFromParcel(Parcel in) { - Builder builder = new Builder(); - if (in.readInt() == 1) { - builder.setDeviceName(in.readString()); - } - if (in.readInt() == 1) { - builder.setDeviceAddress(in.readString()); - } - if (in.readInt() == 1) { - ParcelUuid uuid = in.readParcelable(ParcelUuid.class.getClassLoader()); - builder.setServiceUuid(uuid); - if (in.readInt() == 1) { - ParcelUuid uuidMask = in.readParcelable( - ParcelUuid.class.getClassLoader()); - builder.setServiceUuid(uuid, uuidMask); - } - } - if (in.readInt() == 1) { - ParcelUuid servcieDataUuid = - in.readParcelable(ParcelUuid.class.getClassLoader()); - if (in.readInt() == 1) { - int serviceDataLength = in.readInt(); - byte[] serviceData = new byte[serviceDataLength]; - in.readByteArray(serviceData); - if (in.readInt() == 0) { - builder.setServiceData(servcieDataUuid, serviceData); - } else { - int serviceDataMaskLength = in.readInt(); - byte[] serviceDataMask = new byte[serviceDataMaskLength]; - in.readByteArray(serviceDataMask); - builder.setServiceData( - servcieDataUuid, serviceData, serviceDataMask); - } - } - } + @Override + public ScanFilter[] newArray(int size) { + return new ScanFilter[size]; + } - int manufacturerId = in.readInt(); - if (in.readInt() == 1) { - int manufacturerDataLength = in.readInt(); - byte[] manufacturerData = new byte[manufacturerDataLength]; - in.readByteArray(manufacturerData); - if (in.readInt() == 0) { - builder.setManufacturerData(manufacturerId, manufacturerData); - } else { - int manufacturerDataMaskLength = in.readInt(); - byte[] manufacturerDataMask = new byte[manufacturerDataMaskLength]; - in.readByteArray(manufacturerDataMask); - builder.setManufacturerData(manufacturerId, manufacturerData, - manufacturerDataMask); - } + @Override + public ScanFilter createFromParcel(Parcel in) { + Builder builder = new Builder(); + if (in.readInt() == 1) { + builder.setDeviceName(in.readString()); + } + if (in.readInt() == 1) { + builder.setDeviceAddress(in.readString()); + } + if (in.readInt() == 1) { + ParcelUuid uuid = in.readParcelable(ParcelUuid.class.getClassLoader()); + builder.setServiceUuid(uuid); + if (in.readInt() == 1) { + ParcelUuid uuidMask = in.readParcelable( + ParcelUuid.class.getClassLoader()); + builder.setServiceUuid(uuid, uuidMask); + } + } + if (in.readInt() == 1) { + ParcelUuid servcieDataUuid = + in.readParcelable(ParcelUuid.class.getClassLoader()); + if (in.readInt() == 1) { + int serviceDataLength = in.readInt(); + byte[] serviceData = new byte[serviceDataLength]; + in.readByteArray(serviceData); + if (in.readInt() == 0) { + builder.setServiceData(servcieDataUuid, serviceData); + } else { + int serviceDataMaskLength = in.readInt(); + byte[] serviceDataMask = new byte[serviceDataMaskLength]; + in.readByteArray(serviceDataMask); + builder.setServiceData( + servcieDataUuid, serviceData, serviceDataMask); } + } + } - return builder.build(); + int manufacturerId = in.readInt(); + if (in.readInt() == 1) { + int manufacturerDataLength = in.readInt(); + byte[] manufacturerData = new byte[manufacturerDataLength]; + in.readByteArray(manufacturerData); + if (in.readInt() == 0) { + builder.setManufacturerData(manufacturerId, manufacturerData); + } else { + int manufacturerDataMaskLength = in.readInt(); + byte[] manufacturerDataMask = new byte[manufacturerDataMaskLength]; + in.readByteArray(manufacturerDataMask); + builder.setManufacturerData(manufacturerId, manufacturerData, + manufacturerDataMask); } - }; + } + + return builder.build(); + } + }; /** * Returns the filter set the device name field of Bluetooth advertisement data. @@ -288,7 +288,7 @@ public final class ScanFilter implements Parcelable { // Scan record is null but there exist filters on it. if (scanRecord == null && (mDeviceName != null || mServiceUuid != null || mManufacturerData != null - || mServiceData != null)) { + || mServiceData != null)) { return false; } @@ -386,12 +386,12 @@ public final class ScanFilter implements Parcelable { @Override public int hashCode() { return Objects.hash(mDeviceName, mDeviceAddress, mManufacturerId, - Arrays.hashCode(mManufacturerData), - Arrays.hashCode(mManufacturerDataMask), - mServiceDataUuid, - Arrays.hashCode(mServiceData), - Arrays.hashCode(mServiceDataMask), - mServiceUuid, mServiceUuidMask); + Arrays.hashCode(mManufacturerData), + Arrays.hashCode(mManufacturerDataMask), + mServiceDataUuid, + Arrays.hashCode(mServiceData), + Arrays.hashCode(mServiceDataMask), + mServiceUuid, mServiceUuidMask); } @Override @@ -403,20 +403,21 @@ public final class ScanFilter implements Parcelable { return false; } ScanFilter other = (ScanFilter) obj; - return Objects.equals(mDeviceName, other.mDeviceName) && - Objects.equals(mDeviceAddress, other.mDeviceAddress) && - mManufacturerId == other.mManufacturerId && - Objects.deepEquals(mManufacturerData, other.mManufacturerData) && - Objects.deepEquals(mManufacturerDataMask, other.mManufacturerDataMask) && - Objects.equals(mServiceDataUuid, other.mServiceDataUuid) && - Objects.deepEquals(mServiceData, other.mServiceData) && - Objects.deepEquals(mServiceDataMask, other.mServiceDataMask) && - Objects.equals(mServiceUuid, other.mServiceUuid) && - Objects.equals(mServiceUuidMask, other.mServiceUuidMask); + return Objects.equals(mDeviceName, other.mDeviceName) + && Objects.equals(mDeviceAddress, other.mDeviceAddress) + && mManufacturerId == other.mManufacturerId + && Objects.deepEquals(mManufacturerData, other.mManufacturerData) + && Objects.deepEquals(mManufacturerDataMask, other.mManufacturerDataMask) + && Objects.equals(mServiceDataUuid, other.mServiceDataUuid) + && Objects.deepEquals(mServiceData, other.mServiceData) + && Objects.deepEquals(mServiceDataMask, other.mServiceDataMask) + && Objects.equals(mServiceUuid, other.mServiceUuid) + && Objects.equals(mServiceUuidMask, other.mServiceUuidMask); } /** * Checks if the scanfilter is empty + * * @hide */ public boolean isAllFieldsEmpty() { @@ -454,8 +455,8 @@ public final class ScanFilter implements Parcelable { * Set filter on device address. * * @param deviceAddress The device Bluetooth address for the filter. It needs to be in the - * format of "01:02:03:AB:CD:EF". The device address can be validated using - * {@link BluetoothAdapter#checkBluetoothAddress}. + * format of "01:02:03:AB:CD:EF". The device address can be validated using {@link + * BluetoothAdapter#checkBluetoothAddress}. * @throws IllegalArgumentException If the {@code deviceAddress} is invalid. */ public Builder setDeviceAddress(String deviceAddress) { @@ -480,8 +481,8 @@ public final class ScanFilter implements Parcelable { * {@code serviceUuid}. Set any bit in the mask to 1 to indicate a match is needed for the * bit in {@code serviceUuid}, and 0 to ignore that bit. * - * @throws IllegalArgumentException If {@code serviceUuid} is {@code null} but - * {@code uuidMask} is not {@code null}. + * @throws IllegalArgumentException If {@code serviceUuid} is {@code null} but {@code + * uuidMask} is not {@code null}. */ public Builder setServiceUuid(ParcelUuid serviceUuid, ParcelUuid uuidMask) { if (mUuidMask != null && mServiceUuid == null) { @@ -513,9 +514,9 @@ public final class ScanFilter implements Parcelable { * <p> * The {@code serviceDataMask} must have the same length of the {@code serviceData}. * - * @throws IllegalArgumentException If {@code serviceDataUuid} is null or - * {@code serviceDataMask} is {@code null} while {@code serviceData} is not or - * {@code serviceDataMask} and {@code serviceData} has different length. + * @throws IllegalArgumentException If {@code serviceDataUuid} is null or {@code + * serviceDataMask} is {@code null} while {@code serviceData} is not or {@code + * serviceDataMask} and {@code serviceData} has different length. */ public Builder setServiceData(ParcelUuid serviceDataUuid, byte[] serviceData, byte[] serviceDataMask) { @@ -563,10 +564,9 @@ public final class ScanFilter implements Parcelable { * <p> * The {@code manufacturerDataMask} must have the same length of {@code manufacturerData}. * - * @throws IllegalArgumentException If the {@code manufacturerId} is invalid, or - * {@code manufacturerData} is null while {@code manufacturerDataMask} is not, - * or {@code manufacturerData} and {@code manufacturerDataMask} have different - * length. + * @throws IllegalArgumentException If the {@code manufacturerId} is invalid, or {@code + * manufacturerData} is null while {@code manufacturerDataMask} is not, or {@code + * manufacturerData} and {@code manufacturerDataMask} have different length. */ public Builder setManufacturerData(int manufacturerId, byte[] manufacturerData, byte[] manufacturerDataMask) { diff --git a/core/java/android/bluetooth/le/ScanRecord.java b/core/java/android/bluetooth/le/ScanRecord.java index 914e8fd9e07f..f8aaba910b7b 100644 --- a/core/java/android/bluetooth/le/ScanRecord.java +++ b/core/java/android/bluetooth/le/ScanRecord.java @@ -231,9 +231,9 @@ public final class ScanRecord { case DATA_TYPE_SERVICE_DATA_128_BIT: int serviceUuidLength = BluetoothUuid.UUID_BYTES_16_BIT; if (fieldType == DATA_TYPE_SERVICE_DATA_32_BIT) { - serviceUuidLength = BluetoothUuid.UUID_BYTES_32_BIT; + serviceUuidLength = BluetoothUuid.UUID_BYTES_32_BIT; } else if (fieldType == DATA_TYPE_SERVICE_DATA_128_BIT) { - serviceUuidLength = BluetoothUuid.UUID_BYTES_128_BIT; + serviceUuidLength = BluetoothUuid.UUID_BYTES_128_BIT; } byte[] serviceDataUuidBytes = extractBytes(scanRecord, currentPos, @@ -247,8 +247,8 @@ public final class ScanRecord { case DATA_TYPE_MANUFACTURER_SPECIFIC_DATA: // The first two bytes of the manufacturer specific data are // manufacturer ids in little endian. - int manufacturerId = ((scanRecord[currentPos + 1] & 0xFF) << 8) + - (scanRecord[currentPos] & 0xFF); + int manufacturerId = ((scanRecord[currentPos + 1] & 0xFF) << 8) + + (scanRecord[currentPos] & 0xFF); byte[] manufacturerDataBytes = extractBytes(scanRecord, currentPos + 2, dataLength - 2); manufacturerData.put(manufacturerId, manufacturerDataBytes); @@ -276,7 +276,8 @@ public final class ScanRecord { @Override public String toString() { return "ScanRecord [mAdvertiseFlags=" + mAdvertiseFlags + ", mServiceUuids=" + mServiceUuids - + ", mManufacturerSpecificData=" + BluetoothLeUtils.toString(mManufacturerSpecificData) + + ", mManufacturerSpecificData=" + BluetoothLeUtils.toString( + mManufacturerSpecificData) + ", mServiceData=" + BluetoothLeUtils.toString(mServiceData) + ", mTxPowerLevel=" + mTxPowerLevel + ", mDeviceName=" + mDeviceName + "]"; } diff --git a/core/java/android/bluetooth/le/ScanResult.java b/core/java/android/bluetooth/le/ScanResult.java index e552398e9e26..f87a47fb936b 100644 --- a/core/java/android/bluetooth/le/ScanResult.java +++ b/core/java/android/bluetooth/le/ScanResult.java @@ -98,8 +98,10 @@ public final class ScanResult implements Parcelable { * @param scanRecord Scan record including both advertising data and scan response data. * @param rssi Received signal strength. * @param timestampNanos Timestamp at which the scan result was observed. - * @deprecated use {@link #ScanResult(BluetoothDevice, int, int, int, int, int, int, int, ScanRecord, long)} + * @deprecated use {@link #ScanResult(BluetoothDevice, int, int, int, int, int, int, int, + * ScanRecord, long)} */ + @Deprecated public ScanResult(BluetoothDevice device, ScanRecord scanRecord, int rssi, long timestampNanos) { mDevice = device; @@ -129,8 +131,8 @@ public final class ScanResult implements Parcelable { * @param timestampNanos Timestamp at which the scan result was observed. */ public ScanResult(BluetoothDevice device, int eventType, int primaryPhy, int secondaryPhy, - int advertisingSid, int txPower, int rssi, int periodicAdvertisingInterval, - ScanRecord scanRecord, long timestampNanos) { + int advertisingSid, int txPower, int rssi, int periodicAdvertisingInterval, + ScanRecord scanRecord, long timestampNanos) { mDevice = device; mEventType = eventType; mPrimaryPhy = primaryPhy; @@ -254,7 +256,9 @@ public final class ScanResult implements Parcelable { * Can be one of {@link BluetoothDevice#PHY_LE_1M} or * {@link BluetoothDevice#PHY_LE_CODED}. */ - public int getPrimaryPhy() { return mPrimaryPhy; } + public int getPrimaryPhy() { + return mPrimaryPhy; + } /** * Returns the secondary Physical Layer @@ -264,21 +268,27 @@ public final class ScanResult implements Parcelable { * or {@link ScanResult#PHY_UNUSED} - if the advertisement * was not received on a secondary physical channel. */ - public int getSecondaryPhy() { return mSecondaryPhy; } + public int getSecondaryPhy() { + return mSecondaryPhy; + } /** * Returns the advertising set id. * May return {@link ScanResult#SID_NOT_PRESENT} if * no set id was is present. */ - public int getAdvertisingSid() { return mAdvertisingSid; } + public int getAdvertisingSid() { + return mAdvertisingSid; + } /** * Returns the transmit power in dBm. * Valid range is [-127, 126]. A value of {@link ScanResult#TX_POWER_NOT_PRESENT} * indicates that the TX power is not present. */ - public int getTxPower() { return mTxPower; } + public int getTxPower() { + return mTxPower; + } /** * Returns the periodic advertising interval in units of 1.25ms. @@ -293,9 +303,9 @@ public final class ScanResult implements Parcelable { @Override public int hashCode() { return Objects.hash(mDevice, mRssi, mScanRecord, mTimestampNanos, - mEventType, mPrimaryPhy, mSecondaryPhy, - mAdvertisingSid, mTxPower, - mPeriodicAdvertisingInterval); + mEventType, mPrimaryPhy, mSecondaryPhy, + mAdvertisingSid, mTxPower, + mPeriodicAdvertisingInterval); } @Override @@ -307,34 +317,34 @@ public final class ScanResult implements Parcelable { return false; } ScanResult other = (ScanResult) obj; - return Objects.equals(mDevice, other.mDevice) && (mRssi == other.mRssi) && - Objects.equals(mScanRecord, other.mScanRecord) && - (mTimestampNanos == other.mTimestampNanos) && - mEventType == other.mEventType && - mPrimaryPhy == other.mPrimaryPhy && - mSecondaryPhy == other.mSecondaryPhy && - mAdvertisingSid == other.mAdvertisingSid && - mTxPower == other.mTxPower && - mPeriodicAdvertisingInterval == other.mPeriodicAdvertisingInterval; + return Objects.equals(mDevice, other.mDevice) && (mRssi == other.mRssi) + && Objects.equals(mScanRecord, other.mScanRecord) + && (mTimestampNanos == other.mTimestampNanos) + && mEventType == other.mEventType + && mPrimaryPhy == other.mPrimaryPhy + && mSecondaryPhy == other.mSecondaryPhy + && mAdvertisingSid == other.mAdvertisingSid + && mTxPower == other.mTxPower + && mPeriodicAdvertisingInterval == other.mPeriodicAdvertisingInterval; } @Override public String toString() { - return "ScanResult{" + "device=" + mDevice + ", scanRecord=" + - Objects.toString(mScanRecord) + ", rssi=" + mRssi + - ", timestampNanos=" + mTimestampNanos + ", eventType=" + mEventType + - ", primaryPhy=" + mPrimaryPhy + ", secondaryPhy=" + mSecondaryPhy + - ", advertisingSid=" + mAdvertisingSid + ", txPower=" + mTxPower + - ", periodicAdvertisingInterval=" + mPeriodicAdvertisingInterval + '}'; + return "ScanResult{" + "device=" + mDevice + ", scanRecord=" + + Objects.toString(mScanRecord) + ", rssi=" + mRssi + + ", timestampNanos=" + mTimestampNanos + ", eventType=" + mEventType + + ", primaryPhy=" + mPrimaryPhy + ", secondaryPhy=" + mSecondaryPhy + + ", advertisingSid=" + mAdvertisingSid + ", txPower=" + mTxPower + + ", periodicAdvertisingInterval=" + mPeriodicAdvertisingInterval + '}'; } public static final Parcelable.Creator<ScanResult> CREATOR = new Creator<ScanResult>() { - @Override + @Override public ScanResult createFromParcel(Parcel source) { return new ScanResult(source); } - @Override + @Override public ScanResult[] newArray(int size) { return new ScanResult[size]; } diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java index 36e48e9bd0b8..35ed424aa2db 100644 --- a/core/java/android/bluetooth/le/ScanSettings.java +++ b/core/java/android/bluetooth/le/ScanSettings.java @@ -202,8 +202,8 @@ public final class ScanSettings implements Parcelable { } private ScanSettings(int scanMode, int callbackType, int scanResultType, - long reportDelayMillis, int matchMode, - int numOfMatchesPerFilter, boolean legacy, int phy) { + long reportDelayMillis, int matchMode, + int numOfMatchesPerFilter, boolean legacy, int phy) { mScanMode = scanMode; mCallbackType = callbackType; mScanResultType = scanResultType; @@ -221,7 +221,7 @@ public final class ScanSettings implements Parcelable { mReportDelayMillis = in.readLong(); mMatchMode = in.readInt(); mNumOfMatchesPerFilter = in.readInt(); - mLegacy = in.readInt() != 0 ? true : false; + mLegacy = in.readInt() != 0; mPhy = in.readInt(); } @@ -242,18 +242,18 @@ public final class ScanSettings implements Parcelable { return 0; } - public static final Parcelable.Creator<ScanSettings> - CREATOR = new Creator<ScanSettings>() { - @Override - public ScanSettings[] newArray(int size) { - return new ScanSettings[size]; - } + public static final Parcelable.Creator<ScanSettings> CREATOR = + new Creator<ScanSettings>() { + @Override + public ScanSettings[] newArray(int size) { + return new ScanSettings[size]; + } - @Override - public ScanSettings createFromParcel(Parcel in) { - return new ScanSettings(in); - } - }; + @Override + public ScanSettings createFromParcel(Parcel in) { + return new ScanSettings(in); + } + }; /** * Builder for {@link ScanSettings}. @@ -264,7 +264,7 @@ public final class ScanSettings implements Parcelable { private int mScanResultType = SCAN_RESULT_TYPE_FULL; private long mReportDelayMillis = 0; private int mMatchMode = MATCH_MODE_AGGRESSIVE; - private int mNumOfMatchesPerFilter = MATCH_NUM_MAX_ADVERTISEMENT; + private int mNumOfMatchesPerFilter = MATCH_NUM_MAX_ADVERTISEMENT; private boolean mLegacy = true; private int mPhy = PHY_LE_ALL_SUPPORTED; @@ -272,8 +272,7 @@ public final class ScanSettings implements Parcelable { * Set scan mode for Bluetooth LE scan. * * @param scanMode The scan mode can be one of {@link ScanSettings#SCAN_MODE_LOW_POWER}, - * {@link ScanSettings#SCAN_MODE_BALANCED} or - * {@link ScanSettings#SCAN_MODE_LOW_LATENCY}. + * {@link ScanSettings#SCAN_MODE_BALANCED} or {@link ScanSettings#SCAN_MODE_LOW_LATENCY}. * @throws IllegalArgumentException If the {@code scanMode} is invalid. */ public Builder setScanMode(int scanMode) { @@ -301,9 +300,9 @@ public final class ScanSettings implements Parcelable { // Returns true if the callbackType is valid. private boolean isValidCallbackType(int callbackType) { - if (callbackType == CALLBACK_TYPE_ALL_MATCHES || - callbackType == CALLBACK_TYPE_FIRST_MATCH || - callbackType == CALLBACK_TYPE_MATCH_LOST) { + if (callbackType == CALLBACK_TYPE_ALL_MATCHES + || callbackType == CALLBACK_TYPE_FIRST_MATCH + || callbackType == CALLBACK_TYPE_MATCH_LOST) { return true; } return callbackType == (CALLBACK_TYPE_FIRST_MATCH | CALLBACK_TYPE_MATCH_LOST); @@ -312,9 +311,8 @@ public final class ScanSettings implements Parcelable { /** * Set scan result type for Bluetooth LE scan. * - * @param scanResultType Type for scan result, could be either - * {@link ScanSettings#SCAN_RESULT_TYPE_FULL} or - * {@link ScanSettings#SCAN_RESULT_TYPE_ABBREVIATED}. + * @param scanResultType Type for scan result, could be either {@link + * ScanSettings#SCAN_RESULT_TYPE_FULL} or {@link ScanSettings#SCAN_RESULT_TYPE_ABBREVIATED}. * @throws IllegalArgumentException If the {@code scanResultType} is invalid. * @hide */ @@ -333,8 +331,8 @@ public final class ScanSettings implements Parcelable { * Set report delay timestamp for Bluetooth LE scan. * * @param reportDelayMillis Delay of report in milliseconds. Set to 0 to be notified of - * results immediately. Values > 0 causes the scan results to be queued up and - * delivered after the requested delay or when the internal buffers fill up. + * results immediately. Values > 0 causes the scan results to be queued up and delivered + * after the requested delay or when the internal buffers fill up. * @throws IllegalArgumentException If {@code reportDelayMillis} < 0. */ public Builder setReportDelay(long reportDelayMillis) { @@ -349,9 +347,9 @@ public final class ScanSettings implements Parcelable { * Set the number of matches for Bluetooth LE scan filters hardware match * * @param numOfMatches The num of matches can be one of - * {@link ScanSettings#MATCH_NUM_ONE_ADVERTISEMENT} or - * {@link ScanSettings#MATCH_NUM_FEW_ADVERTISEMENT} or - * {@link ScanSettings#MATCH_NUM_MAX_ADVERTISEMENT} + * {@link ScanSettings#MATCH_NUM_ONE_ADVERTISEMENT} + * or {@link ScanSettings#MATCH_NUM_FEW_ADVERTISEMENT} or {@link + * ScanSettings#MATCH_NUM_MAX_ADVERTISEMENT} * @throws IllegalArgumentException If the {@code matchMode} is invalid. */ public Builder setNumOfMatches(int numOfMatches) { @@ -366,9 +364,8 @@ public final class ScanSettings implements Parcelable { /** * Set match mode for Bluetooth LE scan filters hardware match * - * @param matchMode The match mode can be one of - * {@link ScanSettings#MATCH_MODE_AGGRESSIVE} or - * {@link ScanSettings#MATCH_MODE_STICKY} + * @param matchMode The match mode can be one of {@link ScanSettings#MATCH_MODE_AGGRESSIVE} + * or {@link ScanSettings#MATCH_MODE_STICKY} * @throws IllegalArgumentException If the {@code matchMode} is invalid. */ public Builder setMatchMode(int matchMode) { @@ -402,10 +399,8 @@ public final class ScanSettings implements Parcelable { * {@link android.bluetooth.BluetoothAdapter#isLeCodedPhySupported}. * Selecting an unsupported phy will result in failure to start scan. * - * @param phy Can be one of - * {@link BluetoothDevice#PHY_LE_1M}, - * {@link BluetoothDevice#PHY_LE_CODED} or - * {@link ScanSettings#PHY_LE_ALL_SUPPORTED} + * @param phy Can be one of {@link BluetoothDevice#PHY_LE_1M}, {@link + * BluetoothDevice#PHY_LE_CODED} or {@link ScanSettings#PHY_LE_ALL_SUPPORTED} */ public Builder setPhy(int phy) { mPhy = phy; @@ -417,8 +412,8 @@ public final class ScanSettings implements Parcelable { */ public ScanSettings build() { return new ScanSettings(mScanMode, mCallbackType, mScanResultType, - mReportDelayMillis, mMatchMode, - mNumOfMatchesPerFilter, mLegacy, mPhy); + mReportDelayMillis, mMatchMode, + mNumOfMatchesPerFilter, mLegacy, mPhy); } } } diff --git a/core/java/android/bluetooth/le/TruncatedFilter.java b/core/java/android/bluetooth/le/TruncatedFilter.java index 685b1748f9a5..a753aa6fef17 100644 --- a/core/java/android/bluetooth/le/TruncatedFilter.java +++ b/core/java/android/bluetooth/le/TruncatedFilter.java @@ -17,6 +17,7 @@ package android.bluetooth.le; import android.annotation.SystemApi; + import java.util.List; /** diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java index b2952aab2334..1a5de5690cae 100644 --- a/core/java/android/companion/CompanionDeviceManager.java +++ b/core/java/android/companion/CompanionDeviceManager.java @@ -37,6 +37,7 @@ import android.util.Log; import java.util.Collections; import java.util.List; +import java.util.function.BiConsumer; /** * System level service for managing companion devices @@ -271,6 +272,8 @@ public final class CompanionDeviceManager { private Handler mHandler; private AssociationRequest mRequest; + final Object mLock = new Object(); + private CallbackProxy(AssociationRequest request, Callback callback, Handler handler) { mCallback = callback; mHandler = handler; @@ -280,38 +283,44 @@ public final class CompanionDeviceManager { @Override public void onSuccess(PendingIntent launcher) { - Handler handler = mHandler; - if (handler == null) return; - handler.post(() -> { - Callback callback = mCallback; - if (callback == null) return; - callback.onDeviceFound(launcher.getIntentSender()); - }); + lockAndPost(Callback::onDeviceFound, launcher.getIntentSender()); } @Override public void onFailure(CharSequence reason) { - Handler handler = mHandler; - if (handler == null) return; - handler.post(() -> { - Callback callback = mCallback; - if (callback == null) return; - callback.onFailure(reason); - }); + lockAndPost(Callback::onFailure, reason); + } + + <T> void lockAndPost(BiConsumer<Callback, T> action, T payload) { + synchronized (mLock) { + if (mHandler != null) { + mHandler.post(() -> { + Callback callback = null; + synchronized (mLock) { + callback = mCallback; + } + if (callback != null) { + action.accept(callback, payload); + } + }); + } + } } @Override public void onActivityDestroyed(Activity activity) { - if (activity != getActivity()) return; - try { - mService.stopScan(mRequest, this, getCallingPackage()); - } catch (RemoteException e) { - e.rethrowFromSystemServer(); + synchronized (mLock) { + if (activity != getActivity()) return; + try { + mService.stopScan(mRequest, this, getCallingPackage()); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + getActivity().getApplication().unregisterActivityLifecycleCallbacks(this); + mCallback = null; + mHandler = null; + mRequest = null; } - getActivity().getApplication().unregisterActivityLifecycleCallbacks(this); - mCallback = null; - mHandler = null; - mRequest = null; } @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) {} diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index bd0228e8049d..08acfb651b18 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2225,7 +2225,12 @@ public class Intent implements Parcelable, Cloneable { * Note that the cleared package does <em>not</em> * receive this broadcast. The data contains the name of the package. * <ul> - * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package. + * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package. If the + * package whose data was cleared is an uninstalled instant app, then the UID + * will be -1. The platform keeps some meta-data associated with instant apps + * after they are uninstalled. + * <li> {@link #EXTRA_PACKAGE_NAME} containing the package name only if the cleared + * data was for an instant app. * </ul> * * <p class="note">This is a protected intent that can only be sent @@ -3950,6 +3955,16 @@ public class Intent implements Parcelable, Cloneable { @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String CATEGORY_SETUP_WIZARD = "android.intent.category.SETUP_WIZARD"; /** + * This is the home activity, that is the activity that serves as the launcher app + * from there the user can start other apps. Often components with lower/higher + * priority intent filters handle the home intent, for example SetupWizard, to + * setup the device and we need to be able to distinguish the home app from these + * setup helpers. + * @hide + */ + @SdkConstant(SdkConstantType.INTENT_CATEGORY) + public static final String CATEGORY_LAUNCHER_APP = "android.intent.category.LAUNCHER_APP"; + /** * This activity is a preference panel. */ @SdkConstant(SdkConstantType.INTENT_CATEGORY) diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index ca5fa6be1323..48587b3630d9 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -780,6 +780,13 @@ public class ActivityInfo extends ComponentInfo * constant starts at the high bits. */ public static final int CONFIG_FONT_SCALE = 0x40000000; + /** + * Bit indicating changes to window configuration that isn't exposed to apps. + * This is for internal use only and apps don't handle it. + * @hide + * {@link Configuration}. + */ + public static final int CONFIG_WINDOW_CONFIGURATION = 0x20000000; /** @hide * Unfortunately the constants for config changes in native code are @@ -1096,12 +1103,12 @@ public class ActivityInfo extends ComponentInfo } /** @hide */ - public void dump(Printer pw, String prefix, int flags) { + public void dump(Printer pw, String prefix, int dumpFlags) { super.dumpFront(pw, prefix); if (permission != null) { pw.println(prefix + "permission=" + permission); } - if ((flags&DUMP_FLAG_DETAILS) != 0) { + if ((dumpFlags & DUMP_FLAG_DETAILS) != 0) { pw.println(prefix + "taskAffinity=" + taskAffinity + " targetActivity=" + targetActivity + " persistableMode=" + persistableModeToString()); @@ -1120,7 +1127,7 @@ public class ActivityInfo extends ComponentInfo if (uiOptions != 0) { pw.println(prefix + " uiOptions=0x" + Integer.toHexString(uiOptions)); } - if ((flags&DUMP_FLAG_DETAILS) != 0) { + if ((dumpFlags & DUMP_FLAG_DETAILS) != 0) { pw.println(prefix + "lockTaskLaunchMode=" + lockTaskLaunchModeToString(lockTaskLaunchMode)); } @@ -1136,7 +1143,7 @@ public class ActivityInfo extends ComponentInfo if (maxAspectRatio != 0) { pw.println(prefix + "maxAspectRatio=" + maxAspectRatio); } - super.dumpBack(pw, prefix, flags); + super.dumpBack(pw, prefix, dumpFlags); } public String toString() { diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 72075a515e02..ad7a5ab10e41 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -1046,22 +1046,22 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { } /** @hide */ - public void dump(Printer pw, String prefix, int flags) { + public void dump(Printer pw, String prefix, int dumpFlags) { super.dumpFront(pw, prefix); - if ((flags&DUMP_FLAG_DETAILS) != 0 && className != null) { + if ((dumpFlags & DUMP_FLAG_DETAILS) != 0 && className != null) { pw.println(prefix + "className=" + className); } if (permission != null) { pw.println(prefix + "permission=" + permission); } pw.println(prefix + "processName=" + processName); - if ((flags&DUMP_FLAG_DETAILS) != 0) { + if ((dumpFlags & DUMP_FLAG_DETAILS) != 0) { pw.println(prefix + "taskAffinity=" + taskAffinity); } pw.println(prefix + "uid=" + uid + " flags=0x" + Integer.toHexString(flags) + " privateFlags=0x" + Integer.toHexString(privateFlags) + " theme=0x" + Integer.toHexString(theme)); - if ((flags&DUMP_FLAG_DETAILS) != 0) { + if ((dumpFlags & DUMP_FLAG_DETAILS) != 0) { pw.println(prefix + "requiresSmallestWidthDp=" + requiresSmallestWidthDp + " compatibleWidthLimitDp=" + compatibleWidthLimitDp + " largestWidthLimitDp=" + largestWidthLimitDp); @@ -1080,12 +1080,12 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { if (resourceDirs != null) { pw.println(prefix + "resourceDirs=" + Arrays.toString(resourceDirs)); } - if ((flags&DUMP_FLAG_DETAILS) != 0 && seInfo != null) { + if ((dumpFlags & DUMP_FLAG_DETAILS) != 0 && seInfo != null) { pw.println(prefix + "seinfo=" + seInfo); pw.println(prefix + "seinfoUser=" + seInfoUser); } pw.println(prefix + "dataDir=" + dataDir); - if ((flags&DUMP_FLAG_DETAILS) != 0) { + if ((dumpFlags & DUMP_FLAG_DETAILS) != 0) { pw.println(prefix + "deviceProtectedDataDir=" + deviceProtectedDataDir); pw.println(prefix + "credentialProtectedDataDir=" + credentialProtectedDataDir); if (sharedLibraryFiles != null) { @@ -1104,7 +1104,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { + " targetSdkVersion=" + targetSdkVersion + " versionCode=" + versionCode + " targetSandboxVersion=" + targetSandboxVersion); - if ((flags&DUMP_FLAG_DETAILS) != 0) { + if ((dumpFlags & DUMP_FLAG_DETAILS) != 0) { if (manageSpaceActivityName != null) { pw.println(prefix + "manageSpaceActivityName=" + manageSpaceActivityName); } @@ -1508,6 +1508,11 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE) != 0; } + /** @hide */ + public boolean isEncryptionAware() { + return isDirectBootAware() || isPartiallyDirectBootAware(); + } + /** * @hide */ diff --git a/core/java/android/content/pm/BaseParceledListSlice.java b/core/java/android/content/pm/BaseParceledListSlice.java index aaa5f19c3fca..5877a09b7759 100644 --- a/core/java/android/content/pm/BaseParceledListSlice.java +++ b/core/java/android/content/pm/BaseParceledListSlice.java @@ -102,7 +102,7 @@ abstract class BaseParceledListSlice<T> implements Parcelable { return; } while (i < N && reply.readInt() != 0) { - final T parcelable = reply.readCreator(creator, loader); + final T parcelable = readCreator(creator, reply, loader); verifySameType(listElementClass, parcelable.getClass()); mList.add(parcelable); diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java index 53be9537d00d..6b1222f53959 100644 --- a/core/java/android/content/pm/ComponentInfo.java +++ b/core/java/android/content/pm/ComponentInfo.java @@ -183,12 +183,12 @@ public class ComponentInfo extends PackageItemInfo { protected void dumpBack(Printer pw, String prefix) { dumpBack(pw, prefix, DUMP_FLAG_ALL); } - - void dumpBack(Printer pw, String prefix, int flags) { - if ((flags&DUMP_FLAG_APPLICATION) != 0) { + + void dumpBack(Printer pw, String prefix, int dumpFlags) { + if ((dumpFlags & DUMP_FLAG_APPLICATION) != 0) { if (applicationInfo != null) { pw.println(prefix + "ApplicationInfo:"); - applicationInfo.dump(pw, prefix + " ", flags); + applicationInfo.dump(pw, prefix + " ", dumpFlags); } else { pw.println(prefix + "ApplicationInfo: null"); } diff --git a/core/java/android/content/pm/InstantAppRequest.java b/core/java/android/content/pm/InstantAppRequest.java index 27d28287b6ae..38f02256ee6e 100644 --- a/core/java/android/content/pm/InstantAppRequest.java +++ b/core/java/android/content/pm/InstantAppRequest.java @@ -38,14 +38,18 @@ public final class InstantAppRequest { * Optional extra bundle provided by the source application to the installer for additional * verification. */ public final Bundle verificationBundle; + /** Whether resolution occurs because an application is starting */ + public final boolean resolveForStart; public InstantAppRequest(AuxiliaryResolveInfo responseObj, Intent origIntent, - String resolvedType, String callingPackage, int userId, Bundle verificationBundle) { + String resolvedType, String callingPackage, int userId, Bundle verificationBundle, + boolean resolveForStart) { this.responseObj = responseObj; this.origIntent = origIntent; this.resolvedType = resolvedType; this.callingPackage = callingPackage; this.userId = userId; this.verificationBundle = verificationBundle; + this.resolveForStart = resolveForStart; } } diff --git a/core/java/android/content/pm/InstantAppResolveInfo.java b/core/java/android/content/pm/InstantAppResolveInfo.java index dcaf66ebc43b..22e994f4cfa8 100644 --- a/core/java/android/content/pm/InstantAppResolveInfo.java +++ b/core/java/android/content/pm/InstantAppResolveInfo.java @@ -37,7 +37,7 @@ import java.util.Locale; @SystemApi public final class InstantAppResolveInfo implements Parcelable { /** Algorithm that will be used to generate the domain digest */ - public static final String SHA_ALGORITHM = "SHA-256"; + private static final String SHA_ALGORITHM = "SHA-256"; private final InstantAppDigest mDigest; private final String mPackageName; diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java index cf0edcad7e2b..ba488f6a0518 100644 --- a/core/java/android/content/pm/PackageInfo.java +++ b/core/java/android/content/pm/PackageInfo.java @@ -187,8 +187,17 @@ public class PackageInfo implements Parcelable { public static final int REQUESTED_PERMISSION_GRANTED = 1<<1; /** - * Array of all signatures read from the package file. This is only filled - * in if the flag {@link PackageManager#GET_SIGNATURES} was set. + * Array of all signatures read from the package file. This is only filled + * in if the flag {@link PackageManager#GET_SIGNATURES} was set. A package + * must be singed with at least one certificate which is at position zero. + * The package can be signed with additional certificates which appear as + * subsequent entries. + * + * <strong>Note:</strong> Signature ordering is not guaranteed to be + * stable which means that a package signed with certificates A and B is + * equivalent to being signed with certificates B and A. This means that + * in case multiple signatures are reported you cannot assume the one at + * the first position to be the same across updates. */ public Signature[] signatures; diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 449b4a999c42..ef8f84bd1690 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1904,10 +1904,16 @@ public abstract class PackageManager { * Feature for {@link #getSystemAvailableFeatures} and * {@link #hasSystemFeature(String, int)}: If this feature is supported, the Vulkan native API * will enumerate at least one {@code VkPhysicalDevice}, and the feature version will indicate - * what level of optional compute features are supported beyond the Vulkan 1.0 requirements. + * what level of optional compute features that device supports beyond the Vulkan 1.0 + * requirements. * <p> - * Compute level 0 indicates support for the {@code VariablePointers} SPIR-V capability defined - * by the SPV_KHR_variable_pointers extension. + * Compute level 0 indicates: + * <ul> + * <li>The {@code VK_KHR_variable_pointers} extension and + * {@code VkPhysicalDeviceVariablePointerFeaturesKHR::variablePointers} feature are + supported.</li> + * <li>{@code VkPhysicalDeviceLimits::maxPerStageDescriptorStorageBuffers} is at least 16.</li> + * </ul> */ @SdkConstant(SdkConstantType.FEATURE) public static final String FEATURE_VULKAN_HARDWARE_COMPUTE = "android.hardware.vulkan.compute"; diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 99700df2b990..e8bade9b2c94 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -20,7 +20,6 @@ import android.content.ComponentName; import android.content.Intent; import android.content.pm.PackageManager.ApplicationInfoFlags; import android.content.pm.PackageManager.ComponentInfoFlags; -import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.PackageInfoFlags; import android.content.pm.PackageManager.ResolveInfoFlags; import android.os.Bundle; @@ -372,4 +371,11 @@ public abstract class PackageManagerInternal { /** Whether the binder caller can access instant apps. */ public abstract boolean canAccessInstantApps(int callingUid, int userId); + + /** + * Returns {@code true} if a given package has instant application meta-data. + * Otherwise, returns {@code false}. Meta-data is state (eg. cookie, app icon, etc) + * associated with an instant app. It may be kept after the instant app has been uninstalled. + */ + public abstract boolean hasInstantApplicationMetadata(String packageName, int userId); } diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 07ce4e9c5d8a..8b54b0d8b52a 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -97,6 +97,7 @@ import com.android.internal.util.XmlUtils; import libcore.io.IoUtils; +import libcore.util.EmptyArray; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -158,8 +159,6 @@ public class PackageParser { private static final boolean MULTI_PACKAGE_APK_ENABLED = Build.IS_DEBUGGABLE && SystemProperties.getBoolean(PROPERTY_CHILD_PACKAGES_ENABLED, false); - private static final int MAX_PACKAGES_PER_APK = 5; - public static final int APK_SIGNING_UNKNOWN = 0; public static final int APK_SIGNING_V1 = 1; public static final int APK_SIGNING_V2 = 2; @@ -1120,12 +1119,12 @@ public class PackageParser { final String cacheKey = getCacheKey(packageFile, flags); final File cacheFile = new File(mCacheDir, cacheKey); - // If the cache is not up to date, return null. - if (!isCacheUpToDate(packageFile, cacheFile)) { - return null; - } - try { + // If the cache is not up to date, return null. + if (!isCacheUpToDate(packageFile, cacheFile)) { + return null; + } + final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath()); Package p = fromCacheEntry(bytes); if (mCallback != null) { @@ -1140,7 +1139,7 @@ public class PackageParser { } } return p; - } catch (Exception e) { + } catch (Throwable e) { Slog.w(TAG, "Error reading package cache: ", e); // If something went wrong while reading the cache entry, delete the cache file @@ -1158,26 +1157,30 @@ public class PackageParser { return; } - final String cacheKey = getCacheKey(packageFile, flags); - final File cacheFile = new File(mCacheDir, cacheKey); + try { + final String cacheKey = getCacheKey(packageFile, flags); + final File cacheFile = new File(mCacheDir, cacheKey); - if (cacheFile.exists()) { - if (!cacheFile.delete()) { - Slog.e(TAG, "Unable to delete cache file: " + cacheFile); + if (cacheFile.exists()) { + if (!cacheFile.delete()) { + Slog.e(TAG, "Unable to delete cache file: " + cacheFile); + } } - } - final byte[] cacheEntry = toCacheEntry(parsed); + final byte[] cacheEntry = toCacheEntry(parsed); - if (cacheEntry == null) { - return; - } + if (cacheEntry == null) { + return; + } - try (FileOutputStream fos = new FileOutputStream(cacheFile)) { - fos.write(cacheEntry); - } catch (IOException ioe) { - Slog.w(TAG, "Error writing cache entry.", ioe); - cacheFile.delete(); + try (FileOutputStream fos = new FileOutputStream(cacheFile)) { + fos.write(cacheEntry); + } catch (IOException ioe) { + Slog.w(TAG, "Error writing cache entry.", ioe); + cacheFile.delete(); + } + } catch (Throwable e) { + Slog.w(TAG, "Error saving package cache.", e); } } @@ -1938,14 +1941,6 @@ public class PackageParser { */ private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException, IOException { - // Let ppl not abuse this mechanism by limiting the packages per APK - if (parentPkg.childPackages != null && parentPkg.childPackages.size() + 2 - > MAX_PACKAGES_PER_APK) { - outError[0] = "Maximum number of packages per APK is: " + MAX_PACKAGES_PER_APK; - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return false; - } - // Make sure we have a valid child package name String childPackageName = parser.getAttributeValue(null, "package"); if (validateName(childPackageName, true, false) != null) { @@ -2820,14 +2815,14 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestUsesLibrary_name); final int version = sa.getInt( com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary_version, -1); - String certSha256 = sa.getNonResourceString(com.android.internal.R.styleable + String certSha256Digest = sa.getNonResourceString(com.android.internal.R.styleable .AndroidManifestUsesStaticLibrary_certDigest); sa.recycle(); // Since an APK providing a static shared lib can only provide the lib - fail if malformed - if (lname == null || version < 0 || certSha256 == null) { + if (lname == null || version < 0 || certSha256Digest == null) { outError[0] = "Bad uses-static-library declaration name: " + lname + " version: " - + version + " certDigest" + certSha256; + + version + " certDigest" + certSha256Digest; mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; XmlUtils.skipCurrentTag(parser); return false; @@ -2844,18 +2839,75 @@ public class PackageParser { lname = lname.intern(); // We allow ":" delimiters in the SHA declaration as this is the format // emitted by the certtool making it easy for developers to copy/paste. - certSha256 = certSha256.replace(":", "").toLowerCase(); + certSha256Digest = certSha256Digest.replace(":", "").toLowerCase(); + + // Fot apps targeting O-MR1 we require explicit enumeration of all certs. + String[] additionalCertSha256Digests = EmptyArray.STRING; + if (pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.O) { + additionalCertSha256Digests = parseAdditionalCertificates(res, parser, outError); + if (additionalCertSha256Digests == null) { + return false; + } + } else { + XmlUtils.skipCurrentTag(parser); + } + + final String[] certSha256Digests = new String[additionalCertSha256Digests.length + 1]; + certSha256Digests[0] = certSha256Digest; + System.arraycopy(additionalCertSha256Digests, 0, certSha256Digests, + 1, additionalCertSha256Digests.length); + pkg.usesStaticLibraries = ArrayUtils.add(pkg.usesStaticLibraries, lname); pkg.usesStaticLibrariesVersions = ArrayUtils.appendInt( pkg.usesStaticLibrariesVersions, version, true); - pkg.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String.class, - pkg.usesStaticLibrariesCertDigests, certSha256, true); - - XmlUtils.skipCurrentTag(parser); + pkg.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String[].class, + pkg.usesStaticLibrariesCertDigests, certSha256Digests, true); return true; } + private String[] parseAdditionalCertificates(Resources resources, XmlResourceParser parser, + String[] outError) throws XmlPullParserException, IOException { + String[] certSha256Digests = EmptyArray.STRING; + + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + final String nodeName = parser.getName(); + if (nodeName.equals("additional-certificate")) { + final TypedArray sa = resources.obtainAttributes(parser, com.android.internal. + R.styleable.AndroidManifestAdditionalCertificate); + String certSha256Digest = sa.getNonResourceString(com.android.internal. + R.styleable.AndroidManifestAdditionalCertificate_certDigest); + sa.recycle(); + + if (TextUtils.isEmpty(certSha256Digest)) { + outError[0] = "Bad additional-certificate declaration with empty" + + " certDigest:" + certSha256Digest; + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + XmlUtils.skipCurrentTag(parser); + sa.recycle(); + return null; + } + + // We allow ":" delimiters in the SHA declaration as this is the format + // emitted by the certtool making it easy for developers to copy/paste. + certSha256Digest = certSha256Digest.replace(":", "").toLowerCase(); + certSha256Digests = ArrayUtils.appendElement(String.class, + certSha256Digests, certSha256Digest); + } else { + XmlUtils.skipCurrentTag(parser); + } + } + + return certSha256Digests; + } + private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser) throws XmlPullParserException, IOException { TypedArray sa = res.obtainAttributes(parser, @@ -3240,11 +3292,11 @@ public class PackageParser { perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel); if ((perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_FLAGS) != 0) { - if ( (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_EPHEMERAL) == 0 + if ( (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_INSTANT) == 0 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) == 0 && (perm.info.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE) != PermissionInfo.PROTECTION_SIGNATURE) { - outError[0] = "<permission> protectionLevel specifies a non-ephemeral flag but is " + outError[0] = "<permission> protectionLevel specifies a non-instnat flag but is " + "not based on signature type"; mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false; @@ -5822,7 +5874,7 @@ public class PackageParser { public ArrayList<String> usesLibraries = null; public ArrayList<String> usesStaticLibraries = null; public int[] usesStaticLibrariesVersions = null; - public String[] usesStaticLibrariesCertDigests = null; + public String[][] usesStaticLibrariesCertDigests = null; public ArrayList<String> usesOptionalLibraries = null; public String[] usesLibraryFiles = null; @@ -6320,8 +6372,10 @@ public class PackageParser { internStringArrayList(usesStaticLibraries); usesStaticLibrariesVersions = new int[libCount]; dest.readIntArray(usesStaticLibrariesVersions); - usesStaticLibrariesCertDigests = new String[libCount]; - dest.readStringArray(usesStaticLibrariesCertDigests); + usesStaticLibrariesCertDigests = new String[libCount][]; + for (int i = 0; i < libCount; i++) { + usesStaticLibrariesCertDigests[i] = dest.createStringArray(); + } } preferredActivityFilters = new ArrayList<>(); @@ -6467,7 +6521,9 @@ public class PackageParser { dest.writeInt(usesStaticLibraries.size()); dest.writeStringList(usesStaticLibraries); dest.writeIntArray(usesStaticLibrariesVersions); - dest.writeStringArray(usesStaticLibrariesCertDigests); + for (String[] usesStaticLibrariesCertDigest : usesStaticLibrariesCertDigests) { + dest.writeStringArray(usesStaticLibrariesCertDigest); + } } dest.writeParcelableList(preferredActivityFilters, flags); diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java index 71a632189796..b84c1b93068d 100644 --- a/core/java/android/content/pm/PermissionInfo.java +++ b/core/java/android/content/pm/PermissionInfo.java @@ -122,13 +122,10 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { /** * Additional flag for {@link #protectionLevel}, corresponding - * to the <code>ephemeral</code> value of + * to the <code>instant</code> value of * {@link android.R.attr#protectionLevel}. - * @hide */ - @SystemApi - @TestApi - public static final int PROTECTION_FLAG_EPHEMERAL = 0x1000; + public static final int PROTECTION_FLAG_INSTANT = 0x1000; /** * Additional flag for {@link #protectionLevel}, corresponding @@ -263,8 +260,8 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { if ((level&PermissionInfo.PROTECTION_FLAG_SETUP) != 0) { protLevel += "|setup"; } - if ((level&PermissionInfo.PROTECTION_FLAG_EPHEMERAL) != 0) { - protLevel += "|ephemeral"; + if ((level&PermissionInfo.PROTECTION_FLAG_INSTANT) != 0) { + protLevel += "|instant"; } if ((level&PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) != 0) { protLevel += "|runtime"; diff --git a/core/java/android/content/pm/ProviderInfo.java b/core/java/android/content/pm/ProviderInfo.java index 91dc06e12138..379b7833150c 100644 --- a/core/java/android/content/pm/ProviderInfo.java +++ b/core/java/android/content/pm/ProviderInfo.java @@ -125,11 +125,11 @@ public final class ProviderInfo extends ComponentInfo } /** @hide */ - public void dump(Printer pw, String prefix, int flags) { + public void dump(Printer pw, String prefix, int dumpFlags) { super.dumpFront(pw, prefix); pw.println(prefix + "authority=" + authority); pw.println(prefix + "flags=0x" + Integer.toHexString(flags)); - super.dumpBack(pw, prefix, flags); + super.dumpBack(pw, prefix, dumpFlags); } public int describeContents() { diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java index f312204e9467..799316700b4d 100644 --- a/core/java/android/content/pm/ResolveInfo.java +++ b/core/java/android/content/pm/ResolveInfo.java @@ -282,7 +282,7 @@ public class ResolveInfo implements Parcelable { } /** @hide */ - public void dump(Printer pw, String prefix, int flags) { + public void dump(Printer pw, String prefix, int dumpFlags) { if (filter != null) { pw.println(prefix + "Filter:"); filter.dump(pw, prefix + " "); @@ -302,13 +302,13 @@ public class ResolveInfo implements Parcelable { } if (activityInfo != null) { pw.println(prefix + "ActivityInfo:"); - activityInfo.dump(pw, prefix + " ", flags); + activityInfo.dump(pw, prefix + " ", dumpFlags); } else if (serviceInfo != null) { pw.println(prefix + "ServiceInfo:"); - serviceInfo.dump(pw, prefix + " ", flags); + serviceInfo.dump(pw, prefix + " ", dumpFlags); } else if (providerInfo != null) { pw.println(prefix + "ProviderInfo:"); - providerInfo.dump(pw, prefix + " ", flags); + providerInfo.dump(pw, prefix + " ", dumpFlags); } } diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java index c683ea5d9739..91f884ccd3dc 100644 --- a/core/java/android/content/pm/ServiceInfo.java +++ b/core/java/android/content/pm/ServiceInfo.java @@ -91,13 +91,13 @@ public class ServiceInfo extends ComponentInfo } /** @hide */ - void dump(Printer pw, String prefix, int flags) { + void dump(Printer pw, String prefix, int dumpFlags) { super.dumpFront(pw, prefix); pw.println(prefix + "permission=" + permission); pw.println(prefix + "flags=0x" + Integer.toHexString(flags)); - super.dumpBack(pw, prefix, flags); + super.dumpBack(pw, prefix, dumpFlags); } - + public String toString() { return "ServiceInfo{" + Integer.toHexString(System.identityHashCode(this)) diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java index c0b82b4dfee3..61b0eb0b51f8 100644 --- a/core/java/android/content/pm/ShortcutManager.java +++ b/core/java/android/content/pm/ShortcutManager.java @@ -36,161 +36,72 @@ import com.android.internal.annotations.VisibleForTesting; import java.util.List; /** - * The ShortcutManager manages an app's <em>shortcuts</em>. Shortcuts provide users - * with quick access to activities other than an app's main activity in the currently-active - * launcher. For example, - * an email app may publish the "compose new email" action, which will directly open the - * compose activity. The {@link ShortcutInfo} class contains information about each of the - * shortcuts themselves. + * The ShortcutManager manages an app's <em>shortcuts</em>. Shortcuts provide users with quick + * access to activities other than an app's main activity in the currently-active launcher, provided + * that the launcher supports app shortcuts. For example, an email app may publish the "compose new + * email" action, which will directly open the compose activity. The {@link ShortcutInfo} class + * contains information about each of the shortcuts themselves. * - * <h3>Static Shortcuts and Dynamic Shortcuts</h3> + * <p>This page discusses the implementation details of the <code>ShortcutManager</code> class. For + * guidance on performing operations on app shortcuts within your app, see the + * <a href="/guide/topics/ui/shortcuts.html">App Shortcuts</a> feature guide. * - * <p> - * There are several different types of shortcuts: + * <h3>Shortcut characteristics</h3> * - * <ul> - * <li><p>Static shortcuts are declared in a resource XML file, which is referenced in the publisher - * app's <code>AndroidManifest.xml</code> file. These shortcuts are visually associated with an - * app's launcher icon. - * <p>Static shortcuts are published when an app is installed, and the details of these shortcuts - * change when an app is upgraded with an updated XML file. Static shortcuts are immutable, and - * their definitions, such as icons and labels, cannot be changed dynamically without upgrading the - * publisher app.</li> + * This section describes in-depth details about each shortcut type's usage and availability. * - * <li>Dynamic shortcuts are published at runtime using this class's APIs. These shortcuts are - * visually associated with an app's launcher icon. Apps can publish, update, and remove dynamic - * shortcuts at runtime. - * </ul> + * <p class="note"><b>Important security note:</b> All shortcut information is stored in + * <a href="/training/articles/direct-boot.html">credential encrypted storage</a>, so your app + * cannot access a user's shortcuts until after they've unlocked the device. * - * <p>Only main activities—activities that handle the {@code MAIN} action and the - * {@code LAUNCHER} category—can have shortcuts. - * If an app has multiple main activities, these activities have different sets - * of shortcuts. + * <h4>Static and dynamic shortcuts</h4> * * <p>Static shortcuts and dynamic shortcuts are shown in a supported launcher when the user - * long-presses on an app's launcher icon. Note that the actual gesture may be different - * depending on the launcher app. - * - * <p>Each launcher icon can have at most {@link #getMaxShortcutCountPerActivity()} number of - * static and dynamic shortcuts combined. - * - * - * <h3>Pinning Shortcuts</h3> - * - * <p>Apps running in the foreground can also <em>pin</em> shortcuts at runtime, subject to user - * permission, using this class's APIs. Each pinned shortcut is a copy of a static shortcut or a - * dynamic shortcut. Although users can pin a shortcut multiple times, the system calls the pinning - * API only once to complete the pinning process. Unlike static and dynamic shortcuts, pinned - * shortcuts appear as separate icons, visually distinct from the app's launcher icon, in the - * launcher. There is no limit to the number of pinned shortcuts that an app can create. - * - * <p>Pinned shortcuts <strong>cannot</strong> be removed by publisher apps. They're removed only - * when the user removes them, when the publisher app is uninstalled, or when the user performs the - * clear data action on the publisher app from the device's <b>Settings</b> app. - * - * <p>However, the publisher app can <em>disable</em> pinned shortcuts so they cannot be started. - * See the following sections for details. - * - * <h3>Updating and Disabling Shortcuts</h3> - * - * <p>When a dynamic shortcut is pinned, even when the publisher removes it as a dynamic shortcut, - * the pinned shortcut will still be visible and launchable. This allows an app to have - * more than {@link #getMaxShortcutCountPerActivity()} number of shortcuts. - * - * <p>For example, suppose {@link #getMaxShortcutCountPerActivity()} is 5: - * <ol> - * <li>A chat app publishes 5 dynamic shortcuts for the 5 most recent - * conversations (c1, c2, ..., c5). - * - * <li>The user pins all 5 of the shortcuts. - * - * <li>Later, the user has started 3 additional conversations (c6, c7, and c8), - * so the publisher app - * re-publishes its dynamic shortcuts. The new dynamic shortcut list is: - * c4, c5, ..., c8. - * The publisher app has to remove c1, c2, and c3 because it can't have more than - * 5 dynamic shortcuts. + * performs a specific gesture. On currently-supported launchers, the gesture is a long-press on the + * app's launcher icon, but the actual gesture may be different on other launcher apps. * - * <li>However, even though c1, c2, and c3 are no longer dynamic shortcuts, the pinned - * shortcuts for these conversations are still available and launchable. + * <p>The {@link LauncherApps} class provides APIs for launcher apps to access shortcuts. * - * <li>At this point, the user can access a total of 8 shortcuts that link to activities in - * the publisher app, including the 3 pinned - * shortcuts, even though an app can have at most 5 dynamic shortcuts. - * - * <li>The app can use {@link #updateShortcuts(List)} to update <em>any</em> of the existing - * 8 shortcuts, when, for example, the chat peers' icons have changed. - * </ol> - * The {@link #addDynamicShortcuts(List)} and {@link #setDynamicShortcuts(List)} methods - * can also be used - * to update existing shortcuts with the same IDs, but they <b>cannot</b> be used - * for updating non-dynamic, pinned shortcuts because these two methods try to convert the given - * lists of shortcuts to dynamic shortcuts. + * <h4>Pinned shortcuts</h4> * + * <p>Because pinned shortcuts appear in the launcher itself, they're always visible. A pinned + * shortcut is removed from the launcher only in the following situations: + * <ul> + * <li>The user removes it. + * <li>The publisher app associated with the shortcut is uninstalled. + * <li>The user performs the clear data action on the publisher app from the device's + * <b>Settings</b> app. + * </ul> * - * <h4>Disabling Static Shortcuts</h4> - * <p>When an app is upgraded and the new version - * no longer uses a static shortcut that appeared in the previous version, this deprecated - * shortcut isn't published as a static shortcut. + * <p>Because the system performs + * <a href="/guide/topics/ui/shortcuts.html#backup-and-restore">backup and restore</a> on pinned + * shortcuts automatically, these shortcuts' IDs should contain either stable, constant strings or + * server-side identifiers, rather than identifiers generated locally that might not make sense on + * other devices. * - * <p>If the deprecated shortcut is pinned, then the pinned shortcut will remain on the launcher, - * but it's disabled automatically. When a pinned shortcut is disabled, this class's APIs cannot - * update it. + * <h3>Shortcut display order</h3> * - * <h4>Disabling Dynamic Shortcuts</h4> - * Sometimes pinned shortcuts become obsolete and may not be usable. For example, a pinned shortcut - * to a group chat becomes unusable when the associated group chat is deleted. In cases like this, - * apps should use {@link #disableShortcuts(List)}, which removes the specified dynamic - * shortcuts and also makes any specified pinned shortcuts un-launchable. - * The {@link #disableShortcuts(List, CharSequence)} method can also be used to disable shortcuts - * and show users a custom error message when they attempt to launch the disabled shortcuts. + * <p>When the launcher displays an app's shortcuts, they should appear in the following order: * + * <ul> + * <li>Static shortcuts (if {@link ShortcutInfo#isDeclaredInManifest()} is {@code true}), + * and then show dynamic shortcuts (if {@link ShortcutInfo#isDynamic()} is {@code true}). + * <li>Within each shortcut type (static and dynamic), sort the shortcuts in order of increasing + * rank according to {@link ShortcutInfo#getRank()}. + * </ul> * - * <h3>Publishing Static Shortcuts</h3> + * <p>Shortcut ranks are non-negative, sequential integers that determine the order in which + * shortcuts appear, assuming that the shortcuts are all in the same category. You can update ranks + * of existing shortcuts when you call {@link #updateShortcuts(List)}, + * {@link #addDynamicShortcuts(List)}, or {@link #setDynamicShortcuts(List)}. * - * <p> - * In order to add static shortcuts to your app, first add - * {@code <meta-data android:name="android.app.shortcuts" />} to your main activity in - * AndroidManifest.xml: - * <pre> - *<manifest xmlns:android="http://schemas.android.com/apk/res/android" - * package="com.example.myapplication"> - * <application ... > - * <activity android:name="Main"> - * <intent-filter> - * <action android:name="android.intent.action.MAIN" /> - * <category android:name="android.intent.category.LAUNCHER" /> - * </intent-filter> - * <strong><meta-data android:name="android.app.shortcuts" - * android:resource="@xml/shortcuts" /></strong> - * </activity> - * </application> - *</manifest> - * </pre> + * <p class="note"><b>Note:</b> Ranks are auto-adjusted so that they're unique for each type of + * shortcut (static or dynamic). For example, if there are 3 dynamic shortcuts with ranks 0, 1 and + * 2, adding another dynamic shortcut with a rank of 1 represents a request to place this shortcut + * at the second position. In response, the third and fourth shortcuts move closer to the bottom of + * the shortcut list, with their ranks changing to 2 and 3, respectively. * - * Then, define your app's static shortcuts in the <code>res/xml/shortcuts.xml</code> - * file: - * <pre> - *<shortcuts xmlns:android="http://schemas.android.com/apk/res/android"> - * <shortcut - * android:shortcutId="compose" - * android:enabled="true" - * android:icon="@drawable/compose_icon" - * android:shortcutShortLabel="@string/compose_shortcut_short_label1" - * android:shortcutLongLabel="@string/compose_shortcut_long_label1" - * android:shortcutDisabledMessage="@string/compose_disabled_message1"> - * <intent - * android:action="android.intent.action.VIEW" - * android:targetPackage="com.example.myapplication" - * android:targetClass="com.example.myapplication.ComposeActivity" /> - * <!-- If your shortcut is associated with multiple intents, include them - * here. The last intent in the list is what the user sees when they - * launch this shortcut. --> - * <categories android:name="android.shortcut.conversation" /> - * </shortcut> - * <!-- Specify more shortcuts here. --> - *</shortcuts> - * </pre> + * <h3>Options for static shortcuts</h3> * * The following list includes descriptions for the different attributes within a static shortcut: * <dl> @@ -236,9 +147,10 @@ import java.util.List; * {@code android:action} is mandatory. * See <a href="{@docRoot}guide/topics/ui/settings.html#Intents">Using intents</a> for the * other supported tags. - * You can provide multiple intents for a single shortcut so that the last defined activity is launched - * with the other activities in the <a href="/guide/components/tasks-and-back-stack.html">back stack</a>. - * See {@link android.app.TaskStackBuilder} for details. + * <p>You can provide multiple intents for a single shortcut so that the last defined activity is + * launched with the other activities in the + * <a href="/guide/components/tasks-and-back-stack.html">back stack</a>. See + * {@link android.app.TaskStackBuilder} for details. * <p><b>Note:</b> String resources may not be used within an {@code <intent>} element. * </dd> * <dt>{@code categories}</dt> @@ -247,337 +159,92 @@ import java.util.List; * </dd> * </dl> * - * <h3>Publishing Dynamic Shortcuts</h3> + * <h3>Updating shortcuts</h3> * - * <p> - * Apps can publish dynamic shortcuts with {@link #setDynamicShortcuts(List)} - * or {@link #addDynamicShortcuts(List)}. The {@link #updateShortcuts(List)} method can also be - * used to update existing, mutable shortcuts. - * Use {@link #removeDynamicShortcuts(List)} or {@link #removeAllDynamicShortcuts()} to remove - * dynamic shortcuts. - * - * <p>The following code snippet shows how to create a single dynamic shortcut: - * <pre> - *ShortcutManager shortcutManager = getSystemService(ShortcutManager.class); - * - *ShortcutInfo shortcut = new ShortcutInfo.Builder(this, "id1") - * .setShortLabel("Web site") - * .setLongLabel("Open the web site") - * .setIcon(Icon.createWithResource(context, R.drawable.icon_website)) - * .setIntent(new Intent(Intent.ACTION_VIEW, - * Uri.parse("https://www.mysite.example.com/"))) - * .build(); - * - *shortcutManager.setDynamicShortcuts(Arrays.asList(shortcut)); - * </pre> - * - * <h3>Publishing Pinned Shortcuts</h3> - * - * <p>Apps can pin an existing shortcut (either static or dynamic) or an entirely new shortcut to a - * supported launcher programatically using {@link #requestPinShortcut(ShortcutInfo, IntentSender)}. - * You pass two arguments into this method: - * - * <ul> - * <li>A {@link ShortcutInfo} object – If the shortcut already exists, this object should - * contain only the shortcut's ID. Otherwise, the new {@link ShortcutInfo} object must contain an - * ID, an intent, and a short label for the new shortcut. - * <li><p>A {@link android.app.PendingIntent} object – This intent represents the callback - * that your app receives if the shortcut is successfully pinned to the device's launcher. - * <p><b>Note:</b> If the user doesn't allow the shortcut to be pinned to the launcher, the - * pinning process fails, and the {@link Intent} object that is passed into this - * {@link android.app.PendingIntent} object isn't executed. - * <div class="note"><p><b>Note:</b> Due to background execution limits introduced in Android - * {@link VERSION_CODES#O}, it's best to use a - * <a href="{@docRoot}guide/components/broadcasts.html#manifest-declared_receivers"> - * manifest-declared receiver</a> to receive a callback. - * <p>Also, to prevent other apps from invoking the receiver, add the attribute assignment - * <code>android:exported="false"</code> to the receiver's manifest entry.</p></div> - * </ul> - * - * The following code snippet shows how to pin a single shortcut that already exists and is enabled: - * - * <pre> - *ShortcutManager mShortcutManager = - * context.getSystemService(ShortcutManager.class); - * - *if (mShortcutManager.isRequestPinShortcutSupported()) { - * - * // This example defines a new shortcut; that is, this shortcut hasn't - * // been published before. - * ShortcutInfo pinShortcutInfo = new ShortcutInfo.Builder() - * .setIcon(myIcon) - * .setShortLabel("My awesome shortcut") - * .setIntent(myIntent) - * .build(); - * - * PendingIntent resultPendingIntent = null; - * - * // Create the following Intent and PendingIntent objects only if your app - * // needs to be notified that the user allowed the shortcut to be pinned. - * // Use a boolean value, such as "appNeedsNotifying", to define this behavior. - * if (appNeedsNotifying) { - * // We assume here the app has a manifest-declared receiver "MyReceiver". - * Intent pinnedShortcutCallbackIntent = new Intent(context, MyReceiver.class); - * - * // Configure the intent so that your app's broadcast receiver gets - * // the callback successfully. - * PendingIntent successCallback = PendingIntent.createBroadcast(context, 0, - * pinnedShortcutCallbackIntent); - * - * resultPendingIntent = successCallback.getIntentSender(); - * } - * - * mShortcutManager.requestPinShortcut(pinShortcutInfo, resultPendingIntent); - *} - * </pre> - * - * <p class="note"><strong>Note:</strong> As you add logic in your app to make requests to pin - * shortcuts, keep in mind that not all launchers support pinning of shortcuts. To determine whether - * your app can complete this process on a particular device, check the return value of - * {@link #isRequestPinShortcutSupported()}. Based on this return value, you might decide to hide - * the option in your app that allows users to pin a shortcut. - * - * <p class="note"><strong>Note:</strong> See also the support library APIs - * {@link android.support.v4.content.pm.ShortcutManagerCompat#isRequestPinShortcutSupported( - * Context)} and - * {@link android.support.v4.content.pm.ShortcutManagerCompat#requestPinShortcut( - * Context, ShortcutInfoCompat, IntentSender)}, which works on Android versions lower than - * {@link VERSION_CODES#O} by falling back to the deprecated private intent - * {@code com.android.launcher.action.INSTALL_SHORTCUT}. + * <p>As an example, suppose {@link #getMaxShortcutCountPerActivity()} is 5: + * <ol> + * <li>A chat app publishes 5 dynamic shortcuts for the 5 most recent + * conversations (c1, c2, ..., c5). * - * <h4>Custom Activity for Pinning Shortcuts</h4> + * <li>The user pins all 5 of the shortcuts. * - * <p>You can also create a specialized activity that helps users create shortcuts, complete with - * custom options and a confirmation button. In your app's manifest file, add - * {@link Intent#ACTION_CREATE_SHORTCUT} to the activity's <code><intent-filter></code> - * element, as shown in the following snippet: + * <li>Later, the user has started 3 additional conversations (c6, c7, and c8), + * so the publisher app + * re-publishes its dynamic shortcuts. The new dynamic shortcut list is: + * c4, c5, ..., c8. + * The publisher app has to remove c1, c2, and c3 because it can't have more than + * 5 dynamic shortcuts. * - * <pre> - *<manifest> - * ... - * <application> - * <activity android:name="com.example.MyCustomPromptToPinShortcut" ... > - * <intent-filter - * action android:name="android.intent.action.ACTION_CREATE_SHORTCUT"> - * ... - * </intent-filter> - * </activity> - * ... - * </application> - *</manifest> - * </pre> + * <li>However, even though c1, c2, and c3 are no longer dynamic shortcuts, the pinned + * shortcuts for these conversations are still available and launchable. * - * <p>When you use this specialized activity in your app, the following sequence of steps takes - * place:</p> + * <li>At this point, the user can access a total of 8 shortcuts that link to activities in + * the publisher app, including the 3 pinned shortcuts, even though an app can have at most 5 + * dynamic shortcuts. * - * <ol> - * <li>The user attempts to create a shortcut, triggering the system to start the specialized - * activity.</li> - * <li>The user sets options for the shortcut.</li> - * <li>The user selects the confirmation button, allowing your app to create the shortcut using - * the {@link #createShortcutResultIntent(ShortcutInfo)} method. This method returns an - * {@link Intent}, which your app relays back to the previously-executing activity using - * {@link Activity#setResult(int)}.</li> - * <li>Your app calls {@link Activity#finish()} on the activity used for creating the customized - * shortcut.</li> + * <li>The app can use {@link #updateShortcuts(List)} to update <em>any</em> of the existing + * 8 shortcuts, when, for example, the chat peers' icons have changed. + * <p>The {@link #addDynamicShortcuts(List)} and {@link #setDynamicShortcuts(List)} methods + * can also be used to update existing shortcuts with the same IDs, but they <b>cannot</b> be + * used for updating non-dynamic, pinned shortcuts because these 2 methods try to convert the + * given lists of shortcuts to dynamic shortcuts. * </ol> * - * <h3>Shortcut Intents</h3> + * <h3>Shortcut intents</h3> + * * <p> * Dynamic shortcuts can be published with any set of {@link Intent#addFlags Intent} flags. * Typically, {@link Intent#FLAG_ACTIVITY_CLEAR_TASK} is specified, possibly along with other * flags; otherwise, if the app is already running, the app is simply brought to * the foreground, and the target activity may not appear. * - * <p>The {@link ShortcutInfo.Builder#setIntents(Intent[])} method can be used instead of - * {@link ShortcutInfo.Builder#setIntent(Intent)} with {@link android.app.TaskStackBuilder} - * in order to launch an activity with other activities in the back stack. - * When the user selects a shortcut to load an activity with a back stack, - * then presses the back key, a parent activity from the same app will be shown - * instead of the user being navigated back to the launcher. - * - * <p>Static shortcuts can also have multiple intents to achieve the same effect. - * In order to associate multiple {@link Intent} objects with a shortcut, simply list multiple - * <code><intent></code> elements within a single <code><shortcut></code> element. - * The last intent specifies what the user sees when they launch a shortcut. - * * <p>Static shortcuts <b>cannot</b> have custom intent flags. * The first intent of a static shortcut will always have {@link Intent#FLAG_ACTIVITY_NEW_TASK} - * and {@link Intent#FLAG_ACTIVITY_CLEAR_TASK} set. - * This means, when the app is already running, all the existing activities will be - * destroyed when a static shortcut is launched. - * If this behavior is not desirable, you can use a <em>trampoline activity</em>, - * or an invisible activity that starts another activity in {@link Activity#onCreate}, - * then calls {@link Activity#finish()}. - * The first activity should include an attribute setting - * of {@code android:taskAffinity=""} in the app's <code>AndroidManifest.xml</code> - * file, and the intent within the static shortcut should point at this first activity. - * - * - * <h3>Showing New Information in a Shortcut</h3> - * <p> - * In order to avoid confusion, you should not use {@link #updateShortcuts(List)} to update - * a shortcut so that it contains conceptually different information. + * and {@link Intent#FLAG_ACTIVITY_CLEAR_TASK} set. This means, when the app is already running, all + * the existing activities in your app will be destroyed when a static shortcut is launched. + * If this behavior is not desirable, you can use a <em>trampoline activity</em>, or an invisible + * activity that starts another activity in {@link Activity#onCreate}, then calls + * {@link Activity#finish()}: + * <ol> + * <li>In the <code>AndroidManifest.xml</code> file, the trampoline activity should include the + * attribute assignment {@code android:taskAffinity=""}. + * <li>In the shortcuts resource file, the intent within the static shortcut should point at + * the trampoline activity. + * </ol> * - * <p>For example, a phone app may publish the most frequently called contact as a dynamic - * shortcut. Over time, this contact may change. When it does, the app should - * represent the changed contact with a new shortcut that contains a different ID, using either - * {@link #setDynamicShortcuts(List)} or {@link #addDynamicShortcuts(List)}, rather than updating - * the existing shortcut with {@link #updateShortcuts(List)}. - * This is because when the shortcut is pinned, changing - * it to reference a different contact will likely confuse the user. + * <h3>Handling system locale changes</h3> * - * <p>On the other hand, when the - * contact's information has changed, such as the name or picture, the app should - * use {@link #updateShortcuts(List)} so that the pinned shortcut is updated too. + * <p>Apps should update dynamic and pinned shortcuts when the system locale changes using the + * {@link Intent#ACTION_LOCALE_CHANGED} broadcast. When the system locale changes, + * <a href="/guide/topics/ui/shortcuts.html#rate-limit">rate limiting</a> is reset, so even + * background apps can add and update dynamic shortcuts until the rate limit is reached again. * + * <h3>Shortcut limits</h3> * - * <h3>Shortcut Display Order</h3> - * When the launcher displays the shortcuts that are associated with a particular launcher icon, - * the shortcuts should appear in the following order: - * <ul> - * <li>First show static shortcuts - * (if {@link ShortcutInfo#isDeclaredInManifest()} is {@code true}), - * and then show dynamic shortcuts (if {@link ShortcutInfo#isDynamic()} is {@code true}). - * <li>Within each category of shortcuts (static and dynamic), sort the shortcuts in order - * of increasing rank according to {@link ShortcutInfo#getRank()}. - * </ul> - * <p>Shortcut ranks are non-negative, sequential integers - * that determine the order in which shortcuts appear, assuming that the shortcuts are all in - * the same category. - * Ranks of existing shortcuts can be updated with - * {@link #updateShortcuts(List)}. You can also use {@link #addDynamicShortcuts(List)} and - * {@link #setDynamicShortcuts(List)}. + * <p>Only main activities—activities that handle the {@code MAIN} action and the + * {@code LAUNCHER} category—can have shortcuts. If an app has multiple main activities, you + * need to define the set of shortcuts for <em>each</em> activity. * - * <p>Ranks are auto-adjusted so that they're unique for each target activity in each category - * (static or dynamic). For example, if there are 3 dynamic shortcuts with ranks 0, 1 and 2, - * adding another dynamic shortcut with a rank of 1 represents a request to place this shortcut at - * the second position. - * In response, the third and fourth shortcuts move closer to the bottom of the shortcut list, - * with their ranks changing to 2 and 3, respectively. + * <p>Each launcher icon can have at most {@link #getMaxShortcutCountPerActivity()} number of + * static and dynamic shortcuts combined. There is no limit to the number of pinned shortcuts that + * an app can create. * - * <h3>Rate Limiting</h3> + * <p>When a dynamic shortcut is pinned, even when the publisher removes it as a dynamic shortcut, + * the pinned shortcut is still visible and launchable. This allows an app to have more than + * {@link #getMaxShortcutCountPerActivity()} number of shortcuts. * - * <p> - * Calls to {@link #setDynamicShortcuts(List)}, {@link #addDynamicShortcuts(List)}, and - * {@link #updateShortcuts(List)} may be rate-limited when called by <em>background apps</em>, or - * apps with no foreground activity or service. When you attempt to call these methods - * from a background app after exceeding the rate limit, these APIs return {@code false}. + * <h4>Rate limiting</h4> * - * <p>Apps with a foreground activity or service are not rate-limited. + * <p>When <a href="/guide/topics/ui/shortcuts.html#rate-limit">rate limiting</a> is active, + * {@link #isRateLimitingActive()} returns {@code true}. * - * <p>Rate-limiting is reset upon certain events, so that even background apps - * can call these APIs until the rate limit is reached again. - * These events include the following: + * <p>Rate limiting is reset upon certain events, so even background apps can call these APIs until + * the rate limit is reached again. These events include the following: * <ul> * <li>An app comes to the foreground. * <li>The system locale changes. * <li>The user performs the <strong>inline reply</strong> action on a notification. * </ul> - * - * <p>When rate-limiting is active, {@link #isRateLimitingActive()} returns {@code true}. - * - * <h4>Resetting rate-limiting for testing</h4> - * - * <p> - * If your app is rate-limited during development or testing, you can use the - * <strong>Reset ShortcutManager rate-limiting</strong> development option or - * the following {@code adb} command to reset it: - * <pre class="no-pretty-print"> - *$ adb shell cmd shortcut reset-throttling [ --user USER-ID ] - * </pre> - * - * <h3>Handling System Locale Changes</h3> - * - * <p> - * Apps should update dynamic and pinned shortcuts when the system locale changes - * using the {@link Intent#ACTION_LOCALE_CHANGED} broadcast. - * - * <p>When the system locale changes, rate-limiting is reset, so even background apps - * can add and update dynamic shortcuts until the rate limit is reached again. - * - * - * <h3>Backup and Restore</h3> - * - * <p> - * When an app has the {@code android:allowBackup="true"} attribute assignment included - * in its <code>AndroidManifest.xml</code> file, pinned shortcuts are - * backed up automatically and are restored when the user sets up a new device. - * - * <h4>Categories of shortcuts that are backed up</h4> - * - * <ul> - * <li>Pinned shortcuts are backed up. Bitmap icons are not backed up by the system, - * so launcher apps should back them up and restore them so that the user still sees icons - * for pinned shortcuts on the launcher. Apps can always use - * {@link #updateShortcuts(List)} to re-publish icons. - * - * <li>Static shortcuts aren't backed up, but when an app is re-installed on a new - * device, they are re-published from the <code>AndroidManifest.xml</code> file. - * - * <li>Dynamic shortcuts <b>aren't</b> backed up. - * </ul> - * - * <p>Because dynamic shortcuts are not restored, it is recommended that apps check - * currently-published dynamic shortcuts using {@link #getDynamicShortcuts()} - * each time they are launched, and they should re-publish - * dynamic shortcuts when necessary. - * - * <pre> - *public class MainActivity extends Activity { - * public void onCreate(Bundle savedInstanceState) { - * super.onCreate(savedInstanceState); - * ShortcutManager shortcutManager = - * getSystemService(ShortcutManager.class); - * - * if (shortcutManager.getDynamicShortcuts().size() == 0) { - * // Application restored. Need to re-publish dynamic shortcuts. - * if (shortcutManager.getPinnedShortcuts().size() > 0) { - * // Pinned shortcuts have been restored. Use - * // updateShortcuts() to make sure they contain - * // up-to-date information. - * } - * } - * } - * // ... - *} - * </pre> - * - * - * <h4>Backup/restore and shortcut IDs</h4> - * <p> - * Because pinned shortcuts are backed up and restored on new devices, shortcut IDs - * should contain either stable, constant strings or server-side identifiers, - * rather than identifiers generated locally that might not make sense on other devices. - * - * - * <h3>Report Shortcut Usage and Prediction</h3> - * <p> - * Launcher apps may be capable of predicting which shortcuts will most likely be - * used at a given time by examining the shortcut usage history data. - * - * <p>In order to provide launchers with such data, publisher apps should - * report the shortcuts that are used with {@link #reportShortcutUsed(String)} - * when a shortcut is selected, - * <b>or when an action equivalent to a shortcut is taken by the user even if it wasn't started - * with the shortcut</b>. - * - * <p>For example, suppose a navigation app supports "navigate to work" as a shortcut. - * It should then report when the user selects this shortcut <b>and</b> when the user chooses - * to navigate to work within the app itself. - * This helps the launcher app - * learn that the user wants to navigate to work at a certain time every - * weekday, and it can then show this shortcut in a suggestion list at the right time. - * - * <h3>Launcher API</h3> - * - * The {@link LauncherApps} class provides APIs for launcher apps to access shortcuts. - * - * - * <h3>Direct Boot and Shortcuts</h3> - * - * All shortcut information is stored in credential encrypted storage, so no shortcuts can be - * accessed when the user is locked. */ @SystemService(Context.SHORTCUT_SERVICE) public class ShortcutManager { diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index f7cccd56f079..780e6f769290 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -19,15 +19,14 @@ package android.content.res; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.WindowConfiguration; import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo.Config; -import android.graphics.Rect; import android.os.Build; import android.os.LocaleList; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; -import android.view.DisplayInfo; import android.view.View; import com.android.internal.util.XmlUtils; @@ -42,7 +41,6 @@ import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Locale; - /** * This class describes all device configuration information that can * impact the resources the application retrieves. This includes both @@ -298,13 +296,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration /** * @hide - * {@link android.graphics.Rect} defining app bounds. The dimensions override usages of - * {@link DisplayInfo#appHeight} and {@link DisplayInfo#appWidth} and mirrors these values at - * the display level. Lower levels can override these values to provide custom bounds to enforce - * features such as a max aspect ratio. - * TODO(b/36812336): Move appBounds out of {@link Configuration}. + * Configuration relating to the windowing state of the object associated with this + * Configuration. Contents of this field are not intended to affect resources, but need to be + * communicated and propagated at the same time as the rest of Configuration. */ - public Rect appBounds; + public final WindowConfiguration windowConfiguration = new WindowConfiguration(); /** @hide */ static public int resetScreenLayout(int curLayout) { @@ -895,9 +891,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration compatScreenWidthDp = o.compatScreenWidthDp; compatScreenHeightDp = o.compatScreenHeightDp; compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp; - setAppBounds(o.appBounds); assetsSeq = o.assetsSeq; seq = o.seq; + windowConfiguration.setTo(o.windowConfiguration); } public String toString() { @@ -1046,9 +1042,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration case NAVIGATIONHIDDEN_YES: sb.append("/h"); break; default: sb.append("/"); sb.append(navigationHidden); break; } - if (appBounds != null) { - sb.append(" appBounds="); sb.append(appBounds); - } + sb.append(" winConfig="); sb.append(windowConfiguration); if (assetsSeq != 0) { sb.append(" as.").append(assetsSeq); } @@ -1083,8 +1077,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED; densityDpi = DENSITY_DPI_UNDEFINED; assetsSeq = ASSETS_SEQ_UNDEFINED; - appBounds = null; seq = 0; + windowConfiguration.setToDefaults(); } /** @@ -1183,7 +1177,6 @@ public final class Configuration implements Parcelable, Comparable<Configuration changed |= ActivityInfo.CONFIG_ORIENTATION; orientation = delta.orientation; } - if (((delta.screenLayout & SCREENLAYOUT_SIZE_MASK) != SCREENLAYOUT_SIZE_UNDEFINED) && (delta.screenLayout & SCREENLAYOUT_SIZE_MASK) != (screenLayout & SCREENLAYOUT_SIZE_MASK)) { @@ -1271,10 +1264,6 @@ public final class Configuration implements Parcelable, Comparable<Configuration if (delta.compatSmallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) { compatSmallestScreenWidthDp = delta.compatSmallestScreenWidthDp; } - if (delta.appBounds != null && !delta.appBounds.equals(appBounds)) { - changed |= ActivityInfo.CONFIG_SCREEN_SIZE; - setAppBounds(delta.appBounds); - } if (delta.assetsSeq != ASSETS_SEQ_UNDEFINED && delta.assetsSeq != assetsSeq) { changed |= ActivityInfo.CONFIG_ASSETS_PATHS; assetsSeq = delta.assetsSeq; @@ -1282,6 +1271,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration if (delta.seq != 0) { seq = delta.seq; } + if (windowConfiguration.updateFrom(delta.windowConfiguration) != 0) { + changed |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION; + } return changed; } @@ -1433,13 +1425,10 @@ public final class Configuration implements Parcelable, Comparable<Configuration changed |= ActivityInfo.CONFIG_ASSETS_PATHS; } - // Make sure that one of the values is not null and that they are not equal. - if ((compareUndefined || delta.appBounds != null) - && appBounds != delta.appBounds - && (appBounds == null || (!publicOnly && !appBounds.equals(delta.appBounds)) - || (publicOnly && (appBounds.width() != delta.appBounds.width() - || appBounds.height() != delta.appBounds.height())))) { - changed |= ActivityInfo.CONFIG_SCREEN_SIZE; + // WindowConfiguration differences aren't considered public... + if (!publicOnly + && windowConfiguration.diff(delta.windowConfiguration, compareUndefined) != 0) { + changed |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION; } return changed; @@ -1537,7 +1526,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration dest.writeInt(compatScreenWidthDp); dest.writeInt(compatScreenHeightDp); dest.writeInt(compatSmallestScreenWidthDp); - dest.writeValue(appBounds); + dest.writeValue(windowConfiguration); dest.writeInt(assetsSeq); dest.writeInt(seq); } @@ -1573,7 +1562,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration compatScreenWidthDp = source.readInt(); compatScreenHeightDp = source.readInt(); compatSmallestScreenWidthDp = source.readInt(); - appBounds = (Rect) source.readValue(null); + windowConfiguration.setTo((WindowConfiguration) source.readValue(null)); assetsSeq = source.readInt(); seq = source.readInt(); } @@ -1663,21 +1652,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration if (n != 0) return n; n = this.assetsSeq - that.assetsSeq; if (n != 0) return n; - - if (this.appBounds == null && that.appBounds != null) { - return 1; - } else if (this.appBounds != null && that.appBounds == null) { - return -1; - } else if (this.appBounds != null && that.appBounds != null) { - n = this.appBounds.left - that.appBounds.left; - if (n != 0) return n; - n = this.appBounds.top - that.appBounds.top; - if (n != 0) return n; - n = this.appBounds.right - that.appBounds.right; - if (n != 0) return n; - n = this.appBounds.bottom - that.appBounds.bottom; - if (n != 0) return n; - } + n = windowConfiguration.compareTo(that.windowConfiguration); + if (n != 0) return n; // if (n != 0) return n; return n; @@ -1768,33 +1744,6 @@ public final class Configuration implements Parcelable, Comparable<Configuration /** * @hide * - * Helper method for setting the app bounds. - */ - public void setAppBounds(Rect rect) { - if (rect == null) { - appBounds = null; - return; - } - - setAppBounds(rect.left, rect.top, rect.right, rect.bottom); - } - - /** - * @hide - * - * Helper method for setting the app bounds. - */ - public void setAppBounds(int left, int top, int right, int bottom) { - if (appBounds == null) { - appBounds = new Rect(); - } - - appBounds.set(left, top, right, bottom); - } - - /** - * @hide - * * Clears the locale without changing layout direction. */ public void clearLocales() { @@ -2282,6 +2231,10 @@ public final class Configuration implements Parcelable, Comparable<Configuration if (base.assetsSeq != change.assetsSeq) { delta.assetsSeq = change.assetsSeq; } + + if (!base.windowConfiguration.equals(change.windowConfiguration)) { + delta.windowConfiguration.setTo(change.windowConfiguration); + } return delta; } @@ -2354,10 +2307,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration SMALLEST_SCREEN_WIDTH_DP_UNDEFINED); configOut.densityDpi = XmlUtils.readIntAttribute(parser, XML_ATTR_DENSITY, DENSITY_DPI_UNDEFINED); - configOut.appBounds = - Rect.unflattenFromString(XmlUtils.readStringAttribute(parser, XML_ATTR_APP_BOUNDS)); - // For persistence, we don't care about assetsSeq, so do not read it out. + // For persistence, we don't care about assetsSeq and WindowConfiguration, so do not read it + // out. } @@ -2427,11 +2379,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration XmlUtils.writeIntAttribute(xml, XML_ATTR_DENSITY, config.densityDpi); } - if (config.appBounds != null) { - XmlUtils.writeStringAttribute(xml, XML_ATTR_APP_BOUNDS, - config.appBounds.flattenToString()); - } - - // For persistence, we do not care about assetsSeq, so do not write it out. + // For persistence, we do not care about assetsSeq and window configuration, so do not write + // it out. } } diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java index 8cd3d7b5bc68..3d019f07cb84 100644 --- a/core/java/android/database/DatabaseUtils.java +++ b/core/java/android/database/DatabaseUtils.java @@ -1408,6 +1408,12 @@ public class DatabaseUtils { } else if (prefixSql.equals("END")) { return STATEMENT_COMMIT; } else if (prefixSql.equals("ROL")) { + boolean isRollbackToSavepoint = sql.toUpperCase(Locale.ROOT).contains(" TO "); + if (isRollbackToSavepoint) { + Log.w(TAG, "Statement '" + sql + + "' may not work on API levels 16-27, use ';" + sql + "' instead"); + return STATEMENT_OTHER; + } return STATEMENT_ABORT; } else if (prefixSql.equals("BEG")) { return STATEMENT_BEGIN; diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java index de02ee51ac3a..59fb269c71fc 100644 --- a/core/java/android/database/sqlite/SQLiteDatabase.java +++ b/core/java/android/database/sqlite/SQLiteDatabase.java @@ -79,8 +79,6 @@ public final class SQLiteDatabase extends SQLiteClosable { private static final int EVENT_DB_CORRUPT = 75004; - // TODO b/63398887 STOPSHIP. - // Temporarily enabled for testing across a broader set of dogfood devices. private static final boolean DEBUG_CLOSE_IDLE_CONNECTIONS = SystemProperties .getBoolean("persist.debug.sqlite.close_idle_connections", true); diff --git a/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java b/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java index 797430a4c8ec..1721e0c69dc3 100644 --- a/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java +++ b/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java @@ -16,6 +16,7 @@ package android.database.sqlite; +import android.annotation.TestApi; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.os.CancellationSignal; @@ -25,6 +26,7 @@ import android.os.CancellationSignal; * * @hide */ +@TestApi public final class SQLiteDirectCursorDriver implements SQLiteCursorDriver { private final SQLiteDatabase mDatabase; private final String mEditTable; diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index bda80390a614..6fbacaf32fd6 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -18,13 +18,16 @@ package android.hardware.display; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; +import android.graphics.Point; import android.media.projection.MediaProjection; import android.os.Handler; import android.util.SparseArray; import android.view.Display; import android.view.Surface; +import android.view.WindowManagerPolicy; import java.util.ArrayList; @@ -236,6 +239,13 @@ public final class DisplayManager { * keyguard is shown but is insecure. * * <p> + * This might be used in a case when the content of a virtual display is captured and sent to an + * external hardware display that is not visible to the system directly. This flag will allow + * the continued display of content while other displays will be covered by a keyguard which + * doesn't require providing credentials to unlock. This means that there is either no password + * or other authentication method set, or the device is in a trusted state - + * {@link android.service.trust.TrustAgentService} has available and active trust agent. + * </p><p> * This flag can only be applied to private displays as defined by the * {@link Display#FLAG_PRIVATE} display flag. It is mutually exclusive with * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}. If both flags are specified then this flag's behavior @@ -243,8 +253,11 @@ public final class DisplayManager { * </p> * * @see #createVirtualDisplay + * @see WindowManagerPolicy#isKeyguardSecure(int) + * @see WindowManagerPolicy#isKeyguardTrustedLw() * @hide */ + // TODO: Update name and documentation and un-hide the flag. Don't change the value before that. public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5; /** @@ -575,6 +588,20 @@ public final class DisplayManager { } /** + * Gets the stable device display size, in pixels. + * + * This should really only be used for things like server-side filtering of available + * applications. Most applications don't need the level of stability guaranteed by this and + * should instead query either the size of the display they're currently running on or the + * size of the default display. + * @hide + */ + @SystemApi + public Point getStableDisplaySize() { + return mGlobal.getStableDisplaySize(); + } + + /** * Listens for changes in available display devices. */ public interface DisplayListener { diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java index 0b998e58656b..a8a4eb67f580 100644 --- a/core/java/android/hardware/display/DisplayManagerGlobal.java +++ b/core/java/android/hardware/display/DisplayManagerGlobal.java @@ -18,6 +18,7 @@ package android.hardware.display; import android.content.Context; import android.content.res.Resources; +import android.graphics.Point; import android.hardware.display.DisplayManager.DisplayListener; import android.media.projection.IMediaProjection; import android.media.projection.MediaProjection; @@ -444,6 +445,17 @@ public final class DisplayManagerGlobal { } } + /** + * Gets the stable device display size, in pixels. + */ + public Point getStableDisplaySize() { + try { + return mDm.getStableDisplaySize(); + } catch (RemoteException ex) { + throw ex.rethrowFromSystemServer(); + } + } + private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub { @Override public void onDisplayEvent(int displayId, int event) { diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl index 7ca4dc140eca..505388419c8c 100644 --- a/core/java/android/hardware/display/IDisplayManager.aidl +++ b/core/java/android/hardware/display/IDisplayManager.aidl @@ -16,6 +16,7 @@ package android.hardware.display; +import android.graphics.Point; import android.hardware.display.IDisplayManagerCallback; import android.hardware.display.IVirtualDisplayCallback; import android.hardware.display.WifiDisplay; @@ -77,4 +78,7 @@ interface IDisplayManager { // No permissions required but must be same Uid as the creator. void releaseVirtualDisplay(in IVirtualDisplayCallback token); + + // Get a stable metric for the device's display size. No permissions required. + Point getStableDisplaySize(); } diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index 8b6f9c1bbdd2..987718a82c47 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -128,6 +128,13 @@ public class FingerprintManager { public static final int FINGERPRINT_ERROR_LOCKOUT_PERMANENT = 9; /** + * The user canceled the operation. Upon receiving this, applications should use alternate + * authentication (e.g. a password). The application should also provide the means to return + * to fingerprint authentication, such as a "use fingerprint" button. + */ + public static final int FINGERPRINT_ERROR_USER_CANCELED = 10; + + /** * @hide */ public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000; diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java index d73d3d8b04cf..595d85715fc9 100644 --- a/core/java/android/hardware/usb/UsbManager.java +++ b/core/java/android/hardware/usb/UsbManager.java @@ -17,10 +17,13 @@ package android.hardware.usb; +import android.Manifest; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SdkConstant; -import android.annotation.SystemService; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.SystemApi; +import android.annotation.SystemService; import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; @@ -520,6 +523,8 @@ public class UsbManager { * * {@hide} */ + @SystemApi + @RequiresPermission(Manifest.permission.MANAGE_USB) public void grantPermission(UsbDevice device, String packageName) { try { int uid = mContext.getPackageManager() diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 48123fede6f5..744ee8ed0e74 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -840,8 +840,8 @@ public class ConnectivityManager { * In order to support the always-on feature, an app has to * <ul> * <li>target {@link VERSION_CODES#N API 24} or above, and - * <li>not opt out through the {@link VpnService#METADATA_SUPPORTS_ALWAYS_ON} meta-data - * field. + * <li>not opt out through the {@link VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON} + * meta-data field. * </ul> * * @param userId The identifier of the user for whom the VPN app is installed. diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index e693009c3377..91801127fd4a 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -36,7 +36,7 @@ interface INetworkStatsService { * PACKAGE_USAGE_STATS permission is always checked. If PACKAGE_USAGE_STATS is not granted * READ_NETWORK_USAGE_STATS is checked for. */ - INetworkStatsSession openSessionForUsageStats(String callingPackage); + INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage); /** Return network layer usage total for traffic that matches template. */ long getNetworkTotalBytes(in NetworkTemplate template, long start, long end); diff --git a/core/java/android/net/ITetheringStatsProvider.aidl b/core/java/android/net/ITetheringStatsProvider.aidl index 769086da42b4..da0bf4c47b94 100644 --- a/core/java/android/net/ITetheringStatsProvider.aidl +++ b/core/java/android/net/ITetheringStatsProvider.aidl @@ -19,7 +19,7 @@ package android.net; import android.net.NetworkStats; /** - * Interface that allows NetworkManagementService to query for tethering statistics. + * Interface for NetworkManagementService to query tethering statistics and set data limits. * * TODO: this does not really need to be an interface since Tethering runs in the same process * as NetworkManagementService. Consider refactoring Tethering to use direct access to @@ -29,5 +29,17 @@ import android.net.NetworkStats; * @hide */ interface ITetheringStatsProvider { - NetworkStats getTetherStats(); + // Returns cumulative statistics for all tethering sessions since boot, on all upstreams. + // @code {how} is one of the NetworkStats.STATS_PER_* constants. If {@code how} is + // {@code STATS_PER_IFACE}, the provider should not include any traffic that is already + // counted by kernel interface counters. + NetworkStats getTetherStats(int how); + + // Sets the interface quota for the specified upstream interface. This is defined as the number + // of bytes, starting from zero and counting from now, after which data should stop being + // forwarded to/from the specified upstream. A value of QUOTA_UNLIMITED means there is no limit. + void setInterfaceQuota(String iface, long quotaBytes); + + // Indicates that no data usage limit is set. + const int QUOTA_UNLIMITED = -1; } diff --git a/core/java/android/net/IpPrefix.java b/core/java/android/net/IpPrefix.java index 6b4f2d5acd00..6e2654e3ce7c 100644 --- a/core/java/android/net/IpPrefix.java +++ b/core/java/android/net/IpPrefix.java @@ -20,6 +20,8 @@ import android.os.Parcel; import android.os.Parcelable; import android.util.Pair; +import java.net.Inet4Address; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Arrays; @@ -185,6 +187,20 @@ public final class IpPrefix implements Parcelable { } /** + * @hide + */ + public boolean isIPv6() { + return getAddress() instanceof Inet6Address; + } + + /** + * @hide + */ + public boolean isIPv4() { + return getAddress() instanceof Inet4Address; + } + + /** * Returns a string representation of this {@code IpPrefix}. * * @return a string such as {@code "192.0.2.0/24"} or {@code "2001:db8:1:2::/64"}. diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java index 62de9911bc48..bcfe93882375 100644 --- a/core/java/android/net/LinkAddress.java +++ b/core/java/android/net/LinkAddress.java @@ -76,7 +76,7 @@ public class LinkAddress implements Parcelable { * RFC 6724 section 3.2. * @hide */ - static int scopeForUnicastAddress(InetAddress addr) { + private static int scopeForUnicastAddress(InetAddress addr) { if (addr.isAnyLocalAddress()) { return RT_SCOPE_HOST; } @@ -101,7 +101,7 @@ public class LinkAddress implements Parcelable { * Per RFC 4193 section 8, fc00::/7 identifies these addresses. */ private boolean isIPv6ULA() { - if (address instanceof Inet6Address) { + if (isIPv6()) { byte[] bytes = address.getAddress(); return ((bytes[0] & (byte)0xfe) == (byte)0xfc); } @@ -109,13 +109,29 @@ public class LinkAddress implements Parcelable { } /** + * @return true if the address is IPv6. + * @hide + */ + public boolean isIPv6() { + return address instanceof Inet6Address; + } + + /** + * @return true if the address is IPv4 or is a mapped IPv4 address. + * @hide + */ + public boolean isIPv4() { + return address instanceof Inet4Address; + } + + /** * Utility function for the constructors. */ private void init(InetAddress address, int prefixLength, int flags, int scope) { if (address == null || address.isMulticastAddress() || prefixLength < 0 || - ((address instanceof Inet4Address) && prefixLength > 32) || + (address instanceof Inet4Address && prefixLength > 32) || (prefixLength > 128)) { throw new IllegalArgumentException("Bad LinkAddress params " + address + "/" + prefixLength); @@ -184,6 +200,7 @@ public class LinkAddress implements Parcelable { */ public LinkAddress(String address, int flags, int scope) { // This may throw an IllegalArgumentException; catching it is the caller's responsibility. + // TODO: consider rejecting mapped IPv4 addresses such as "::ffff:192.0.2.5/24". Pair<InetAddress, Integer> ipAndMask = NetworkUtils.parseIpAndMask(address); init(ipAndMask.first, ipAndMask.second, flags, scope); } diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java index 0c0872a78f74..3c868c399b1f 100644 --- a/core/java/android/net/Network.java +++ b/core/java/android/net/Network.java @@ -22,6 +22,9 @@ import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; +import libcore.net.http.Dns; +import libcore.net.http.HttpURLConnectionFactory; + import java.io.FileDescriptor; import java.io.IOException; import java.net.DatagramSocket; @@ -35,18 +38,9 @@ import java.net.UnknownHostException; import java.net.URL; import java.net.URLConnection; import java.util.Arrays; -import java.util.List; import java.util.concurrent.TimeUnit; import javax.net.SocketFactory; -import com.android.okhttp.ConnectionPool; -import com.android.okhttp.Dns; -import com.android.okhttp.HttpHandler; -import com.android.okhttp.HttpsHandler; -import com.android.okhttp.OkHttpClient; -import com.android.okhttp.OkUrlFactory; -import com.android.okhttp.internal.Internal; - /** * Identifies a {@code Network}. This is supplied to applications via * {@link ConnectivityManager.NetworkCallback} in response to the active @@ -66,10 +60,9 @@ public class Network implements Parcelable { // Objects used to perform per-network operations such as getSocketFactory // and openConnection, and a lock to protect access to them. private volatile NetworkBoundSocketFactory mNetworkBoundSocketFactory = null; - // mLock should be used to control write access to mConnectionPool and mDns. - // maybeInitHttpClient() must be called prior to reading either variable. - private volatile ConnectionPool mConnectionPool = null; - private volatile Dns mDns = null; + // mLock should be used to control write access to mUrlConnectionFactory. + // maybeInitUrlConnectionFactory() must be called prior to reading this field. + private volatile HttpURLConnectionFactory mUrlConnectionFactory; private final Object mLock = new Object(); // Default connection pool values. These are evaluated at startup, just @@ -221,19 +214,19 @@ public class Network implements Parcelable { // will be instantiated in the near future with the same NetID. A good // solution would involve purging empty (or when all connections are timed // out) ConnectionPools. - private void maybeInitHttpClient() { + private void maybeInitUrlConnectionFactory() { synchronized (mLock) { - if (mDns == null) { - mDns = new Dns() { - @Override - public List<InetAddress> lookup(String hostname) throws UnknownHostException { - return Arrays.asList(Network.this.getAllByName(hostname)); - } - }; - } - if (mConnectionPool == null) { - mConnectionPool = new ConnectionPool(httpMaxConnections, + if (mUrlConnectionFactory == null) { + // Set configuration on the HttpURLConnectionFactory that will be good for all + // connections created by this Network. Configuration that might vary is left + // until openConnection() and passed as arguments. + Dns dnsLookup = hostname -> Arrays.asList(Network.this.getAllByName(hostname)); + HttpURLConnectionFactory urlConnectionFactory = new HttpURLConnectionFactory(); + urlConnectionFactory.setDns(dnsLookup); // Let traffic go via dnsLookup + // A private connection pool just for this Network. + urlConnectionFactory.setNewConnectionPool(httpMaxConnections, httpKeepAliveDurationMs, TimeUnit.MILLISECONDS); + mUrlConnectionFactory = urlConnectionFactory; } } } @@ -254,7 +247,7 @@ public class Network implements Parcelable { } // TODO: Should this be optimized to avoid fetching the global proxy for every request? final ProxyInfo proxyInfo = cm.getProxyForNetwork(this); - java.net.Proxy proxy = null; + final java.net.Proxy proxy; if (proxyInfo != null) { proxy = proxyInfo.makeProxy(); } else { @@ -276,26 +269,9 @@ public class Network implements Parcelable { */ public URLConnection openConnection(URL url, java.net.Proxy proxy) throws IOException { if (proxy == null) throw new IllegalArgumentException("proxy is null"); - maybeInitHttpClient(); - String protocol = url.getProtocol(); - OkUrlFactory okUrlFactory; - // TODO: HttpHandler creates OkUrlFactory instances that share the default ResponseCache. - // Could this cause unexpected behavior? - if (protocol.equals("http")) { - okUrlFactory = HttpHandler.createHttpOkUrlFactory(proxy); - } else if (protocol.equals("https")) { - okUrlFactory = HttpsHandler.createHttpsOkUrlFactory(proxy); - } else { - // OkHttp only supports HTTP and HTTPS and returns a null URLStreamHandler if - // passed another protocol. - throw new MalformedURLException("Invalid URL or unrecognized protocol " + protocol); - } - OkHttpClient client = okUrlFactory.client(); - client.setSocketFactory(getSocketFactory()).setConnectionPool(mConnectionPool); - // Let network traffic go via mDns - client.setDns(mDns); - - return okUrlFactory.open(url); + maybeInitUrlConnectionFactory(); + SocketFactory socketFactory = getSocketFactory(); + return mUrlConnectionFactory.openConnection(url, socketFactory, proxy); } /** diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 0b9289345dbe..4bb884405360 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -770,7 +770,6 @@ public final class NetworkCapabilities implements Parcelable { StringJoiner joiner = new StringJoiner(", "); - // TODO: consider only enforcing that capabilities are not removed, allowing addition. // Ignore NOT_METERED being added or removed as it is effectively dynamic. http://b/63326103 // TODO: properly support NOT_METERED as a mutable and requestable capability. final long mask = ~MUTABLE_CAPABILITIES & ~(1 << NET_CAPABILITY_NOT_METERED); diff --git a/core/java/android/net/NetworkFactory.java b/core/java/android/net/NetworkFactory.java index cab88b9972b5..e2f8d1a3f08b 100644 --- a/core/java/android/net/NetworkFactory.java +++ b/core/java/android/net/NetworkFactory.java @@ -254,6 +254,16 @@ public class NetworkFactory extends Handler { } } + /** + * Post a command, on this NetworkFactory Handler, to re-evaluate all + * oustanding requests. Can be called from a factory implementation. + */ + protected void reevaluateAllRequests() { + post(() -> { + evalRequests(); + }); + } + // override to do simple mode (request independent) protected void startNetwork() { } protected void stopNetwork() { } diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java index 060af0dd1ba1..50dd468aa905 100644 --- a/core/java/android/net/NetworkScoreManager.java +++ b/core/java/android/net/NetworkScoreManager.java @@ -226,7 +226,11 @@ public class NetworkScoreManager { * the {@link #ACTION_CHANGE_ACTIVE} intent. * @return the full package name of the current active scorer, or null if there is no active * scorer. + * @throws SecurityException if the caller doesn't hold either {@link permission#SCORE_NETWORKS} + * or {@link permission#REQUEST_NETWORK_SCORES} permissions. */ + @RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS, + android.Manifest.permission.REQUEST_NETWORK_SCORES}) public String getActiveScorerPackage() { try { return mService.getActiveScorerPackage(); @@ -238,6 +242,8 @@ public class NetworkScoreManager { /** * Returns metadata about the active scorer or <code>null</code> if there is no active scorer. * + * @throws SecurityException if the caller does not hold the + * {@link permission#REQUEST_NETWORK_SCORES} permission. * @hide */ @Nullable @@ -254,8 +260,11 @@ public class NetworkScoreManager { * Returns the list of available scorer apps. The list will be empty if there are * no valid scorers. * + * @throws SecurityException if the caller does not hold the + * {@link permission#REQUEST_NETWORK_SCORES} permission. * @hide */ + @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) public List<NetworkScorerAppData> getAllValidScorers() { try { return mService.getAllValidScorers(); @@ -294,9 +303,11 @@ public class NetworkScoreManager { * from one scorer cannot be compared to those from another scorer. * * @return whether the clear was successful. - * @throws SecurityException if the caller is not the active scorer or privileged. + * @throws SecurityException if the caller is not the active scorer or if the caller doesn't + * hold the {@link permission#REQUEST_NETWORK_SCORES} permission. */ - @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) + @RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS, + android.Manifest.permission.REQUEST_NETWORK_SCORES}) public boolean clearScores() throws SecurityException { try { return mService.clearScores(); @@ -312,12 +323,13 @@ public class NetworkScoreManager { * the {@link #ACTION_CHANGE_ACTIVE} broadcast, or using a custom configuration activity. * * @return true if the operation succeeded, or false if the new package is not a valid scorer. - * @throws SecurityException if the caller is not a system process or does not hold the - * {@link permission#SCORE_NETWORKS} permission + * @throws SecurityException if the caller doesn't hold either {@link permission#SCORE_NETWORKS} + * or {@link permission#REQUEST_NETWORK_SCORES} permissions. * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS) + @RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS, + android.Manifest.permission.REQUEST_NETWORK_SCORES}) public boolean setActiveScorer(String packageName) throws SecurityException { try { return mService.setActiveScorer(packageName); @@ -331,9 +343,11 @@ public class NetworkScoreManager { * * <p>May only be called by the current scorer app, or the system. * - * @throws SecurityException if the caller is neither the active scorer nor the system. + * @throws SecurityException if the caller is not the active scorer or if the caller doesn't + * hold the {@link permission#REQUEST_NETWORK_SCORES} permission. */ - @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) + @RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS, + android.Manifest.permission.REQUEST_NETWORK_SCORES}) public void disableScoring() throws SecurityException { try { mService.disableScoring(); @@ -350,6 +364,7 @@ public class NetworkScoreManager { * {@link permission#REQUEST_NETWORK_SCORES} permission. * @hide */ + @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) public boolean requestScores(NetworkKey[] networks) throws SecurityException { try { return mService.requestScores(networks); @@ -369,6 +384,7 @@ public class NetworkScoreManager { * @deprecated equivalent to registering for cache updates with CACHE_FILTER_NONE. * @hide */ + @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) @Deprecated // migrate to registerNetworkScoreCache(int, INetworkScoreCache, int) public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) { registerNetworkScoreCache(networkType, scoreCache, CACHE_FILTER_NONE); @@ -385,6 +401,7 @@ public class NetworkScoreManager { * @throws IllegalArgumentException if a score cache is already registered for this type. * @hide */ + @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache, @CacheUpdateFilter int filterType) { try { @@ -404,6 +421,7 @@ public class NetworkScoreManager { * @throws IllegalArgumentException if a score cache is already registered for this type. * @hide */ + @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) public void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) { try { mService.unregisterNetworkScoreCache(networkType, scoreCache); @@ -417,8 +435,11 @@ public class NetworkScoreManager { * * @param callingUid the UID to check * @return true if the provided UID is the active scorer, false otherwise. + * @throws SecurityException if the caller does not hold the + * {@link permission#REQUEST_NETWORK_SCORES} permission. * @hide */ + @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) public boolean isCallerActiveScorer(int callingUid) { try { return mService.isCallerActiveScorer(callingUid); diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index be9e80973875..171adc054bbe 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -82,6 +82,11 @@ public class NetworkStats implements Parcelable { /** {@link #roaming} value where roaming data is accounted. */ public static final int ROAMING_YES = 1; + /** Denotes a request for stats at the interface level. */ + public static final int STATS_PER_IFACE = 0; + /** Denotes a request for stats at the interface and UID level. */ + public static final int STATS_PER_UID = 1; + // TODO: move fields to "mVariable" notation /** diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index 5f521de63cf1..433f9410cc6e 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -27,6 +27,7 @@ import static android.net.NetworkStatsHistory.Entry.UNKNOWN; import static android.net.NetworkStatsHistory.ParcelUtils.readLongArray; import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray; import static android.text.format.DateUtils.SECOND_IN_MILLIS; + import static com.android.internal.util.ArrayUtils.total; import android.os.Parcel; @@ -282,6 +283,24 @@ public class NetworkStatsHistory implements Parcelable { return entry; } + public void setValues(int i, Entry entry) { + // Unwind old values + if (rxBytes != null) totalBytes -= rxBytes[i]; + if (txBytes != null) totalBytes -= txBytes[i]; + + bucketStart[i] = entry.bucketStart; + setLong(activeTime, i, entry.activeTime); + setLong(rxBytes, i, entry.rxBytes); + setLong(rxPackets, i, entry.rxPackets); + setLong(txBytes, i, entry.txBytes); + setLong(txPackets, i, entry.txPackets); + setLong(operations, i, entry.operations); + + // Apply new values + if (rxBytes != null) totalBytes += rxBytes[i]; + if (txBytes != null) totalBytes += txBytes[i]; + } + /** * Record that data traffic occurred in the given time range. Will * distribute across internal buckets, creating new buckets as needed. diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 0d2fcd074047..b307c5d6fc53 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -326,6 +326,10 @@ public class NetworkTemplate implements Parcelable { } } + public boolean matchesSubscriberId(String subscriberId) { + return ArrayUtils.contains(mMatchSubscriberIds, subscriberId); + } + /** * Check if mobile network with matching IMSI. */ diff --git a/core/java/android/net/PskKeyManager.java b/core/java/android/net/PskKeyManager.java deleted file mode 100644 index f5167eafab62..000000000000 --- a/core/java/android/net/PskKeyManager.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright 2014 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.net; - -import com.android.org.conscrypt.PSKKeyManager; -import java.net.Socket; -import javax.crypto.SecretKey; -import javax.net.ssl.SSLEngine; - -/** - * Provider of key material for pre-shared key (PSK) key exchange used in TLS-PSK cipher suites. - * - * <h3>Overview of TLS-PSK</h3> - * - * <p>TLS-PSK is a set of TLS/SSL cipher suites which rely on a symmetric pre-shared key (PSK) to - * secure the TLS/SSL connection and mutually authenticate its peers. These cipher suites may be - * a more natural fit compared to conventional public key based cipher suites in some scenarios - * where communication between peers is bootstrapped via a separate step (for example, a pairing - * step) and requires both peers to authenticate each other. In such scenarios a symmetric key (PSK) - * can be exchanged during the bootstrapping step, removing the need to generate and exchange public - * key pairs and X.509 certificates.</p> - * - * <p>When a TLS-PSK cipher suite is used, both peers have to use the same key for the TLS/SSL - * handshake to succeed. Thus, both peers are implicitly authenticated by a successful handshake. - * This removes the need to use a {@code TrustManager} in conjunction with this {@code KeyManager}. - * </p> - * - * <h3>Supporting multiple keys</h3> - * - * <p>A peer may have multiple keys to choose from. To help choose the right key, during the - * handshake the server can provide a <em>PSK identity hint</em> to the client, and the client can - * provide a <em>PSK identity</em> to the server. The contents of these two pieces of information - * are specific to application-level protocols.</p> - * - * <p><em>NOTE: Both the PSK identity hint and the PSK identity are transmitted in cleartext. - * Moreover, these data are received and processed prior to peer having been authenticated. Thus, - * they must not contain or leak key material or other sensitive information, and should be - * treated (e.g., parsed) with caution, as untrusted data.</em></p> - * - * <p>The high-level flow leading to peers choosing a key during TLS/SSL handshake is as follows: - * <ol> - * <li>Server receives a handshake request from client. - * <li>Server replies, optionally providing a PSK identity hint to client.</li> - * <li>Client chooses the key.</li> - * <li>Client provides a PSK identity of the chosen key to server.</li> - * <li>Server chooses the key.</li> - * </ol></p> - * - * <p>In the flow above, either peer can signal that they do not have a suitable key, in which case - * the the handshake will be aborted immediately. This may enable a network attacker who does not - * know the key to learn which PSK identity hints or PSK identities are supported. If this is a - * concern then a randomly generated key should be used in the scenario where no key is available. - * This will lead to the handshake aborting later, due to key mismatch -- same as in the scenario - * where a key is available -- making it appear to the attacker that all PSK identity hints and PSK - * identities are supported.</p> - * - * <h3>Maximum sizes</h3> - * - * <p>The maximum supported sizes are as follows: - * <ul> - * <li>256 bytes for keys (see {@link #MAX_KEY_LENGTH_BYTES}),</li> - * <li>128 bytes for PSK identity and PSK identity hint (in modified UTF-8 representation) (see - * {@link #MAX_IDENTITY_LENGTH_BYTES} and {@link #MAX_IDENTITY_HINT_LENGTH_BYTES}).</li> - * </ul></p> - * - * <h3>Subclassing</h3> - * Subclasses should normally provide their own implementation of {@code getKey} because the default - * implementation returns no key, which aborts the handshake. - * - * <h3>Known issues</h3> - * The implementation of {@code ECDHE_PSK} cipher suites in API Level 21 contains a bug which breaks - * compatibility with other implementations. {@code ECDHE_PSK} cipher suites are enabled by default - * on platforms with API Level 21 when an {@code SSLContext} is initialized with a - * {@code PskKeyManager}. A workaround is to disable {@code ECDHE_PSK} cipher suites on platforms - * with API Level 21. - * - * <h3>Example</h3> - * The following example illustrates how to create an {@code SSLContext} which enables the use of - * TLS-PSK in {@code SSLSocket}, {@code SSLServerSocket} and {@code SSLEngine} instances obtained - * from it. - * <pre> {@code - * PskKeyManager pskKeyManager = ...; - * - * SSLContext sslContext = SSLContext.getInstance("TLS"); - * sslContext.init( - * new KeyManager[] { pskKeyManager }, - * new TrustManager[0], // No TrustManagers needed for TLS-PSK - * null // Use the default source of entropy - * ); - * - * SSLSocket sslSocket = (SSLSocket) sslContext.getSocketFactory().createSocket(...); - * }</pre> - * - * @removed This class is removed because it does not work with TLS 1.3. - */ -public abstract class PskKeyManager implements PSKKeyManager { - // IMPLEMENTATION DETAILS: This class exists only because the default implemenetation of the - // TLS/SSL JSSE provider (currently Conscrypt) cannot depend on Android framework classes. - // As a result, this framework class simply extends the PSKKeyManager interface from Conscrypt - // without adding any new methods or fields. Moreover, for technical reasons (Conscrypt classes - // are "hidden") this class replaces the Javadoc of Conscrypt's PSKKeyManager. - - /** - * Maximum supported length (in bytes) for PSK identity hint (in modified UTF-8 representation). - */ - public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = - PSKKeyManager.MAX_IDENTITY_HINT_LENGTH_BYTES; - - /** Maximum supported length (in bytes) for PSK identity (in modified UTF-8 representation). */ - public static final int MAX_IDENTITY_LENGTH_BYTES = PSKKeyManager.MAX_IDENTITY_LENGTH_BYTES; - - /** Maximum supported length (in bytes) for PSK. */ - public static final int MAX_KEY_LENGTH_BYTES = PSKKeyManager.MAX_KEY_LENGTH_BYTES; - - /** - * Gets the PSK identity hint to report to the client to help agree on the PSK for the provided - * socket. - * - * <p> - * The default implementation returns {@code null}. - * - * @return PSK identity hint to be provided to the client or {@code null} to provide no hint. - */ - @Override - public String chooseServerKeyIdentityHint(Socket socket) { - return null; - } - - /** - * Gets the PSK identity hint to report to the client to help agree on the PSK for the provided - * engine. - * - * <p> - * The default implementation returns {@code null}. - * - * @return PSK identity hint to be provided to the client or {@code null} to provide no hint. - */ - @Override - public String chooseServerKeyIdentityHint(SSLEngine engine) { - return null; - } - - /** - * Gets the PSK identity to report to the server to help agree on the PSK for the provided - * socket. - * - * <p> - * The default implementation returns an empty string. - * - * @param identityHint identity hint provided by the server or {@code null} if none provided. - * - * @return PSK identity to provide to the server. {@code null} is permitted but will be - * converted into an empty string. - */ - @Override - public String chooseClientKeyIdentity(String identityHint, Socket socket) { - return ""; - } - - /** - * Gets the PSK identity to report to the server to help agree on the PSK for the provided - * engine. - * - * <p> - * The default implementation returns an empty string. - * - * @param identityHint identity hint provided by the server or {@code null} if none provided. - * - * @return PSK identity to provide to the server. {@code null} is permitted but will be - * converted into an empty string. - */ - @Override - public String chooseClientKeyIdentity(String identityHint, SSLEngine engine) { - return ""; - } - - /** - * Gets the PSK to use for the provided socket. - * - * <p> - * The default implementation returns {@code null}. - * - * @param identityHint identity hint provided by the server to help select the key or - * {@code null} if none provided. - * @param identity identity provided by the client to help select the key. - * - * @return key or {@code null} to signal to peer that no suitable key is available and to abort - * the handshake. - */ - @Override - public SecretKey getKey(String identityHint, String identity, Socket socket) { - return null; - } - - /** - * Gets the PSK to use for the provided engine. - * - * <p> - * The default implementation returns {@code null}. - * - * @param identityHint identity hint provided by the server to help select the key or - * {@code null} if none provided. - * @param identity identity provided by the client to help select the key. - * - * @return key or {@code null} to signal to peer that no suitable key is available and to abort - * the handshake. - */ - @Override - public SecretKey getKey(String identityHint, String identity, SSLEngine engine) { - return null; - } -} diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java index 666da0a455fa..e38d227bb4e6 100644 --- a/core/java/android/net/ScoredNetwork.java +++ b/core/java/android/net/ScoredNetwork.java @@ -16,18 +16,14 @@ package android.net; -import android.annotation.IntDef; import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; -import java.lang.Math; -import java.lang.UnsupportedOperationException; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.util.Objects; +import java.util.Set; /** * A network identifier along with a score for the quality of that network. @@ -195,7 +191,28 @@ public class ScoredNetwork implements Parcelable { return Objects.equals(networkKey, that.networkKey) && Objects.equals(rssiCurve, that.rssiCurve) && Objects.equals(meteredHint, that.meteredHint) - && Objects.equals(attributes, that.attributes); + && bundleEquals(attributes, that.attributes); + } + + private boolean bundleEquals(Bundle bundle1, Bundle bundle2) { + if (bundle1 == bundle2) { + return true; + } + if (bundle1 == null || bundle2 == null) { + return false; + } + if (bundle1.size() != bundle2.size()) { + return false; + } + Set<String> keys = bundle1.keySet(); + for (String key : keys) { + Object value1 = bundle1.get(key); + Object value2 = bundle2.get(key); + if (!Objects.equals(value1, value2)) { + return false; + } + } + return true; } @Override diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java index 7fb0c47598c8..185b1818df45 100644 --- a/core/java/android/net/VpnService.java +++ b/core/java/android/net/VpnService.java @@ -152,9 +152,10 @@ public class VpnService extends Service { * </service> * } </pre> * - * <p>This meta-data field defaults to {@code true} if absent. + * <p>This meta-data field defaults to {@code true} if absent. It will only have effect on + * {@link android.os.Build.VERSION_CODES#O_MR1} or higher. */ - public static final String METADATA_SUPPORTS_ALWAYS_ON = + public static final String SERVICE_META_DATA_SUPPORTS_ALWAYS_ON = "android.net.VpnService.SUPPORTS_ALWAYS_ON"; /** diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 7852125db6f0..935f5f3b78a7 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -773,7 +773,12 @@ public class Build { /** * O MR1. */ - public static final int O_MR1 = CUR_DEVELOPMENT; // STOPSHIP Replace with the real version. + public static final int O_MR1 = 27; + + /** + * P. + */ + public static final int P = CUR_DEVELOPMENT; // STOPSHIP Replace with the real version. } /** The type of build, like "user" or "eng". */ diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index b916b4381a5d..05627160cc3a 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -220,6 +220,21 @@ interface INetworkManagementService void unregisterTetheringStatsProvider(ITetheringStatsProvider provider); /** + * Reports that a tethering provider has reached a data limit. + * + * Currently triggers a global alert, which causes NetworkStatsService to poll counters and + * re-evaluate data usage. + * + * This does not take an interface name because: + * 1. The tethering offload stats provider cannot reliably determine the interface on which the + * limit was reached, because the HAL does not provide it. + * 2. Firing an interface-specific alert instead of a global alert isn't really useful since in + * all cases of interest, the system responds to both in the same way - it polls stats, and + * then notifies NetworkPolicyManagerService of the fact. + */ + void tetherLimitReached(ITetheringStatsProvider provider); + + /** ** PPPD **/ @@ -266,7 +281,7 @@ interface INetworkManagementService /** * Return summary of network statistics all tethering interfaces. */ - NetworkStats getNetworkStatsTethering(); + NetworkStats getNetworkStatsTethering(int how); /** * Set quota for an interface. diff --git a/core/java/android/os/IStatsManager.aidl b/core/java/android/os/IStatsManager.aidl new file mode 100644 index 000000000000..9b5139dc5092 --- /dev/null +++ b/core/java/android/os/IStatsManager.aidl @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2016, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +/** + * Binder interface to communicate with the statistics collection service. + * {@hide} + */ +oneway interface IStatsManager { + /** + * Tell the incident daemon that the android system server is up and running. + */ + void systemRunning(); +} diff --git a/core/java/android/os/IncidentManager.java b/core/java/android/os/IncidentManager.java index bc8e2e470c55..1336c66b7133 100644 --- a/core/java/android/os/IncidentManager.java +++ b/core/java/android/os/IncidentManager.java @@ -21,8 +21,6 @@ import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.content.Context; -import android.os.IIncidentManager; -import android.os.ServiceManager; import android.provider.Settings; import android.util.Slog; @@ -37,7 +35,7 @@ import android.util.Slog; public class IncidentManager { private static final String TAG = "incident"; - private Context mContext; + private final Context mContext; /** * @hide @@ -54,18 +52,7 @@ public class IncidentManager { android.Manifest.permission.PACKAGE_USAGE_STATS }) public void reportIncident(IncidentReportArgs args) { - final IIncidentManager service = IIncidentManager.Stub.asInterface( - ServiceManager.getService("incident")); - if (service == null) { - Slog.e(TAG, "reportIncident can't find incident binder service"); - return; - } - - try { - service.reportIncident(args); - } catch (RemoteException ex) { - Slog.e(TAG, "reportIncident failed", ex); - } + reportIncidentInternal(args); } /** @@ -89,7 +76,7 @@ public class IncidentManager { }) public void reportIncident(String settingName, byte[] headerProto) { // Sections - String setting = Settings.System.getString(mContext.getContentResolver(), settingName); + String setting = Settings.Global.getString(mContext.getContentResolver(), settingName); IncidentReportArgs args; try { args = IncidentReportArgs.parseSetting(setting); @@ -98,23 +85,25 @@ public class IncidentManager { return; } if (args == null) { - Slog.i(TAG, "Incident report requested but disabled: " + settingName); + Slog.i(TAG, String.format("Incident report requested but disabled with " + + "settings [name: %s, value: %s]", settingName, setting)); return; } - // Header args.addHeader(headerProto); - // Look up the service + Slog.i(TAG, "Taking incident report: " + settingName); + reportIncidentInternal(args); + } + + private void reportIncidentInternal(IncidentReportArgs args) { final IIncidentManager service = IIncidentManager.Stub.asInterface( - ServiceManager.getService("incident")); + ServiceManager.getService(Context.INCIDENT_SERVICE)); if (service == null) { Slog.e(TAG, "reportIncident can't find incident binder service"); return; } - // Call the service - Slog.i(TAG, "Taking incident report: " + settingName); try { service.reportIncident(args); } catch (RemoteException ex) { diff --git a/core/java/android/os/IncidentReportArgs.java b/core/java/android/os/IncidentReportArgs.java index ce2ae1071d01..abb316171309 100644 --- a/core/java/android/os/IncidentReportArgs.java +++ b/core/java/android/os/IncidentReportArgs.java @@ -18,7 +18,6 @@ package android.os; import android.annotation.SystemApi; import android.annotation.TestApi; -import android.content.Intent; import android.os.Parcel; import android.os.Parcelable; import android.util.IntArray; @@ -50,10 +49,12 @@ public final class IncidentReportArgs implements Parcelable { readFromParcel(in); } + @Override public int describeContents() { return 0; } + @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(mAll ? 1 : 0); @@ -100,6 +101,7 @@ public final class IncidentReportArgs implements Parcelable { /** * Print this report as a string. */ + @Override public String toString() { final StringBuilder sb = new StringBuilder("Incident("); if (mAll) { @@ -131,10 +133,11 @@ public final class IncidentReportArgs implements Parcelable { } /** - * Add this section to the incident report. + * Add this section to the incident report. Skip if the input is smaller than 2 since section + * id are only valid for positive integer as Protobuf field id. Here 1 is reserved for Header. */ public void addSection(int section) { - if (!mAll) { + if (!mAll && section > 1) { mSections.add(section); } } diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index 3e071437b097..4703af06c06e 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -53,31 +53,25 @@ import java.util.HashMap; import java.util.concurrent.atomic.AtomicInteger; /** - * <p>StrictMode is a developer tool which detects things you might be - * doing by accident and brings them to your attention so you can fix - * them. + * StrictMode is a developer tool which detects things you might be doing by accident and brings + * them to your attention so you can fix them. * - * <p>StrictMode is most commonly used to catch accidental disk or - * network access on the application's main thread, where UI - * operations are received and animations take place. Keeping disk - * and network operations off the main thread makes for much smoother, - * more responsive applications. By keeping your application's main thread - * responsive, you also prevent - * <a href="{@docRoot}guide/practices/design/responsiveness.html">ANR dialogs</a> - * from being shown to users. + * <p>StrictMode is most commonly used to catch accidental disk or network access on the + * application's main thread, where UI operations are received and animations take place. Keeping + * disk and network operations off the main thread makes for much smoother, more responsive + * applications. By keeping your application's main thread responsive, you also prevent <a + * href="{@docRoot}guide/practices/design/responsiveness.html">ANR dialogs</a> from being shown to + * users. * - * <p class="note">Note that even though an Android device's disk is - * often on flash memory, many devices run a filesystem on top of that - * memory with very limited concurrency. It's often the case that - * almost all disk accesses are fast, but may in individual cases be - * dramatically slower when certain I/O is happening in the background - * from other processes. If possible, it's best to assume that such - * things are not fast.</p> + * <p class="note">Note that even though an Android device's disk is often on flash memory, many + * devices run a filesystem on top of that memory with very limited concurrency. It's often the case + * that almost all disk accesses are fast, but may in individual cases be dramatically slower when + * certain I/O is happening in the background from other processes. If possible, it's best to assume + * that such things are not fast. * - * <p>Example code to enable from early in your - * {@link android.app.Application}, {@link android.app.Activity}, or - * other application component's - * {@link android.app.Application#onCreate} method: + * <p>Example code to enable from early in your {@link android.app.Application}, {@link + * android.app.Activity}, or other application component's {@link android.app.Application#onCreate} + * method: * * <pre> * public void onCreate() { @@ -99,36 +93,32 @@ import java.util.concurrent.atomic.AtomicInteger; * } * </pre> * - * <p>You can decide what should happen when a violation is detected. - * For example, using {@link ThreadPolicy.Builder#penaltyLog} you can - * watch the output of <code>adb logcat</code> while you use your - * application to see the violations as they happen. + * <p>You can decide what should happen when a violation is detected. For example, using {@link + * ThreadPolicy.Builder#penaltyLog} you can watch the output of <code>adb logcat</code> while you + * use your application to see the violations as they happen. * - * <p>If you find violations that you feel are problematic, there are - * a variety of tools to help solve them: threads, {@link android.os.Handler}, - * {@link android.os.AsyncTask}, {@link android.app.IntentService}, etc. - * But don't feel compelled to fix everything that StrictMode finds. In particular, - * many cases of disk access are often necessary during the normal activity lifecycle. Use - * StrictMode to find things you did by accident. Network requests on the UI thread + * <p>If you find violations that you feel are problematic, there are a variety of tools to help + * solve them: threads, {@link android.os.Handler}, {@link android.os.AsyncTask}, {@link + * android.app.IntentService}, etc. But don't feel compelled to fix everything that StrictMode + * finds. In particular, many cases of disk access are often necessary during the normal activity + * lifecycle. Use StrictMode to find things you did by accident. Network requests on the UI thread * are almost always a problem, though. * - * <p class="note">StrictMode is not a security mechanism and is not - * guaranteed to find all disk or network accesses. While it does - * propagate its state across process boundaries when doing - * {@link android.os.Binder} calls, it's still ultimately a best - * effort mechanism. Notably, disk or network access from JNI calls - * won't necessarily trigger it. Future versions of Android may catch - * more (or fewer) operations, so you should never leave StrictMode - * enabled in applications distributed on Google Play. + * <p class="note">StrictMode is not a security mechanism and is not guaranteed to find all disk or + * network accesses. While it does propagate its state across process boundaries when doing {@link + * android.os.Binder} calls, it's still ultimately a best effort mechanism. Notably, disk or network + * access from JNI calls won't necessarily trigger it. Future versions of Android may catch more (or + * fewer) operations, so you should never leave StrictMode enabled in applications distributed on + * Google Play. */ public final class StrictMode { private static final String TAG = "StrictMode"; private static final boolean LOG_V = Log.isLoggable(TAG, Log.VERBOSE); /** - * Boolean system property to disable strict mode checks outright. - * Set this to 'true' to force disable; 'false' has no effect on other - * enable/disable policy. + * Boolean system property to disable strict mode checks outright. Set this to 'true' to force + * disable; 'false' has no effect on other enable/disable policy. + * * @hide */ public static final String DISABLE_PROPERTY = "persist.sys.strictmode.disable"; @@ -141,9 +131,9 @@ public final class StrictMode { public static final String VISUAL_PROPERTY = "persist.sys.strictmode.visual"; /** - * Temporary property used to include {@link #DETECT_VM_CLEARTEXT_NETWORK} - * in {@link VmPolicy.Builder#detectAll()}. Apps can still always opt-into - * detection using {@link VmPolicy.Builder#detectCleartextNetwork()}. + * Temporary property used to include {@link #DETECT_VM_CLEARTEXT_NETWORK} in {@link + * VmPolicy.Builder#detectAll()}. Apps can still always opt-into detection using {@link + * VmPolicy.Builder#detectCleartextNetwork()}. */ private static final String CLEARTEXT_PROPERTY = "persist.sys.strictmode.clear"; @@ -162,105 +152,96 @@ public final class StrictMode { // Byte 1: Thread-policy - /** - * @hide - */ - public static final int DETECT_DISK_WRITE = 0x01; // for ThreadPolicy + /** @hide */ + public static final int DETECT_DISK_WRITE = 0x01; // for ThreadPolicy - /** - * @hide - */ - public static final int DETECT_DISK_READ = 0x02; // for ThreadPolicy + /** @hide */ + public static final int DETECT_DISK_READ = 0x02; // for ThreadPolicy - /** - * @hide - */ - public static final int DETECT_NETWORK = 0x04; // for ThreadPolicy + /** @hide */ + public static final int DETECT_NETWORK = 0x04; // for ThreadPolicy /** * For StrictMode.noteSlowCall() * * @hide */ - public static final int DETECT_CUSTOM = 0x08; // for ThreadPolicy + public static final int DETECT_CUSTOM = 0x08; // for ThreadPolicy /** * For StrictMode.noteResourceMismatch() * * @hide */ - public static final int DETECT_RESOURCE_MISMATCH = 0x10; // for ThreadPolicy + public static final int DETECT_RESOURCE_MISMATCH = 0x10; // for ThreadPolicy - /** - * @hide - */ - public static final int DETECT_UNBUFFERED_IO = 0x20; // for ThreadPolicy + /** @hide */ + public static final int DETECT_UNBUFFERED_IO = 0x20; // for ThreadPolicy private static final int ALL_THREAD_DETECT_BITS = - DETECT_DISK_WRITE | DETECT_DISK_READ | DETECT_NETWORK | DETECT_CUSTOM | - DETECT_RESOURCE_MISMATCH | DETECT_UNBUFFERED_IO; + DETECT_DISK_WRITE + | DETECT_DISK_READ + | DETECT_NETWORK + | DETECT_CUSTOM + | DETECT_RESOURCE_MISMATCH + | DETECT_UNBUFFERED_IO; // Byte 2: Process-policy /** * Note, a "VM_" bit, not thread. + * * @hide */ - public static final int DETECT_VM_CURSOR_LEAKS = 0x01 << 8; // for VmPolicy + public static final int DETECT_VM_CURSOR_LEAKS = 0x01 << 8; // for VmPolicy /** * Note, a "VM_" bit, not thread. + * * @hide */ - public static final int DETECT_VM_CLOSABLE_LEAKS = 0x02 << 8; // for VmPolicy + public static final int DETECT_VM_CLOSABLE_LEAKS = 0x02 << 8; // for VmPolicy /** * Note, a "VM_" bit, not thread. + * * @hide */ - public static final int DETECT_VM_ACTIVITY_LEAKS = 0x04 << 8; // for VmPolicy + public static final int DETECT_VM_ACTIVITY_LEAKS = 0x04 << 8; // for VmPolicy - /** - * @hide - */ - private static final int DETECT_VM_INSTANCE_LEAKS = 0x08 << 8; // for VmPolicy + /** @hide */ + private static final int DETECT_VM_INSTANCE_LEAKS = 0x08 << 8; // for VmPolicy - /** - * @hide - */ - public static final int DETECT_VM_REGISTRATION_LEAKS = 0x10 << 8; // for VmPolicy + /** @hide */ + public static final int DETECT_VM_REGISTRATION_LEAKS = 0x10 << 8; // for VmPolicy - /** - * @hide - */ - private static final int DETECT_VM_FILE_URI_EXPOSURE = 0x20 << 8; // for VmPolicy + /** @hide */ + private static final int DETECT_VM_FILE_URI_EXPOSURE = 0x20 << 8; // for VmPolicy - /** - * @hide - */ - private static final int DETECT_VM_CLEARTEXT_NETWORK = 0x40 << 8; // for VmPolicy + /** @hide */ + private static final int DETECT_VM_CLEARTEXT_NETWORK = 0x40 << 8; // for VmPolicy - /** - * @hide - */ - private static final int DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION = 0x80 << 8; // for VmPolicy + /** @hide */ + private static final int DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION = 0x80 << 8; // for VmPolicy - /** - * @hide - */ - private static final int DETECT_VM_UNTAGGED_SOCKET = 0x80 << 24; // for VmPolicy + /** @hide */ + private static final int DETECT_VM_UNTAGGED_SOCKET = 0x80 << 24; // for VmPolicy private static final int ALL_VM_DETECT_BITS = - DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS | - DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_INSTANCE_LEAKS | - DETECT_VM_REGISTRATION_LEAKS | DETECT_VM_FILE_URI_EXPOSURE | - DETECT_VM_CLEARTEXT_NETWORK | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION | - DETECT_VM_UNTAGGED_SOCKET; + DETECT_VM_CURSOR_LEAKS + | DETECT_VM_CLOSABLE_LEAKS + | DETECT_VM_ACTIVITY_LEAKS + | DETECT_VM_INSTANCE_LEAKS + | DETECT_VM_REGISTRATION_LEAKS + | DETECT_VM_FILE_URI_EXPOSURE + | DETECT_VM_CLEARTEXT_NETWORK + | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION + | DETECT_VM_UNTAGGED_SOCKET; // Byte 3: Penalty /** {@hide} */ - public static final int PENALTY_LOG = 0x01 << 16; // normal android.util.Log + public static final int PENALTY_LOG = 0x01 << 16; // normal android.util.Log /** {@hide} */ public static final int PENALTY_DIALOG = 0x02 << 16; /** {@hide} */ @@ -271,13 +252,11 @@ public final class StrictMode { public static final int PENALTY_DROPBOX = 0x20 << 16; /** - * Non-public penalty mode which overrides all the other penalty - * bits and signals that we're in a Binder call and we should - * ignore the other penalty bits and instead serialize back all - * our offending stack traces to the caller to ultimately handle - * in the originating process. + * Non-public penalty mode which overrides all the other penalty bits and signals that we're in + * a Binder call and we should ignore the other penalty bits and instead serialize back all our + * offending stack traces to the caller to ultimately handle in the originating process. * - * This must be kept in sync with the constant in libs/binder/Parcel.cpp + * <p>This must be kept in sync with the constant in libs/binder/Parcel.cpp * * @hide */ @@ -308,18 +287,23 @@ public final class StrictMode { // CAUTION: we started stealing the top bits of Byte 4 for VM above - /** - * Mask of all the penalty bits valid for thread policies. - */ + /** Mask of all the penalty bits valid for thread policies. */ private static final int THREAD_PENALTY_MASK = - PENALTY_LOG | PENALTY_DIALOG | PENALTY_DEATH | PENALTY_DROPBOX | PENALTY_GATHER | - PENALTY_DEATH_ON_NETWORK | PENALTY_FLASH; - - /** - * Mask of all the penalty bits valid for VM policies. - */ - private static final int VM_PENALTY_MASK = PENALTY_LOG | PENALTY_DEATH | PENALTY_DROPBOX - | PENALTY_DEATH_ON_CLEARTEXT_NETWORK | PENALTY_DEATH_ON_FILE_URI_EXPOSURE; + PENALTY_LOG + | PENALTY_DIALOG + | PENALTY_DEATH + | PENALTY_DROPBOX + | PENALTY_GATHER + | PENALTY_DEATH_ON_NETWORK + | PENALTY_FLASH; + + /** Mask of all the penalty bits valid for VM policies. */ + private static final int VM_PENALTY_MASK = + PENALTY_LOG + | PENALTY_DEATH + | PENALTY_DROPBOX + | PENALTY_DEATH_ON_CLEARTEXT_NETWORK + | PENALTY_DEATH_ON_FILE_URI_EXPOSURE; /** {@hide} */ public static final int NETWORK_POLICY_ACCEPT = 0; @@ -330,14 +314,16 @@ public final class StrictMode { // TODO: wrap in some ImmutableHashMap thing. // Note: must be before static initialization of sVmPolicy. - private static final HashMap<Class, Integer> EMPTY_CLASS_LIMIT_MAP = new HashMap<Class, Integer>(); + private static final HashMap<Class, Integer> EMPTY_CLASS_LIMIT_MAP = + new HashMap<Class, Integer>(); /** * The current VmPolicy in effect. * - * TODO: these are redundant (mask is in VmPolicy). Should remove sVmPolicyMask. + * <p>TODO: these are redundant (mask is in VmPolicy). Should remove sVmPolicyMask. */ private static volatile int sVmPolicyMask = 0; + private static volatile VmPolicy sVmPolicy = VmPolicy.LAX; /** {@hide} */ @@ -355,8 +341,8 @@ public final class StrictMode { } /** - * The number of threads trying to do an async dropbox write. - * Just to limit ourselves out of paranoia. + * The number of threads trying to do an async dropbox write. Just to limit ourselves out of + * paranoia. */ private static final AtomicInteger sDropboxCallsInFlight = new AtomicInteger(0); @@ -365,18 +351,15 @@ public final class StrictMode { /** * {@link StrictMode} policy applied to a certain thread. * - * <p>The policy is enabled by {@link #setThreadPolicy}. The current policy - * can be retrieved with {@link #getThreadPolicy}. + * <p>The policy is enabled by {@link #setThreadPolicy}. The current policy can be retrieved + * with {@link #getThreadPolicy}. * - * <p>Note that multiple penalties may be provided and they're run - * in order from least to most severe (logging before process - * death, for example). There's currently no mechanism to choose + * <p>Note that multiple penalties may be provided and they're run in order from least to most + * severe (logging before process death, for example). There's currently no mechanism to choose * different penalties for different detected actions. */ public static final class ThreadPolicy { - /** - * The default, lax policy which doesn't catch anything. - */ + /** The default, lax policy which doesn't catch anything. */ public static final ThreadPolicy LAX = new ThreadPolicy(0); final int mask; @@ -391,16 +374,15 @@ public final class StrictMode { } /** - * Creates {@link ThreadPolicy} instances. Methods whose names start - * with {@code detect} specify what problems we should look - * for. Methods whose names start with {@code penalty} specify what - * we should do when we detect a problem. + * Creates {@link ThreadPolicy} instances. Methods whose names start with {@code detect} + * specify what problems we should look for. Methods whose names start with {@code penalty} + * specify what we should do when we detect a problem. * - * <p>You can call as many {@code detect} and {@code penalty} - * methods as you like. Currently order is insignificant: all - * penalties apply to all detected problems. + * <p>You can call as many {@code detect} and {@code penalty} methods as you like. Currently + * order is insignificant: all penalties apply to all detected problems. * * <p>For example, detect everything and log anything that's found: + * * <pre> * StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder() * .detectAll() @@ -413,18 +395,15 @@ public final class StrictMode { private int mMask = 0; /** - * Create a Builder that detects nothing and has no - * violations. (but note that {@link #build} will default - * to enabling {@link #penaltyLog} if no other penalties - * are specified) + * Create a Builder that detects nothing and has no violations. (but note that {@link + * #build} will default to enabling {@link #penaltyLog} if no other penalties are + * specified) */ public Builder() { mMask = 0; } - /** - * Initialize a Builder from an existing ThreadPolicy. - */ + /** Initialize a Builder from an existing ThreadPolicy. */ public Builder(ThreadPolicy policy) { mMask = policy.mask; } @@ -432,8 +411,8 @@ public final class StrictMode { /** * Detect everything that's potentially suspect. * - * <p>As of the Gingerbread release this includes network and - * disk operations but will likely expand in future releases. + * <p>As of the Gingerbread release this includes network and disk operations but will + * likely expand in future releases. */ public Builder detectAll() { detectDiskReads(); @@ -453,135 +432,106 @@ public final class StrictMode { return this; } - /** - * Disable the detection of everything. - */ + /** Disable the detection of everything. */ public Builder permitAll() { return disable(ALL_THREAD_DETECT_BITS); } - /** - * Enable detection of network operations. - */ + /** Enable detection of network operations. */ public Builder detectNetwork() { return enable(DETECT_NETWORK); } - /** - * Disable detection of network operations. - */ + /** Disable detection of network operations. */ public Builder permitNetwork() { return disable(DETECT_NETWORK); } - /** - * Enable detection of disk reads. - */ + /** Enable detection of disk reads. */ public Builder detectDiskReads() { return enable(DETECT_DISK_READ); } - /** - * Disable detection of disk reads. - */ + /** Disable detection of disk reads. */ public Builder permitDiskReads() { return disable(DETECT_DISK_READ); } - /** - * Enable detection of slow calls. - */ + /** Enable detection of slow calls. */ public Builder detectCustomSlowCalls() { return enable(DETECT_CUSTOM); } - /** - * Disable detection of slow calls. - */ + /** Disable detection of slow calls. */ public Builder permitCustomSlowCalls() { return disable(DETECT_CUSTOM); } - /** - * Disable detection of mismatches between defined resource types - * and getter calls. - */ + /** Disable detection of mismatches between defined resource types and getter calls. */ public Builder permitResourceMismatches() { return disable(DETECT_RESOURCE_MISMATCH); } - /** - * Detect unbuffered input/output operations. - */ + /** Detect unbuffered input/output operations. */ public Builder detectUnbufferedIo() { return enable(DETECT_UNBUFFERED_IO); } - /** - * Disable detection of unbuffered input/output operations. - */ + /** Disable detection of unbuffered input/output operations. */ public Builder permitUnbufferedIo() { return disable(DETECT_UNBUFFERED_IO); } /** - * Enables detection of mismatches between defined resource types - * and getter calls. - * <p> - * This helps detect accidental type mismatches and potentially - * expensive type conversions when obtaining typed resources. - * <p> - * For example, a strict mode violation would be thrown when - * calling {@link android.content.res.TypedArray#getInt(int, int)} - * on an index that contains a String-type resource. If the string - * value can be parsed as an integer, this method call will return - * a value without crashing; however, the developer should format - * the resource as an integer to avoid unnecessary type conversion. + * Enables detection of mismatches between defined resource types and getter calls. + * + * <p>This helps detect accidental type mismatches and potentially expensive type + * conversions when obtaining typed resources. + * + * <p>For example, a strict mode violation would be thrown when calling {@link + * android.content.res.TypedArray#getInt(int, int)} on an index that contains a + * String-type resource. If the string value can be parsed as an integer, this method + * call will return a value without crashing; however, the developer should format the + * resource as an integer to avoid unnecessary type conversion. */ public Builder detectResourceMismatches() { return enable(DETECT_RESOURCE_MISMATCH); } - /** - * Enable detection of disk writes. - */ + /** Enable detection of disk writes. */ public Builder detectDiskWrites() { return enable(DETECT_DISK_WRITE); } - /** - * Disable detection of disk writes. - */ + /** Disable detection of disk writes. */ public Builder permitDiskWrites() { return disable(DETECT_DISK_WRITE); } /** - * Show an annoying dialog to the developer on detected - * violations, rate-limited to be only a little annoying. + * Show an annoying dialog to the developer on detected violations, rate-limited to be + * only a little annoying. */ public Builder penaltyDialog() { return enable(PENALTY_DIALOG); } /** - * Crash the whole process on violation. This penalty runs at - * the end of all enabled penalties so you'll still get - * see logging or other violations before the process dies. + * Crash the whole process on violation. This penalty runs at the end of all enabled + * penalties so you'll still get see logging or other violations before the process + * dies. * - * <p>Unlike {@link #penaltyDeathOnNetwork}, this applies - * to disk reads, disk writes, and network usage if their - * corresponding detect flags are set. + * <p>Unlike {@link #penaltyDeathOnNetwork}, this applies to disk reads, disk writes, + * and network usage if their corresponding detect flags are set. */ public Builder penaltyDeath() { return enable(PENALTY_DEATH); } /** - * Crash the whole process on any network usage. Unlike - * {@link #penaltyDeath}, this penalty runs - * <em>before</em> anything else. You must still have - * called {@link #detectNetwork} to enable this. + * Crash the whole process on any network usage. Unlike {@link #penaltyDeath}, this + * penalty runs <em>before</em> anything else. You must still have called {@link + * #detectNetwork} to enable this. * * <p>In the Honeycomb or later SDKs, this is on by default. */ @@ -589,25 +539,20 @@ public final class StrictMode { return enable(PENALTY_DEATH_ON_NETWORK); } - /** - * Flash the screen during a violation. - */ + /** Flash the screen during a violation. */ public Builder penaltyFlashScreen() { return enable(PENALTY_FLASH); } - /** - * Log detected violations to the system log. - */ + /** Log detected violations to the system log. */ public Builder penaltyLog() { return enable(PENALTY_LOG); } /** - * Enable detected violations log a stacktrace and timing data - * to the {@link android.os.DropBoxManager DropBox} on policy - * violation. Intended mostly for platform integrators doing - * beta user field data collection. + * Enable detected violations log a stacktrace and timing data to the {@link + * android.os.DropBoxManager DropBox} on policy violation. Intended mostly for platform + * integrators doing beta user field data collection. */ public Builder penaltyDropBox() { return enable(PENALTY_DROPBOX); @@ -626,16 +571,19 @@ public final class StrictMode { /** * Construct the ThreadPolicy instance. * - * <p>Note: if no penalties are enabled before calling - * <code>build</code>, {@link #penaltyLog} is implicitly - * set. + * <p>Note: if no penalties are enabled before calling <code>build</code>, {@link + * #penaltyLog} is implicitly set. */ public ThreadPolicy build() { // If there are detection bits set but no violation bits // set, enable simple logging. - if (mMask != 0 && - (mMask & (PENALTY_DEATH | PENALTY_LOG | - PENALTY_DROPBOX | PENALTY_DIALOG)) == 0) { + if (mMask != 0 + && (mMask + & (PENALTY_DEATH + | PENALTY_LOG + | PENALTY_DROPBOX + | PENALTY_DIALOG)) + == 0) { penaltyLog(); } return new ThreadPolicy(mMask); @@ -649,9 +597,7 @@ public final class StrictMode { * <p>The policy is enabled by {@link #setVmPolicy}. */ public static final class VmPolicy { - /** - * The default, lax policy which doesn't catch anything. - */ + /** The default, lax policy which doesn't catch anything. */ public static final VmPolicy LAX = new VmPolicy(0, EMPTY_CLASS_LIMIT_MAP); final int mask; @@ -673,16 +619,15 @@ public final class StrictMode { } /** - * Creates {@link VmPolicy} instances. Methods whose names start - * with {@code detect} specify what problems we should look - * for. Methods whose names start with {@code penalty} specify what - * we should do when we detect a problem. + * Creates {@link VmPolicy} instances. Methods whose names start with {@code detect} specify + * what problems we should look for. Methods whose names start with {@code penalty} specify + * what we should do when we detect a problem. * - * <p>You can call as many {@code detect} and {@code penalty} - * methods as you like. Currently order is insignificant: all - * penalties apply to all detected problems. + * <p>You can call as many {@code detect} and {@code penalty} methods as you like. Currently + * order is insignificant: all penalties apply to all detected problems. * * <p>For example, detect everything and log anything that's found: + * * <pre> * StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder() * .detectAll() @@ -694,16 +639,14 @@ public final class StrictMode { public static final class Builder { private int mMask; - private HashMap<Class, Integer> mClassInstanceLimit; // null until needed - private boolean mClassInstanceLimitNeedCow = false; // need copy-on-write + private HashMap<Class, Integer> mClassInstanceLimit; // null until needed + private boolean mClassInstanceLimitNeedCow = false; // need copy-on-write public Builder() { mMask = 0; } - /** - * Build upon an existing VmPolicy. - */ + /** Build upon an existing VmPolicy. */ public Builder(VmPolicy base) { mMask = base.mask; mClassInstanceLimitNeedCow = true; @@ -711,16 +654,16 @@ public final class StrictMode { } /** - * Set an upper bound on how many instances of a class can be in memory - * at once. Helps to prevent object leaks. + * Set an upper bound on how many instances of a class can be in memory at once. Helps + * to prevent object leaks. */ public Builder setClassInstanceLimit(Class klass, int instanceLimit) { if (klass == null) { throw new NullPointerException("klass == null"); } if (mClassInstanceLimitNeedCow) { - if (mClassInstanceLimit.containsKey(klass) && - mClassInstanceLimit.get(klass) == instanceLimit) { + if (mClassInstanceLimit.containsKey(klass) + && mClassInstanceLimit.get(klass) == instanceLimit) { // no-op; don't break COW return this; } @@ -734,9 +677,7 @@ public final class StrictMode { return this; } - /** - * Detect leaks of {@link android.app.Activity} subclasses. - */ + /** Detect leaks of {@link android.app.Activity} subclasses. */ public Builder detectActivityLeaks() { return enable(DETECT_VM_ACTIVITY_LEAKS); } @@ -744,9 +685,8 @@ public final class StrictMode { /** * Detect everything that's potentially suspect. * - * <p>In the Honeycomb release this includes leaks of - * SQLite cursors, Activities, and other closable objects - * but will likely expand in future releases. + * <p>In the Honeycomb release this includes leaks of SQLite cursors, Activities, and + * other closable objects but will likely expand in future releases. */ public Builder detectAll() { detectLeakedSqlLiteObjects(); @@ -777,53 +717,46 @@ public final class StrictMode { } /** - * Detect when an - * {@link android.database.sqlite.SQLiteCursor} or other - * SQLite object is finalized without having been closed. + * Detect when an {@link android.database.sqlite.SQLiteCursor} or other SQLite object is + * finalized without having been closed. * - * <p>You always want to explicitly close your SQLite - * cursors to avoid unnecessary database contention and - * temporary memory leaks. + * <p>You always want to explicitly close your SQLite cursors to avoid unnecessary + * database contention and temporary memory leaks. */ public Builder detectLeakedSqlLiteObjects() { return enable(DETECT_VM_CURSOR_LEAKS); } /** - * Detect when an {@link java.io.Closeable} or other - * object with a explict termination method is finalized - * without having been closed. + * Detect when an {@link java.io.Closeable} or other object with a explict termination + * method is finalized without having been closed. * - * <p>You always want to explicitly close such objects to - * avoid unnecessary resources leaks. + * <p>You always want to explicitly close such objects to avoid unnecessary resources + * leaks. */ public Builder detectLeakedClosableObjects() { return enable(DETECT_VM_CLOSABLE_LEAKS); } /** - * Detect when a {@link BroadcastReceiver} or - * {@link ServiceConnection} is leaked during {@link Context} - * teardown. + * Detect when a {@link BroadcastReceiver} or {@link ServiceConnection} is leaked during + * {@link Context} teardown. */ public Builder detectLeakedRegistrationObjects() { return enable(DETECT_VM_REGISTRATION_LEAKS); } /** - * Detect when the calling application exposes a {@code file://} - * {@link android.net.Uri} to another app. - * <p> - * This exposure is discouraged since the receiving app may not have - * access to the shared path. For example, the receiving app may not - * have requested the - * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} runtime - * permission, or the platform may be sharing the - * {@link android.net.Uri} across user profile boundaries. - * <p> - * Instead, apps should use {@code content://} Uris so the platform - * can extend temporary permission for the receiving app to access - * the resource. + * Detect when the calling application exposes a {@code file://} {@link android.net.Uri} + * to another app. + * + * <p>This exposure is discouraged since the receiving app may not have access to the + * shared path. For example, the receiving app may not have requested the {@link + * android.Manifest.permission#READ_EXTERNAL_STORAGE} runtime permission, or the + * platform may be sharing the {@link android.net.Uri} across user profile boundaries. + * + * <p>Instead, apps should use {@code content://} Uris so the platform can extend + * temporary permission for the receiving app to access the resource. * * @see android.support.v4.content.FileProvider * @see Intent#FLAG_GRANT_READ_URI_PERMISSION @@ -833,34 +766,32 @@ public final class StrictMode { } /** - * Detect any network traffic from the calling app which is not - * wrapped in SSL/TLS. This can help you detect places that your app - * is inadvertently sending cleartext data across the network. - * <p> - * Using {@link #penaltyDeath()} or - * {@link #penaltyDeathOnCleartextNetwork()} will block further - * traffic on that socket to prevent accidental data leakage, in - * addition to crashing your process. - * <p> - * Using {@link #penaltyDropBox()} will log the raw contents of the - * packet that triggered the violation. - * <p> - * This inspects both IPv4/IPv6 and TCP/UDP network traffic, but it - * may be subject to false positives, such as when STARTTLS - * protocols or HTTP proxies are used. + * Detect any network traffic from the calling app which is not wrapped in SSL/TLS. This + * can help you detect places that your app is inadvertently sending cleartext data + * across the network. + * + * <p>Using {@link #penaltyDeath()} or {@link #penaltyDeathOnCleartextNetwork()} will + * block further traffic on that socket to prevent accidental data leakage, in addition + * to crashing your process. + * + * <p>Using {@link #penaltyDropBox()} will log the raw contents of the packet that + * triggered the violation. + * + * <p>This inspects both IPv4/IPv6 and TCP/UDP network traffic, but it may be subject to + * false positives, such as when STARTTLS protocols or HTTP proxies are used. */ public Builder detectCleartextNetwork() { return enable(DETECT_VM_CLEARTEXT_NETWORK); } /** - * Detect when the calling application sends a {@code content://} - * {@link android.net.Uri} to another app without setting - * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} or - * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION}. - * <p> - * Forgetting to include one or more of these flags when sending an - * intent is typically an app bug. + * Detect when the calling application sends a {@code content://} {@link + * android.net.Uri} to another app without setting {@link + * Intent#FLAG_GRANT_READ_URI_PERMISSION} or {@link + * Intent#FLAG_GRANT_WRITE_URI_PERMISSION}. + * + * <p>Forgetting to include one or more of these flags when sending an intent is + * typically an app bug. * * @see Intent#FLAG_GRANT_READ_URI_PERMISSION * @see Intent#FLAG_GRANT_WRITE_URI_PERMISSION @@ -870,12 +801,11 @@ public final class StrictMode { } /** - * Detect any sockets in the calling app which have not been tagged - * using {@link TrafficStats}. Tagging sockets can help you - * investigate network usage inside your app, such as a narrowing - * down heavy usage to a specific library or component. - * <p> - * This currently does not detect sockets created in native code. + * Detect any sockets in the calling app which have not been tagged using {@link + * TrafficStats}. Tagging sockets can help you investigate network usage inside your + * app, such as a narrowing down heavy usage to a specific library or component. + * + * <p>This currently does not detect sockets created in native code. * * @see TrafficStats#setThreadStatsTag(int) * @see TrafficStats#tagSocket(java.net.Socket) @@ -886,17 +816,16 @@ public final class StrictMode { } /** - * Crashes the whole process on violation. This penalty runs at the - * end of all enabled penalties so you'll still get your logging or - * other violations before the process dies. + * Crashes the whole process on violation. This penalty runs at the end of all enabled + * penalties so you'll still get your logging or other violations before the process + * dies. */ public Builder penaltyDeath() { return enable(PENALTY_DEATH); } /** - * Crashes the whole process when cleartext network traffic is - * detected. + * Crashes the whole process when cleartext network traffic is detected. * * @see #detectCleartextNetwork() */ @@ -905,8 +834,8 @@ public final class StrictMode { } /** - * Crashes the whole process when a {@code file://} - * {@link android.net.Uri} is exposed beyond this app. + * Crashes the whole process when a {@code file://} {@link android.net.Uri} is exposed + * beyond this app. * * @see #detectFileUriExposure() */ @@ -914,18 +843,15 @@ public final class StrictMode { return enable(PENALTY_DEATH_ON_FILE_URI_EXPOSURE); } - /** - * Log detected violations to the system log. - */ + /** Log detected violations to the system log. */ public Builder penaltyLog() { return enable(PENALTY_LOG); } /** - * Enable detected violations log a stacktrace and timing data - * to the {@link android.os.DropBoxManager DropBox} on policy - * violation. Intended mostly for platform integrators doing - * beta user field data collection. + * Enable detected violations log a stacktrace and timing data to the {@link + * android.os.DropBoxManager DropBox} on policy violation. Intended mostly for platform + * integrators doing beta user field data collection. */ public Builder penaltyDropBox() { return enable(PENALTY_DROPBOX); @@ -944,48 +870,51 @@ public final class StrictMode { /** * Construct the VmPolicy instance. * - * <p>Note: if no penalties are enabled before calling - * <code>build</code>, {@link #penaltyLog} is implicitly - * set. + * <p>Note: if no penalties are enabled before calling <code>build</code>, {@link + * #penaltyLog} is implicitly set. */ public VmPolicy build() { // If there are detection bits set but no violation bits // set, enable simple logging. - if (mMask != 0 && - (mMask & (PENALTY_DEATH | PENALTY_LOG | - PENALTY_DROPBOX | PENALTY_DIALOG)) == 0) { + if (mMask != 0 + && (mMask + & (PENALTY_DEATH + | PENALTY_LOG + | PENALTY_DROPBOX + | PENALTY_DIALOG)) + == 0) { penaltyLog(); } - return new VmPolicy(mMask, + return new VmPolicy( + mMask, mClassInstanceLimit != null ? mClassInstanceLimit : EMPTY_CLASS_LIMIT_MAP); } } } /** - * Log of strict mode violation stack traces that have occurred - * during a Binder call, to be serialized back later to the caller - * via Parcel.writeNoException() (amusingly) where the caller can - * choose how to react. + * Log of strict mode violation stack traces that have occurred during a Binder call, to be + * serialized back later to the caller via Parcel.writeNoException() (amusingly) where the + * caller can choose how to react. */ private static final ThreadLocal<ArrayList<ViolationInfo>> gatheredViolations = new ThreadLocal<ArrayList<ViolationInfo>>() { - @Override protected ArrayList<ViolationInfo> initialValue() { - // Starts null to avoid unnecessary allocations when - // checking whether there are any violations or not in - // hasGatheredViolations() below. - return null; - } - }; + @Override + protected ArrayList<ViolationInfo> initialValue() { + // Starts null to avoid unnecessary allocations when + // checking whether there are any violations or not in + // hasGatheredViolations() below. + return null; + } + }; /** - * Sets the policy for what actions on the current thread should - * be detected, as well as the penalty if such actions occur. + * Sets the policy for what actions on the current thread should be detected, as well as the + * penalty if such actions occur. * - * <p>Internally this sets a thread-local variable which is - * propagated across cross-process IPC calls, meaning you can - * catch violations when a system service or another process - * accesses the disk or network on your behalf. + * <p>Internally this sets a thread-local variable which is propagated across cross-process IPC + * calls, meaning you can catch violations when a system service or another process accesses the + * disk or network on your behalf. * * @param policy the policy to put into place */ @@ -1016,7 +945,7 @@ public final class StrictMode { if (policy instanceof AndroidBlockGuardPolicy) { androidPolicy = (AndroidBlockGuardPolicy) policy; } else { - androidPolicy = threadAndroidPolicy.get(); + androidPolicy = THREAD_ANDROID_POLICY.get(); BlockGuard.setThreadPolicy(androidPolicy); } androidPolicy.setPolicyMask(policyMask); @@ -1030,63 +959,49 @@ public final class StrictMode { CloseGuard.setEnabled(enabled); } - /** - * @hide - */ + /** @hide */ public static class StrictModeViolation extends BlockGuard.BlockGuardPolicyException { public StrictModeViolation(int policyState, int policyViolated, String message) { super(policyState, policyViolated, message); } } - /** - * @hide - */ + /** @hide */ public static class StrictModeNetworkViolation extends StrictModeViolation { public StrictModeNetworkViolation(int policyMask) { super(policyMask, DETECT_NETWORK, null); } } - /** - * @hide - */ + /** @hide */ private static class StrictModeDiskReadViolation extends StrictModeViolation { public StrictModeDiskReadViolation(int policyMask) { super(policyMask, DETECT_DISK_READ, null); } } - /** - * @hide - */ - private static class StrictModeDiskWriteViolation extends StrictModeViolation { + /** @hide */ + private static class StrictModeDiskWriteViolation extends StrictModeViolation { public StrictModeDiskWriteViolation(int policyMask) { super(policyMask, DETECT_DISK_WRITE, null); } } - /** - * @hide - */ + /** @hide */ private static class StrictModeCustomViolation extends StrictModeViolation { public StrictModeCustomViolation(int policyMask, String name) { super(policyMask, DETECT_CUSTOM, name); } } - /** - * @hide - */ + /** @hide */ private static class StrictModeResourceMismatchViolation extends StrictModeViolation { public StrictModeResourceMismatchViolation(int policyMask, Object tag) { super(policyMask, DETECT_RESOURCE_MISMATCH, tag != null ? tag.toString() : null); } } - /** - * @hide - */ + /** @hide */ private static class StrictModeUnbufferedIOViolation extends StrictModeViolation { public StrictModeUnbufferedIOViolation(int policyMask) { super(policyMask, DETECT_UNBUFFERED_IO, null); @@ -1097,16 +1012,13 @@ public final class StrictMode { * Returns the bitmask of the current thread's policy. * * @return the bitmask of all the DETECT_* and PENALTY_* bits currently enabled - * * @hide */ public static int getThreadPolicyMask() { return BlockGuard.getThreadPolicy().getPolicyMask(); } - /** - * Returns the current thread's policy. - */ + /** Returns the current thread's policy. */ public static ThreadPolicy getThreadPolicy() { // TODO: this was a last minute Gingerbread API change (to // introduce VmPolicy cleanly) but this isn't particularly @@ -1116,14 +1028,13 @@ public final class StrictMode { } /** - * A convenience wrapper that takes the current - * {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it - * to permit both disk reads & writes, and sets the new policy - * with {@link #setThreadPolicy}, returning the old policy so you - * can restore it at the end of a block. + * A convenience wrapper that takes the current {@link ThreadPolicy} from {@link + * #getThreadPolicy}, modifies it to permit both disk reads & writes, and sets the new + * policy with {@link #setThreadPolicy}, returning the old policy so you can restore it at the + * end of a block. * - * @return the old policy, to be passed to {@link #setThreadPolicy} to - * restore the policy at the end of a block + * @return the old policy, to be passed to {@link #setThreadPolicy} to restore the policy at the + * end of a block */ public static ThreadPolicy allowThreadDiskWrites() { int oldPolicyMask = getThreadPolicyMask(); @@ -1135,14 +1046,11 @@ public final class StrictMode { } /** - * A convenience wrapper that takes the current - * {@link ThreadPolicy} from {@link #getThreadPolicy}, modifies it - * to permit disk reads, and sets the new policy - * with {@link #setThreadPolicy}, returning the old policy so you - * can restore it at the end of a block. + * A convenience wrapper that takes the current {@link ThreadPolicy} from {@link + * #getThreadPolicy}, modifies it to permit disk reads, and sets the new policy with {@link + * #setThreadPolicy}, returning the old policy so you can restore it at the end of a block. * - * @return the old policy, to be passed to setThreadPolicy to - * restore the policy. + * @return the old policy, to be passed to setThreadPolicy to restore the policy. */ public static ThreadPolicy allowThreadDiskReads() { int oldPolicyMask = getThreadPolicyMask(); @@ -1182,8 +1090,8 @@ public final class StrictMode { * @hide */ public static boolean conditionallyEnableDebugLogging() { - boolean doFlashes = SystemProperties.getBoolean(VISUAL_PROPERTY, false) - && !amTheSystemServerProcess(); + boolean doFlashes = + SystemProperties.getBoolean(VISUAL_PROPERTY, false) && !amTheSystemServerProcess(); final boolean suppress = SystemProperties.getBoolean(DISABLE_PROPERTY, false); // For debug builds, log event loop stalls to dropbox for analysis. @@ -1201,9 +1109,10 @@ public final class StrictMode { } // Thread policy controls BlockGuard. - int threadPolicyMask = StrictMode.DETECT_DISK_WRITE | - StrictMode.DETECT_DISK_READ | - StrictMode.DETECT_NETWORK; + int threadPolicyMask = + StrictMode.DETECT_DISK_WRITE + | StrictMode.DETECT_DISK_READ + | StrictMode.DETECT_NETWORK; if (!Build.IS_USER) { threadPolicyMask |= StrictMode.PENALTY_DROPBOX; @@ -1243,8 +1152,7 @@ public final class StrictMode { } /** - * Used by the framework to make network usage on the main - * thread a fatal error. + * Used by the framework to make network usage on the main thread a fatal error. * * @hide */ @@ -1264,8 +1172,8 @@ public final class StrictMode { } /** - * Used by lame internal apps that haven't done the hard work to get - * themselves off file:// Uris yet. + * Used by lame internal apps that haven't done the hard work to get themselves off file:// Uris + * yet. * * @hide */ @@ -1274,17 +1182,14 @@ public final class StrictMode { } /** - * Parses the BlockGuard policy mask out from the Exception's - * getMessage() String value. Kinda gross, but least - * invasive. :/ + * Parses the BlockGuard policy mask out from the Exception's getMessage() String value. Kinda + * gross, but least invasive. :/ * - * Input is of the following forms: - * "policy=137 violation=64" - * "policy=137 violation=64 msg=Arbitrary text" + * <p>Input is of the following forms: "policy=137 violation=64" "policy=137 violation=64 + * msg=Arbitrary text" * - * Returns 0 on failure, which is a valid policy, but not a - * valid policy during a violation (else there must've been - * some policy in effect to violate). + * <p>Returns 0 on failure, which is a valid policy, but not a valid policy during a violation + * (else there must've been some policy in effect to violate). */ private static int parsePolicyFromMessage(String message) { if (message == null || !message.startsWith("policy=")) { @@ -1302,9 +1207,7 @@ public final class StrictMode { } } - /** - * Like parsePolicyFromMessage(), but returns the violation. - */ + /** Like parsePolicyFromMessage(), but returns the violation. */ private static int parseViolationFromMessage(String message) { if (message == null) { return 0; @@ -1328,25 +1231,28 @@ public final class StrictMode { private static final ThreadLocal<ArrayList<ViolationInfo>> violationsBeingTimed = new ThreadLocal<ArrayList<ViolationInfo>>() { - @Override protected ArrayList<ViolationInfo> initialValue() { - return new ArrayList<ViolationInfo>(); - } - }; + @Override + protected ArrayList<ViolationInfo> initialValue() { + return new ArrayList<ViolationInfo>(); + } + }; // Note: only access this once verifying the thread has a Looper. - private static final ThreadLocal<Handler> threadHandler = new ThreadLocal<Handler>() { - @Override protected Handler initialValue() { - return new Handler(); - } - }; + private static final ThreadLocal<Handler> THREAD_HANDLER = + new ThreadLocal<Handler>() { + @Override + protected Handler initialValue() { + return new Handler(); + } + }; - private static final ThreadLocal<AndroidBlockGuardPolicy> - threadAndroidPolicy = new ThreadLocal<AndroidBlockGuardPolicy>() { - @Override - protected AndroidBlockGuardPolicy initialValue() { - return new AndroidBlockGuardPolicy(0); - } - }; + private static final ThreadLocal<AndroidBlockGuardPolicy> THREAD_ANDROID_POLICY = + new ThreadLocal<AndroidBlockGuardPolicy>() { + @Override + protected AndroidBlockGuardPolicy initialValue() { + return new AndroidBlockGuardPolicy(0); + } + }; private static boolean tooManyViolationsThisLoop() { return violationsBeingTimed.get().size() >= MAX_OFFENSES_PER_LOOP; @@ -1395,7 +1301,8 @@ public final class StrictMode { if (tooManyViolationsThisLoop()) { return; } - BlockGuard.BlockGuardPolicyException e = new StrictModeCustomViolation(mPolicyMask, name); + BlockGuard.BlockGuardPolicyException e = + new StrictModeCustomViolation(mPolicyMask, name); e.fillInStackTrace(); startHandlingViolationException(e); } @@ -1496,9 +1403,8 @@ public final class StrictMode { // // TODO: if in gather mode, ignore Looper.myLooper() and always // go into this immediate mode? - if (looper == null || - (info.policy & THREAD_PENALTY_MASK) == PENALTY_DEATH) { - info.durationMillis = -1; // unknown (redundant, already set) + if (looper == null || (info.policy & THREAD_PENALTY_MASK) == PENALTY_DEATH) { + info.durationMillis = -1; // unknown (redundant, already set) handleViolation(info); return; } @@ -1516,8 +1422,8 @@ public final class StrictMode { return; } - final IWindowManager windowManager = (info.policy & PENALTY_FLASH) != 0 ? - sWindowManager.get() : null; + final IWindowManager windowManager = + (info.policy & PENALTY_FLASH) != 0 ? sWindowManager.get() : null; if (windowManager != null) { try { windowManager.showStrictModeViolation(true); @@ -1534,31 +1440,34 @@ public final class StrictMode { // throttled back to 60fps via SurfaceFlinger/View // invalidates, _not_ by posting frame updates every 16 // milliseconds. - threadHandler.get().postAtFrontOfQueue(new Runnable() { - public void run() { - long loopFinishTime = SystemClock.uptimeMillis(); - - // Note: we do this early, before handling the - // violation below, as handling the violation - // may include PENALTY_DEATH and we don't want - // to keep the red border on. - if (windowManager != null) { - try { - windowManager.showStrictModeViolation(false); - } catch (RemoteException unused) { - } - } - - for (int n = 0; n < records.size(); ++n) { - ViolationInfo v = records.get(n); - v.violationNumThisLoop = n + 1; - v.durationMillis = - (int) (loopFinishTime - v.violationUptimeMillis); - handleViolation(v); - } - records.clear(); - } - }); + THREAD_HANDLER + .get() + .postAtFrontOfQueue( + new Runnable() { + public void run() { + long loopFinishTime = SystemClock.uptimeMillis(); + + // Note: we do this early, before handling the + // violation below, as handling the violation + // may include PENALTY_DEATH and we don't want + // to keep the red border on. + if (windowManager != null) { + try { + windowManager.showStrictModeViolation(false); + } catch (RemoteException unused) { + } + } + + for (int n = 0; n < records.size(); ++n) { + ViolationInfo v = records.get(n); + v.violationNumThisLoop = n + 1; + v.durationMillis = + (int) (loopFinishTime - v.violationUptimeMillis); + handleViolation(v); + } + records.clear(); + } + }); } // Note: It's possible (even quite likely) that the @@ -1603,17 +1512,21 @@ public final class StrictMode { } long now = SystemClock.uptimeMillis(); mLastViolationTime.put(crashFingerprint, now); - long timeSinceLastViolationMillis = lastViolationTime == 0 ? - Long.MAX_VALUE : (now - lastViolationTime); + long timeSinceLastViolationMillis = + lastViolationTime == 0 ? Long.MAX_VALUE : (now - lastViolationTime); if ((info.policy & PENALTY_LOG) != 0 && sListener != null) { sListener.onViolation(info.crashInfo.stackTrace); } - if ((info.policy & PENALTY_LOG) != 0 && - timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) { + if ((info.policy & PENALTY_LOG) != 0 + && timeSinceLastViolationMillis > MIN_LOG_INTERVAL_MS) { if (info.durationMillis != -1) { - Log.d(TAG, "StrictMode policy violation; ~duration=" + - info.durationMillis + " ms: " + info.crashInfo.stackTrace); + Log.d( + TAG, + "StrictMode policy violation; ~duration=" + + info.durationMillis + + " ms: " + + info.crashInfo.stackTrace); } else { Log.d(TAG, "StrictMode policy violation: " + info.crashInfo.stackTrace); } @@ -1625,8 +1538,8 @@ public final class StrictMode { // by the ActivityManagerService remaining set. int violationMaskSubset = 0; - if ((info.policy & PENALTY_DIALOG) != 0 && - timeSinceLastViolationMillis > MIN_DIALOG_INTERVAL_MS) { + if ((info.policy & PENALTY_DIALOG) != 0 + && timeSinceLastViolationMillis > MIN_DIALOG_INTERVAL_MS) { violationMaskSubset |= PENALTY_DIALOG; } @@ -1659,10 +1572,9 @@ public final class StrictMode { // We restore the current policy below, in the finally block. setThreadPolicyMask(0); - ActivityManager.getService().handleApplicationStrictModeViolation( - RuntimeInit.getApplicationObject(), - violationMaskSubset, - info); + ActivityManager.getService() + .handleApplicationStrictModeViolation( + RuntimeInit.getApplicationObject(), violationMaskSubset, info); } catch (RemoteException e) { if (e instanceof DeadObjectException) { // System process is dead; ignore @@ -1687,12 +1599,10 @@ public final class StrictMode { } /** - * In the common case, as set by conditionallyEnableDebugLogging, - * we're just dropboxing any violations but not showing a dialog, - * not loggging, and not killing the process. In these cases we - * don't need to do a synchronous call to the ActivityManager. - * This is used by both per-thread and vm-wide violations when - * applicable. + * In the common case, as set by conditionallyEnableDebugLogging, we're just dropboxing any + * violations but not showing a dialog, not loggging, and not killing the process. In these + * cases we don't need to do a synchronous call to the ActivityManager. This is used by both + * per-thread and vm-wide violations when applicable. */ private static void dropboxViolationAsync( final int violationMaskSubset, final ViolationInfo info) { @@ -1715,9 +1625,7 @@ public final class StrictMode { Log.d(TAG, "No activity manager; failed to Dropbox violation."); } else { am.handleApplicationStrictModeViolation( - RuntimeInit.getApplicationObject(), - violationMaskSubset, - info); + RuntimeInit.getApplicationObject(), violationMaskSubset, info); } } catch (RemoteException e) { if (e instanceof DeadObjectException) { @@ -1738,25 +1646,20 @@ public final class StrictMode { } } - /** - * Called from Parcel.writeNoException() - */ + /** Called from Parcel.writeNoException() */ /* package */ static boolean hasGatheredViolations() { return gatheredViolations.get() != null; } /** - * Called from Parcel.writeException(), so we drop this memory and - * don't incorrectly attribute it to the wrong caller on the next - * Binder call on this thread. + * Called from Parcel.writeException(), so we drop this memory and don't incorrectly attribute + * it to the wrong caller on the next Binder call on this thread. */ /* package */ static void clearGatheredViolations() { gatheredViolations.set(null); } - /** - * @hide - */ + /** @hide */ public static void conditionallyCheckInstanceCounts() { VmPolicy policy = getVmPolicy(); int policySize = policy.classInstanceLimit.size(); @@ -1784,7 +1687,7 @@ public final class StrictMode { } private static long sLastInstanceCountCheckMillis = 0; - private static boolean sIsIdlerRegistered = false; // guarded by StrictMode.class + private static boolean sIsIdlerRegistered = false; // guarded by StrictMode.class private static final MessageQueue.IdleHandler sProcessIdleHandler = new MessageQueue.IdleHandler() { public boolean queueIdle() { @@ -1798,9 +1701,8 @@ public final class StrictMode { }; /** - * Sets the policy for what actions in the VM process (on any - * thread) should be detected, as well as the penalty if such - * actions occur. + * Sets the policy for what actions in the VM process (on any thread) should be detected, as + * well as the penalty if such actions occur. * * @param policy the policy to put into place */ @@ -1813,8 +1715,8 @@ public final class StrictMode { Looper looper = Looper.getMainLooper(); if (looper != null) { MessageQueue mq = looper.mQueue; - if (policy.classInstanceLimit.size() == 0 || - (sVmPolicyMask & VM_PENALTY_MASK) == 0) { + if (policy.classInstanceLimit.size() == 0 + || (sVmPolicyMask & VM_PENALTY_MASK) == 0) { mq.removeIdleHandler(sProcessIdleHandler); sIsIdlerRegistered = false; } else if (!sIsIdlerRegistered) { @@ -1833,8 +1735,9 @@ public final class StrictMode { } } - final INetworkManagementService netd = INetworkManagementService.Stub.asInterface( - ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)); + final INetworkManagementService netd = + INetworkManagementService.Stub.asInterface( + ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)); if (netd != null) { try { netd.setUidCleartextNetworkPolicy(android.os.Process.myUid(), networkPolicy); @@ -1846,9 +1749,7 @@ public final class StrictMode { } } - /** - * Gets the current VM policy. - */ + /** Gets the current VM policy. */ public static VmPolicy getVmPolicy() { synchronized (StrictMode.class) { return sVmPolicy; @@ -1858,102 +1759,72 @@ public final class StrictMode { /** * Enable the recommended StrictMode defaults, with violations just being logged. * - * <p>This catches disk and network access on the main thread, as - * well as leaked SQLite cursors and unclosed resources. This is - * simply a wrapper around {@link #setVmPolicy} and {@link + * <p>This catches disk and network access on the main thread, as well as leaked SQLite cursors + * and unclosed resources. This is simply a wrapper around {@link #setVmPolicy} and {@link * #setThreadPolicy}. */ public static void enableDefaults() { - StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() - .detectAll() - .penaltyLog() - .build()); - StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() - .detectAll() - .penaltyLog() - .build()); + StrictMode.setThreadPolicy( + new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build()); + StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build()); } - /** - * @hide - */ + /** @hide */ public static boolean vmSqliteObjectLeaksEnabled() { return (sVmPolicyMask & DETECT_VM_CURSOR_LEAKS) != 0; } - /** - * @hide - */ + /** @hide */ public static boolean vmClosableObjectLeaksEnabled() { return (sVmPolicyMask & DETECT_VM_CLOSABLE_LEAKS) != 0; } - /** - * @hide - */ + /** @hide */ public static boolean vmRegistrationLeaksEnabled() { return (sVmPolicyMask & DETECT_VM_REGISTRATION_LEAKS) != 0; } - /** - * @hide - */ + /** @hide */ public static boolean vmFileUriExposureEnabled() { return (sVmPolicyMask & DETECT_VM_FILE_URI_EXPOSURE) != 0; } - /** - * @hide - */ + /** @hide */ public static boolean vmCleartextNetworkEnabled() { return (sVmPolicyMask & DETECT_VM_CLEARTEXT_NETWORK) != 0; } - /** - * @hide - */ + /** @hide */ public static boolean vmContentUriWithoutPermissionEnabled() { return (sVmPolicyMask & DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION) != 0; } - /** - * @hide - */ + /** @hide */ public static boolean vmUntaggedSocketEnabled() { return (sVmPolicyMask & DETECT_VM_UNTAGGED_SOCKET) != 0; } - /** - * @hide - */ + /** @hide */ public static void onSqliteObjectLeaked(String message, Throwable originStack) { onVmPolicyViolation(message, originStack); } - /** - * @hide - */ + /** @hide */ public static void onWebViewMethodCalledOnWrongThread(Throwable originStack) { onVmPolicyViolation(null, originStack); } - /** - * @hide - */ + /** @hide */ public static void onIntentReceiverLeaked(Throwable originStack) { onVmPolicyViolation(null, originStack); } - /** - * @hide - */ + /** @hide */ public static void onServiceConnectionLeaked(Throwable originStack) { onVmPolicyViolation(null, originStack); } - /** - * @hide - */ + /** @hide */ public static void onFileUriExposed(Uri uri, String location) { final String message = uri + " exposed beyond app through " + location; if ((sVmPolicyMask & PENALTY_DEATH_ON_FILE_URI_EXPOSURE) != 0) { @@ -1963,19 +1834,18 @@ public final class StrictMode { } } - /** - * @hide - */ + /** @hide */ public static void onContentUriWithoutPermission(Uri uri, String location) { - final String message = uri + " exposed beyond app through " + location - + " without permission grant flags; did you forget" - + " FLAG_GRANT_READ_URI_PERMISSION?"; + final String message = + uri + + " exposed beyond app through " + + location + + " without permission grant flags; did you forget" + + " FLAG_GRANT_READ_URI_PERMISSION?"; onVmPolicyViolation(null, new Throwable(message)); } - /** - * @hide - */ + /** @hide */ public static void onCleartextNetworkDetected(byte[] firstPacket) { byte[] rawAddr = null; if (firstPacket != null) { @@ -1994,40 +1864,40 @@ public final class StrictMode { String msg = "Detected cleartext network traffic from UID " + uid; if (rawAddr != null) { try { - msg = "Detected cleartext network traffic from UID " + uid + " to " - + InetAddress.getByAddress(rawAddr); + msg = + "Detected cleartext network traffic from UID " + + uid + + " to " + + InetAddress.getByAddress(rawAddr); } catch (UnknownHostException ignored) { } } final boolean forceDeath = (sVmPolicyMask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0; - onVmPolicyViolation(HexDump.dumpHexString(firstPacket).trim(), new Throwable(msg), - forceDeath); + onVmPolicyViolation( + HexDump.dumpHexString(firstPacket).trim(), new Throwable(msg), forceDeath); } - /** - * @hide - */ + /** @hide */ public static void onUntaggedSocket() { - onVmPolicyViolation(null, new Throwable("Untagged socket detected; use" - + " TrafficStats.setThreadSocketTag() to track all network usage")); + onVmPolicyViolation( + null, + new Throwable( + "Untagged socket detected; use" + + " TrafficStats.setThreadSocketTag() to track all network usage")); } // Map from VM violation fingerprint to uptime millis. private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<Integer, Long>(); - /** - * @hide - */ + /** @hide */ public static void onVmPolicyViolation(String message, Throwable originStack) { onVmPolicyViolation(message, originStack, false); } - /** - * @hide - */ - public static void onVmPolicyViolation(String message, Throwable originStack, - boolean forceDeath) { + /** @hide */ + public static void onVmPolicyViolation( + String message, Throwable originStack, boolean forceDeath) { final boolean penaltyDropbox = (sVmPolicyMask & PENALTY_DROPBOX) != 0; final boolean penaltyDeath = ((sVmPolicyMask & PENALTY_DEATH) != 0) || forceDeath; final boolean penaltyLog = (sVmPolicyMask & PENALTY_LOG) != 0; @@ -2082,10 +1952,9 @@ public final class StrictMode { // We restore the current policy below, in the finally block. setThreadPolicyMask(0); - ActivityManager.getService().handleApplicationStrictModeViolation( - RuntimeInit.getApplicationObject(), - violationMaskSubset, - info); + ActivityManager.getService() + .handleApplicationStrictModeViolation( + RuntimeInit.getApplicationObject(), violationMaskSubset, info); } catch (RemoteException e) { if (e instanceof DeadObjectException) { // System process is dead; ignore @@ -2105,9 +1974,7 @@ public final class StrictMode { } } - /** - * Called from Parcel.writeNoException() - */ + /** Called from Parcel.writeNoException() */ /* package */ static void writeGatheredViolationsToParcel(Parcel p) { ArrayList<ViolationInfo> violations = gatheredViolations.get(); if (violations == null) { @@ -2128,8 +1995,8 @@ public final class StrictMode { private static class LogStackTrace extends Exception {} /** - * Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS, - * we here read back all the encoded violations. + * Called from Parcel.readException() when the exception is EX_STRICT_MODE_VIOLATIONS, we here + * read back all the encoded violations. */ /* package */ static void readAndHandleBinderCallViolations(Parcel p) { // Our own stack trace to append @@ -2155,22 +2022,20 @@ public final class StrictMode { } /** - * Called from android_util_Binder.cpp's - * android_os_Parcel_enforceInterface when an incoming Binder call - * requires changing the StrictMode policy mask. The role of this - * function is to ask Binder for its current (native) thread-local - * policy value and synchronize it to libcore's (Java) - * thread-local policy value. + * Called from android_util_Binder.cpp's android_os_Parcel_enforceInterface when an incoming + * Binder call requires changing the StrictMode policy mask. The role of this function is to ask + * Binder for its current (native) thread-local policy value and synchronize it to libcore's + * (Java) thread-local policy value. */ private static void onBinderStrictModePolicyChange(int newPolicy) { setBlockGuardPolicy(newPolicy); } /** - * A tracked, critical time span. (e.g. during an animation.) + * A tracked, critical time span. (e.g. during an animation.) * - * The object itself is a linked list node, to avoid any allocations - * during rapid span entries and exits. + * <p>The object itself is a linked list node, to avoid any allocations during rapid span + * entries and exits. * * @hide */ @@ -2178,7 +2043,7 @@ public final class StrictMode { private String mName; private long mCreateMillis; private Span mNext; - private Span mPrev; // not used when in freeList, only active + private Span mPrev; // not used when in freeList, only active private final ThreadSpanState mContainerState; Span(ThreadSpanState threadState) { @@ -2191,12 +2056,10 @@ public final class StrictMode { } /** - * To be called when the critical span is complete (i.e. the - * animation is done animating). This can be called on any - * thread (even a different one from where the animation was - * taking place), but that's only a defensive implementation - * measure. It really makes no sense for you to call this on - * thread other than that where you created it. + * To be called when the critical span is complete (i.e. the animation is done animating). + * This can be called on any thread (even a different one from where the animation was + * taking place), but that's only a defensive implementation measure. It really makes no + * sense for you to call this on thread other than that where you created it. * * @hide */ @@ -2240,53 +2103,52 @@ public final class StrictMode { } // The no-op span that's used in user builds. - private static final Span NO_OP_SPAN = new Span() { - public void finish() { - // Do nothing. - } - }; + private static final Span NO_OP_SPAN = + new Span() { + public void finish() { + // Do nothing. + } + }; /** * Linked lists of active spans and a freelist. * - * Locking notes: there's one of these structures per thread and - * all members of this structure (as well as the Span nodes under - * it) are guarded by the ThreadSpanState object instance. While - * in theory there'd be no locking required because it's all local - * per-thread, the finish() method above is defensive against - * people calling it on a different thread from where they created - * the Span, hence the locking. + * <p>Locking notes: there's one of these structures per thread and all members of this + * structure (as well as the Span nodes under it) are guarded by the ThreadSpanState object + * instance. While in theory there'd be no locking required because it's all local per-thread, + * the finish() method above is defensive against people calling it on a different thread from + * where they created the Span, hence the locking. */ private static class ThreadSpanState { - public Span mActiveHead; // doubly-linked list. + public Span mActiveHead; // doubly-linked list. public int mActiveSize; - public Span mFreeListHead; // singly-linked list. only changes at head. + public Span mFreeListHead; // singly-linked list. only changes at head. public int mFreeListSize; } private static final ThreadLocal<ThreadSpanState> sThisThreadSpanState = new ThreadLocal<ThreadSpanState>() { - @Override protected ThreadSpanState initialValue() { - return new ThreadSpanState(); - } - }; + @Override + protected ThreadSpanState initialValue() { + return new ThreadSpanState(); + } + }; - private static Singleton<IWindowManager> sWindowManager = new Singleton<IWindowManager>() { - protected IWindowManager create() { - return IWindowManager.Stub.asInterface(ServiceManager.getService("window")); - } - }; + private static Singleton<IWindowManager> sWindowManager = + new Singleton<IWindowManager>() { + protected IWindowManager create() { + return IWindowManager.Stub.asInterface(ServiceManager.getService("window")); + } + }; /** * Enter a named critical span (e.g. an animation) * - * <p>The name is an arbitary label (or tag) that will be applied - * to any strictmode violation that happens while this span is - * active. You must call finish() on the span when done. + * <p>The name is an arbitary label (or tag) that will be applied to any strictmode violation + * that happens while this span is active. You must call finish() on the span when done. * - * <p>This will never return null, but on devices without debugging - * enabled, this may return a dummy object on which the finish() - * method is a no-op. + * <p>This will never return null, but on devices without debugging enabled, this may return a + * dummy object on which the finish() method is a no-op. * * <p>TODO: add CloseGuard to this, verifying callers call finish. * @@ -2325,13 +2187,11 @@ public final class StrictMode { } /** - * For code to note that it's slow. This is a no-op unless the - * current thread's {@link android.os.StrictMode.ThreadPolicy} has - * {@link android.os.StrictMode.ThreadPolicy.Builder#detectCustomSlowCalls} - * enabled. + * For code to note that it's slow. This is a no-op unless the current thread's {@link + * android.os.StrictMode.ThreadPolicy} has {@link + * android.os.StrictMode.ThreadPolicy.Builder#detectCustomSlowCalls} enabled. * - * @param name a short string for the exception stack trace that's - * built if when this fires. + * @param name a short string for the exception stack trace that's built if when this fires. */ public static void noteSlowCall(String name) { BlockGuard.Policy policy = BlockGuard.getThreadPolicy(); @@ -2343,14 +2203,11 @@ public final class StrictMode { } /** - * For code to note that a resource was obtained using a type other than - * its defined type. This is a no-op unless the current thread's - * {@link android.os.StrictMode.ThreadPolicy} has - * {@link android.os.StrictMode.ThreadPolicy.Builder#detectResourceMismatches()} - * enabled. + * For code to note that a resource was obtained using a type other than its defined type. This + * is a no-op unless the current thread's {@link android.os.StrictMode.ThreadPolicy} has {@link + * android.os.StrictMode.ThreadPolicy.Builder#detectResourceMismatches()} enabled. * - * @param tag an object for the exception stack trace that's - * built if when this fires. + * @param tag an object for the exception stack trace that's built if when this fires. * @hide */ public static void noteResourceMismatch(Object tag) { @@ -2362,9 +2219,7 @@ public final class StrictMode { ((AndroidBlockGuardPolicy) policy).onResourceMismatch(tag); } - /** - * @hide - */ + /** @hide */ public static void noteUnbufferedIO() { BlockGuard.Policy policy = BlockGuard.getThreadPolicy(); if (!(policy instanceof AndroidBlockGuardPolicy)) { @@ -2374,9 +2229,7 @@ public final class StrictMode { ((AndroidBlockGuardPolicy) policy).onUnbufferedIO(); } - /** - * @hide - */ + /** @hide */ public static void noteDiskRead() { BlockGuard.Policy policy = BlockGuard.getThreadPolicy(); if (!(policy instanceof AndroidBlockGuardPolicy)) { @@ -2386,9 +2239,7 @@ public final class StrictMode { ((AndroidBlockGuardPolicy) policy).onReadFromDisk(); } - /** - * @hide - */ + /** @hide */ public static void noteDiskWrite() { BlockGuard.Policy policy = BlockGuard.getThreadPolicy(); if (!(policy instanceof AndroidBlockGuardPolicy)) { @@ -2403,17 +2254,16 @@ public final class StrictMode { new HashMap<Class, Integer>(); /** - * Returns an object that is used to track instances of activites. - * The activity should store a reference to the tracker object in one of its fields. + * Returns an object that is used to track instances of activites. The activity should store a + * reference to the tracker object in one of its fields. + * * @hide */ public static Object trackActivity(Object instance) { return new InstanceTracker(instance); } - /** - * @hide - */ + /** @hide */ public static void incrementExpectedActivityCount(Class klass) { if (klass == null) { return; @@ -2430,9 +2280,7 @@ public final class StrictMode { } } - /** - * @hide - */ + /** @hide */ public static void decrementExpectedActivityCount(Class klass) { if (klass == null) { return; @@ -2483,70 +2331,49 @@ public final class StrictMode { } /** - * Parcelable that gets sent in Binder call headers back to callers - * to report violations that happened during a cross-process call. + * Parcelable that gets sent in Binder call headers back to callers to report violations that + * happened during a cross-process call. * * @hide */ public static class ViolationInfo implements Parcelable { public final String message; - /** - * Stack and other stuff info. - */ + /** Stack and other stuff info. */ public final ApplicationErrorReport.CrashInfo crashInfo; - /** - * The strict mode policy mask at the time of violation. - */ + /** The strict mode policy mask at the time of violation. */ public final int policy; - /** - * The wall time duration of the violation, when known. -1 when - * not known. - */ + /** The wall time duration of the violation, when known. -1 when not known. */ public int durationMillis = -1; - /** - * The number of animations currently running. - */ + /** The number of animations currently running. */ public int numAnimationsRunning = 0; - /** - * List of tags from active Span instances during this - * violation, or null for none. - */ + /** List of tags from active Span instances during this violation, or null for none. */ public String[] tags; /** - * Which violation number this was (1-based) since the last Looper loop, - * from the perspective of the root caller (if it crossed any processes - * via Binder calls). The value is 0 if the root caller wasn't on a Looper - * thread. + * Which violation number this was (1-based) since the last Looper loop, from the + * perspective of the root caller (if it crossed any processes via Binder calls). The value + * is 0 if the root caller wasn't on a Looper thread. */ public int violationNumThisLoop; - /** - * The time (in terms of SystemClock.uptimeMillis()) that the - * violation occurred. - */ + /** The time (in terms of SystemClock.uptimeMillis()) that the violation occurred. */ public long violationUptimeMillis; /** - * The action of the Intent being broadcast to somebody's onReceive - * on this thread right now, or null. + * The action of the Intent being broadcast to somebody's onReceive on this thread right + * now, or null. */ public String broadcastIntentAction; - /** - * If this is a instance count violation, the number of instances in memory, - * else -1. - */ + /** If this is a instance count violation, the number of instances in memory, else -1. */ public long numInstances = -1; - /** - * Create an uninitialized instance of ViolationInfo - */ + /** Create an uninitialized instance of ViolationInfo */ public ViolationInfo() { message = null; crashInfo = null; @@ -2557,9 +2384,7 @@ public final class StrictMode { this(null, tr, policy); } - /** - * Create an instance of ViolationInfo initialized from an exception. - */ + /** Create an instance of ViolationInfo initialized from an exception. */ public ViolationInfo(String message, Throwable tr, int policy) { this.message = message; crashInfo = new ApplicationErrorReport.CrashInfo(tr); @@ -2612,9 +2437,7 @@ public final class StrictMode { return result; } - /** - * Create an instance of ViolationInfo initialized from a Parcel. - */ + /** Create an instance of ViolationInfo initialized from a Parcel. */ public ViolationInfo(Parcel in) { this(in, false); } @@ -2622,8 +2445,8 @@ public final class StrictMode { /** * Create an instance of ViolationInfo initialized from a Parcel. * - * @param unsetGatheringBit if true, the caller is the root caller - * and the gathering penalty should be removed. + * @param unsetGatheringBit if true, the caller is the root caller and the gathering penalty + * should be removed. */ public ViolationInfo(Parcel in, boolean unsetGatheringBit) { message = in.readString(); @@ -2647,9 +2470,7 @@ public final class StrictMode { tags = in.readStringArray(); } - /** - * Save a ViolationInfo instance to a parcel. - */ + /** Save a ViolationInfo instance to a parcel. */ @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(message); @@ -2668,23 +2489,29 @@ public final class StrictMode { dest.writeLong(numInstances); dest.writeString(broadcastIntentAction); dest.writeStringArray(tags); - int total = dest.dataPosition()-start; - if (Binder.CHECK_PARCEL_SIZE && total > 10*1024) { - Slog.d(TAG, "VIO: policy=" + policy + " dur=" + durationMillis - + " numLoop=" + violationNumThisLoop - + " anim=" + numAnimationsRunning - + " uptime=" + violationUptimeMillis - + " numInst=" + numInstances); + int total = dest.dataPosition() - start; + if (Binder.CHECK_PARCEL_SIZE && total > 10 * 1024) { + Slog.d( + TAG, + "VIO: policy=" + + policy + + " dur=" + + durationMillis + + " numLoop=" + + violationNumThisLoop + + " anim=" + + numAnimationsRunning + + " uptime=" + + violationUptimeMillis + + " numInst=" + + numInstances); Slog.d(TAG, "VIO: action=" + broadcastIntentAction); Slog.d(TAG, "VIO: tags=" + Arrays.toString(tags)); - Slog.d(TAG, "VIO: TOTAL BYTES WRITTEN: " + (dest.dataPosition()-start)); + Slog.d(TAG, "VIO: TOTAL BYTES WRITTEN: " + (dest.dataPosition() - start)); } } - - /** - * Dump a ViolationInfo instance to a Printer. - */ + /** Dump a ViolationInfo instance to a Printer. */ public void dump(Printer pw, String prefix) { if (crashInfo != null) { crashInfo.dump(pw, prefix); @@ -2743,8 +2570,8 @@ public final class StrictMode { final int mLimit; private static final StackTraceElement[] FAKE_STACK = { - new StackTraceElement("android.os.StrictMode", "setClassInstanceLimit", - "StrictMode.java", 1) + new StackTraceElement( + "android.os.StrictMode", "setClassInstanceLimit", "StrictMode.java", 1) }; public InstanceCountViolation(Class klass, long instances, int limit) { diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java index 8632194f2b02..560b4b31cdc6 100644 --- a/core/java/android/os/SystemProperties.java +++ b/core/java/android/os/SystemProperties.java @@ -16,6 +16,8 @@ package android.os; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.util.Log; import android.util.MutableInt; @@ -43,17 +45,12 @@ public class SystemProperties { public static final int PROP_VALUE_MAX = 91; + @GuardedBy("sChangeCallbacks") private static final ArrayList<Runnable> sChangeCallbacks = new ArrayList<Runnable>(); @GuardedBy("sRoReads") - private static final HashMap<String, MutableInt> sRoReads; - static { - if (TRACK_KEY_ACCESS) { - sRoReads = new HashMap<>(); - } else { - sRoReads = null; - } - } + private static final HashMap<String, MutableInt> sRoReads = + TRACK_KEY_ACCESS ? new HashMap<>() : null; private static void onKeyAccess(String key) { if (!TRACK_KEY_ACCESS) return; @@ -85,77 +82,102 @@ public class SystemProperties { private static native void native_report_sysprop_change(); /** - * Get the value for the given key. - * @return an empty string if the key isn't found + * Get the String value for the given {@code key}. + * + * <b>WARNING:</b> Do not use this method if the value may not be a valid UTF string! This + * method will crash in native code. + * + * @param key the key to lookup + * @return an empty string if the {@code key} isn't found */ - public static String get(String key) { + @NonNull + public static String get(@NonNull String key) { if (TRACK_KEY_ACCESS) onKeyAccess(key); return native_get(key); } /** - * Get the value for the given key. - * @return if the key isn't found, return def if it isn't null, or an empty string otherwise + * Get the String value for the given {@code key}. + * + * <b>WARNING:</b> Do not use this method if the value may not be a valid UTF string! This + * method will crash in native code. + * + * @param key the key to lookup + * @param def the default value in case the property is not set or empty + * @return if the {@code key} isn't found, return {@code def} if it isn't null, or an empty + * string otherwise */ - public static String get(String key, String def) { + @NonNull + public static String get(@NonNull String key, @Nullable String def) { if (TRACK_KEY_ACCESS) onKeyAccess(key); return native_get(key, def); } /** - * Get the value for the given key, and return as an integer. + * Get the value for the given {@code key}, and return as an integer. + * * @param key the key to lookup * @param def a default value to return * @return the key parsed as an integer, or def if the key isn't found or * cannot be parsed */ - public static int getInt(String key, int def) { + public static int getInt(@NonNull String key, int def) { if (TRACK_KEY_ACCESS) onKeyAccess(key); return native_get_int(key, def); } /** - * Get the value for the given key, and return as a long. + * Get the value for the given {@code key}, and return as a long. + * * @param key the key to lookup * @param def a default value to return * @return the key parsed as a long, or def if the key isn't found or * cannot be parsed */ - public static long getLong(String key, long def) { + public static long getLong(@NonNull String key, long def) { if (TRACK_KEY_ACCESS) onKeyAccess(key); return native_get_long(key, def); } /** - * Get the value for the given key, returned as a boolean. + * Get the value for the given {@code key}, returned as a boolean. * Values 'n', 'no', '0', 'false' or 'off' are considered false. * Values 'y', 'yes', '1', 'true' or 'on' are considered true. * (case sensitive). * If the key does not exist, or has any other value, then the default * result is returned. + * * @param key the key to lookup * @param def a default value to return * @return the key parsed as a boolean, or def if the key isn't found or is * not able to be parsed as a boolean. */ - public static boolean getBoolean(String key, boolean def) { + public static boolean getBoolean(@NonNull String key, boolean def) { if (TRACK_KEY_ACCESS) onKeyAccess(key); return native_get_boolean(key, def); } /** - * Set the value for the given key. - * @throws IllegalArgumentException if the value exceeds 92 characters + * Set the value for the given {@code key} to {@code val}. + * + * @throws IllegalArgumentException if the {@code val} exceeds 91 characters */ - public static void set(String key, String val) { + public static void set(@NonNull String key, @Nullable String val) { if (val != null && val.length() > PROP_VALUE_MAX) { - throw newValueTooLargeException(key, val); + throw new IllegalArgumentException("value of system property '" + key + + "' is longer than " + PROP_VALUE_MAX + " characters: " + val); } if (TRACK_KEY_ACCESS) onKeyAccess(key); native_set(key, val); } - public static void addChangeCallback(Runnable callback) { + /** + * Add a callback that will be run whenever any system property changes. + * + * @param callback The {@link Runnable} that should be executed when a system property + * changes. + */ + public static void addChangeCallback(@NonNull Runnable callback) { synchronized (sChangeCallbacks) { if (sChangeCallbacks.size() == 0) { native_add_change_callback(); @@ -164,7 +186,8 @@ public class SystemProperties { } } - static void callChangeCallbacks() { + @SuppressWarnings("unused") // Called from native code. + private static void callChangeCallbacks() { synchronized (sChangeCallbacks) { //Log.i("foo", "Calling " + sChangeCallbacks.size() + " change callbacks!"); if (sChangeCallbacks.size() == 0) { @@ -177,11 +200,6 @@ public class SystemProperties { } } - private static IllegalArgumentException newValueTooLargeException(String key, String value) { - return new IllegalArgumentException("value of system property '" + key + "' is longer than " - + PROP_VALUE_MAX + " characters: " + value); - } - /* * Notifies listeners that a system property has changed */ diff --git a/core/java/android/os/Temperature.java b/core/java/android/os/Temperature.java index 3e48493a7a81..8767731e748a 100644 --- a/core/java/android/os/Temperature.java +++ b/core/java/android/os/Temperature.java @@ -30,8 +30,8 @@ public class Temperature implements Parcelable { private int mType; public Temperature() { - mType = Integer.MIN_VALUE; - mValue = HardwarePropertiesManager.UNDEFINED_TEMPERATURE; + this(HardwarePropertiesManager.UNDEFINED_TEMPERATURE, + Integer.MIN_VALUE); } public Temperature(float value, int type) { diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 794b3baf1932..430a5e3e7281 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -322,6 +322,8 @@ public class UserManager { * Specifies if a user is disallowed from configuring Tethering * & portable hotspots. This can only be set by device owners and profile owners on the * primary user. The default value is <code>false</code>. + * <p>In Android 9.0 or higher, if tethering is enabled when this restriction is set, + * tethering will be automatically turned off. * * <p>Key for user restrictions. * <p>Type: Boolean @@ -495,8 +497,11 @@ public class UserManager { /** * Specifies if a user is disallowed from adjusting the master volume. If set, the master volume - * will be muted. This can be set by device owners and profile owners. The default value is - * <code>false</code>. + * will be muted. This can be set by device owners from API 21 and profile owners from API 24. + * The default value is <code>false</code>. + * + * <p>When the restriction is set by profile owners, then it only applies to relevant + * profiles. * * <p>This restriction has no effect on managed profiles. * <p>Key for user restrictions. diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java index fe9e8c67e566..da0ed54e003e 100644 --- a/core/java/android/os/VibrationEffect.java +++ b/core/java/android/os/VibrationEffect.java @@ -149,14 +149,43 @@ public abstract class VibrationEffect implements Parcelable { * provide a better experience than you could otherwise build using the generic building * blocks. * + * This will fallback to a generic pattern if one exists and there does not exist a + * hardware-specific implementation of the effect. + * * @param effectId The ID of the effect to perform: - * {@link #EFFECT_CLICK}, {@link #EFFECT_DOUBLE_CLICK}. + * {@link #EFFECT_CLICK}, {@link #EFFECT_DOUBLE_CLICK}, {@link #EFFECT_TICK} * * @return The desired effect. * @hide */ public static VibrationEffect get(int effectId) { - VibrationEffect effect = new Prebaked(effectId); + return get(effectId, true); + } + + /** + * Get a predefined vibration effect. + * + * Predefined effects are a set of common vibration effects that should be identical, regardless + * of the app they come from, in order to provide a cohesive experience for users across + * the entire device. They also may be custom tailored to the device hardware in order to + * provide a better experience than you could otherwise build using the generic building + * blocks. + * + * Some effects you may only want to play if there's a hardware specific implementation because + * they may, for example, be too disruptive to the user without tuning. The {@code fallback} + * parameter allows you to decide whether you want to fallback to the generic implementation or + * only play if there's a tuned, hardware specific one available. + * + * @param effectId The ID of the effect to perform: + * {@link #EFFECT_CLICK}, {@link #EFFECT_DOUBLE_CLICK}, {@link #EFFECT_TICK} + * @param fallback Whether to fallback to a generic pattern if a hardware specific + * implementation doesn't exist. + * + * @return The desired effect. + * @hide + */ + public static VibrationEffect get(int effectId, boolean fallback) { + VibrationEffect effect = new Prebaked(effectId, fallback); effect.validate(); return effect; } @@ -374,19 +403,29 @@ public abstract class VibrationEffect implements Parcelable { /** @hide */ public static class Prebaked extends VibrationEffect implements Parcelable { private int mEffectId; + private boolean mFallback; public Prebaked(Parcel in) { - this(in.readInt()); + this(in.readInt(), in.readByte() != 0); } - public Prebaked(int effectId) { + public Prebaked(int effectId, boolean fallback) { mEffectId = effectId; + mFallback = fallback; } public int getId() { return mEffectId; } + /** + * Whether the effect should fall back to a generic pattern if there's no hardware specific + * implementation of it. + */ + public boolean shouldFallback() { + return mFallback; + } + @Override public void validate() { switch (mEffectId) { @@ -406,7 +445,7 @@ public abstract class VibrationEffect implements Parcelable { return false; } VibrationEffect.Prebaked other = (VibrationEffect.Prebaked) o; - return mEffectId == other.mEffectId; + return mEffectId == other.mEffectId && mFallback == other.mFallback; } @Override @@ -416,7 +455,7 @@ public abstract class VibrationEffect implements Parcelable { @Override public String toString() { - return "Prebaked{mEffectId=" + mEffectId + "}"; + return "Prebaked{mEffectId=" + mEffectId + ", mFallback=" + mFallback + "}"; } @@ -424,6 +463,7 @@ public abstract class VibrationEffect implements Parcelable { public void writeToParcel(Parcel out, int flags) { out.writeInt(PARCEL_TOKEN_EFFECT); out.writeInt(mEffectId); + out.writeByte((byte) (mFallback ? 1 : 0)); } public static final Parcelable.Creator<Prebaked> CREATOR = diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 4725bd4e5f3d..27e399c1fcd6 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1750,6 +1750,10 @@ public final class Settings { return true; } + public int getCurrentGeneration() { + return mCurrentGeneration; + } + private int readCurrentGeneration() { try { return mArray.get(mIndex); @@ -1858,6 +1862,7 @@ public final class Settings { public String getStringForUser(ContentResolver cr, String name, final int userHandle) { final boolean isSelf = (userHandle == UserHandle.myUserId()); + int currentGeneration = -1; if (isSelf) { synchronized (NameValueCache.this) { if (mGenerationTracker != null) { @@ -1871,6 +1876,9 @@ public final class Settings { } else if (mValues.containsKey(name)) { return mValues.get(name); } + if (mGenerationTracker != null) { + currentGeneration = mGenerationTracker.getCurrentGeneration(); + } } } } else { @@ -1961,7 +1969,10 @@ public final class Settings { }); } } - mValues.put(name, value); + if (mGenerationTracker != null && currentGeneration == + mGenerationTracker.getCurrentGeneration()) { + mValues.put(name, value); + } } } else { if (LOCAL_LOGV) Log.i(TAG, "call-query of user " + userHandle @@ -2002,7 +2013,10 @@ public final class Settings { String value = c.moveToNext() ? c.getString(0) : null; synchronized (NameValueCache.this) { - mValues.put(name, value); + if(mGenerationTracker != null && + currentGeneration == mGenerationTracker.getCurrentGeneration()) { + mValues.put(name, value); + } } if (LOCAL_LOGV) { Log.v(TAG, "cache miss [" + mUri.getLastPathSegment() + "]: " + @@ -7212,8 +7226,6 @@ public final class Settings { CLONE_TO_MANAGED_PROFILE.add(LOCATION_PREVIOUS_MODE); CLONE_TO_MANAGED_PROFILE.add(LOCATION_PROVIDERS_ALLOWED); CLONE_TO_MANAGED_PROFILE.add(SELECTED_INPUT_METHOD_SUBTYPE); - CLONE_TO_MANAGED_PROFILE.add(SELECTED_SPELL_CHECKER); - CLONE_TO_MANAGED_PROFILE.add(SELECTED_SPELL_CHECKER_SUBTYPE); } /** @hide */ @@ -8003,6 +8015,8 @@ public final class Settings { public static final String NETSTATS_GLOBAL_ALERT_BYTES = "netstats_global_alert_bytes"; /** {@hide} */ public static final String NETSTATS_SAMPLE_ENABLED = "netstats_sample_enabled"; + /** {@hide} */ + public static final String NETSTATS_AUGMENT_ENABLED = "netstats_augment_enabled"; /** {@hide} */ public static final String NETSTATS_DEV_BUCKET_DURATION = "netstats_dev_bucket_duration"; @@ -9320,6 +9334,25 @@ public final class Settings { public static final String ANOMALY_DETECTION_CONSTANTS = "anomaly_detection_constants"; /** + * Always on display(AOD) specific settings + * This is encoded as a key=value list, separated by commas. Ex: + * + * "prox_screen_off_delay=10000,screen_brightness_array=0:1:2:3:4" + * + * The following keys are supported: + * + * <pre> + * screen_brightness_array (string) + * dimming_scrim_array (string) + * prox_screen_off_delay (long) + * prox_cooldown_trigger (long) + * prox_cooldown_period (long) + * </pre> + * @hide + */ + public static final String ALWAYS_ON_DISPLAY_CONSTANTS = "always_on_display_constants"; + + /** * App standby (app idle) specific settings. * This is encoded as a key=value list, separated by commas. Ex: * diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java index c068e6a21db6..1dcaef4476b7 100644 --- a/core/java/android/service/autofill/AutofillService.java +++ b/core/java/android/service/autofill/AutofillService.java @@ -18,16 +18,15 @@ package android.service.autofill; import android.annotation.CallSuper; import android.annotation.NonNull; import android.annotation.Nullable; -import android.os.RemoteException; -import android.provider.Settings; - -import com.android.internal.os.HandlerCaller; import android.annotation.SdkConstant; -import android.app.Service;import android.content.Intent; +import android.app.Service; +import android.content.Intent; import android.os.CancellationSignal; import android.os.IBinder; import android.os.ICancellationSignal; import android.os.Looper; +import android.os.RemoteException; +import android.provider.Settings; import android.util.Log; import android.view.View; import android.view.ViewStructure; @@ -35,6 +34,7 @@ import android.view.autofill.AutofillId; import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; +import com.android.internal.os.HandlerCaller; import com.android.internal.os.SomeArgs; /** @@ -280,6 +280,77 @@ import com.android.internal.os.SomeArgs; * calling {@link FillResponse.Builder#setIgnoredIds(AutofillId...)} so the system does not trigger * a new {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} when these views are * focused. + * + * <h3>Web security</h3> + * + * <p>When handling autofill requests that represent web pages (typically + * view structures whose root's {@link android.app.assist.AssistStructure.ViewNode#getClassName()} + * is a {@link android.webkit.WebView}), the service should take the following steps to verify if + * the structure can be autofilled with the data associated with the app requesting it: + * + * <ol> + * <li>Use the {@link android.app.assist.AssistStructure.ViewNode#getWebDomain()} to get the + * source of the document. + * <li>Get the canonical domain using the + * <a href="https://publicsuffix.org/>Public Suffix List</a> (see example below). + * <li>Use <a href="https://developers.google.com/digital-asset-links/">Digital Asset Links</a> + * to obtain the package name and certificate fingerprint of the package corresponding to + * the canonical domain. + * <li>Make sure the certificate fingerprint matches the value returned by Package Manager + * (see "Package verification" section above). + * </ol> + * + * <p>Here's an example on how to get the canonical domain using + * <a href="https://github.com/google/guava">Guava</a>: + * + * <pre class="prettyprint"> + * private static String getCanonicalDomain(String domain) { + * InternetDomainName idn = InternetDomainName.from(domain); + * while (idn != null && !idn.isTopPrivateDomain()) { + * idn = idn.parent(); + * } + * return idn == null ? null : idn.toString(); + * } + * </pre> + * + * <p>If the association between the web domain and app package cannot be verified through the steps + * above, but the service thinks that it is appropriate to fill persisted credentials that are + * stored for the web domain, the service should warn the user about the potential data + * leakage first, and ask for the user to confirm. For example, the service could: + * + * <ol> + * <li>Create a dataset that requires + * {@link Dataset.Builder#setAuthentication(android.content.IntentSender) authentication} to + * unlock. + * <li>Include the web domain in the custom presentation for the + * {@link Dataset.Builder#setValue(AutofillId, AutofillValue, android.widget.RemoteViews) + * dataset value}. + * <li>When the user selects that dataset, show a disclaimer dialog explaining that the app is + * requesting credentials for a web domain, but the service could not verify if the app owns + * that domain. If the user agrees, then the service can unlock the dataset. + * <li>Similarly, when adding a {@link SaveInfo} object for the request, the service should + * include the above disclaimer in the {@link SaveInfo.Builder#setDescription(CharSequence)}. + * </ol> + * + * <p>This same procedure could also be used when the autofillable data is contained inside an + * {@code IFRAME}, in which case the WebView generates a new autofill context when a node inside + * the {@code IFRAME} is focused, with the root node containing the {@code IFRAME}'s {@code src} + * attribute on {@link android.app.assist.AssistStructure.ViewNode#getWebDomain()}. A typical and + * legitimate use case for this scenario is a financial app that allows the user + * to login on different bank accounts. For example, a financial app {@code my_financial_app} could + * use a WebView that loads contents from {@code banklogin.my_financial_app.com}, which contains an + * {@code IFRAME} node whose {@code src} attribute is {@code login.some_bank.com}. When fulfilling + * that request, the service could add an + * {@link Dataset.Builder#setAuthentication(android.content.IntentSender) authenticated dataset} + * whose presentation displays "Username for some_bank.com" and + * "Password for some_bank.com". Then when the user taps one of these options, the service + * shows the disclaimer dialog explaining that selecting that option would release the + * {@code login.some_bank.com} credentials to the {@code my_financial_app}; if the user agrees, + * then the service returns an unlocked dataset with the {@code some_bank.com} credentials. + * + * <p><b>Note:</b> The autofill service could also whitelist well-known browser apps and skip the + * verifications above, as long as the service can verify the authenticity of the browser app by + * checking its signing certificate. */ public abstract class AutofillService extends Service { private static final String TAG = "AutofillService"; @@ -424,7 +495,7 @@ public abstract class AutofillService extends Service { * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)}) * to notify the result of the request. * - * <p><b>NOTE: </b>to retrieve the actual value of the field, the service should call + * <p><b>Note:</b> To retrieve the actual value of the field, the service should call * {@link android.app.assist.AssistStructure.ViewNode#getAutofillValue()}; if it calls * {@link android.app.assist.AssistStructure.ViewNode#getText()} or other methods, there is no * guarantee such method will return the most recent value of the field. diff --git a/core/java/android/service/autofill/CustomDescription.java b/core/java/android/service/autofill/CustomDescription.java index 3da0b5e84499..9a4cbc415d64 100644 --- a/core/java/android/service/autofill/CustomDescription.java +++ b/core/java/android/service/autofill/CustomDescription.java @@ -19,14 +19,18 @@ package android.service.autofill; import static android.view.autofill.Helper.sDebug; import android.annotation.NonNull; +import android.app.Activity; +import android.app.PendingIntent; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; -import android.util.SparseArray; +import android.util.Pair; import android.widget.RemoteViews; import com.android.internal.util.Preconditions; +import java.util.ArrayList; + /** * Defines a custom description for the Save UI affordance. * @@ -65,14 +69,17 @@ import com.android.internal.util.Preconditions; * new ImageTransformation.Builder(ccNumberId) * .addOption(Pattern.compile(""^4815.*$"), R.drawable.ic_credit_card_logo1) * .addOption(Pattern.compile(""^1623.*$"), R.drawable.ic_credit_card_logo2) - * .addOption(Pattern.compile(""^42.*$"), R.drawable.ic_credit_card_logo3); + * .addOption(Pattern.compile(""^42.*$"), R.drawable.ic_credit_card_logo3) + * .build(); * // Masked credit card number (as .....LAST_4_DIGITS) - * builder.addChild(R.id.templateCcNumber, new CharSequenceTransformation.Builder() - * .addField(ccNumberId, Pattern.compile(""^.*(\\d\\d\\d\\d)$"), "...$1") + * builder.addChild(R.id.templateCcNumber, new CharSequenceTransformation + * .Builder(ccNumberId, Pattern.compile(""^.*(\\d\\d\\d\\d)$"), "...$1") + * .build(); * // Expiration date as MM / YYYY: - * builder.addChild(R.id.templateExpDate, new CharSequenceTransformation.Builder() - * .addField(ccExpMonthId, Pattern.compile(""^(\\d\\d)$"), "Exp: $1") - * .addField(ccExpYearId, Pattern.compile(""^(\\d\\d)$"), "/$1"); + * builder.addChild(R.id.templateExpDate, new CharSequenceTransformation + * .Builder(ccExpMonthId, Pattern.compile(""^(\\d\\d)$"), "Exp: $1") + * .addField(ccExpYearId, Pattern.compile(""^(\\d\\d)$"), "/$1") + * .build(); * </pre> * * <p>See {@link ImageTransformation}, {@link CharSequenceTransformation} for more info about these @@ -83,7 +90,7 @@ public final class CustomDescription implements Parcelable { private static final String TAG = "CustomDescription"; private final RemoteViews mPresentation; - private final SparseArray<InternalTransformation> mTransformations; + private final ArrayList<Pair<Integer, InternalTransformation>> mTransformations; private CustomDescription(Builder builder) { mPresentation = builder.mPresentation; @@ -96,8 +103,9 @@ public final class CustomDescription implements Parcelable { final int size = mTransformations.size(); if (sDebug) Log.d(TAG, "getPresentation(): applying " + size + " transformations"); for (int i = 0; i < size; i++) { - final int id = mTransformations.keyAt(i); - final InternalTransformation transformation = mTransformations.valueAt(i); + final Pair<Integer, InternalTransformation> pair = mTransformations.get(i); + final int id = pair.first; + final InternalTransformation transformation = pair.second; if (sDebug) Log.d(TAG, "#" + i + ": " + transformation); try { @@ -119,11 +127,23 @@ public final class CustomDescription implements Parcelable { public static class Builder { private final RemoteViews mPresentation; - private SparseArray<InternalTransformation> mTransformations; + private ArrayList<Pair<Integer, InternalTransformation>> mTransformations; /** * Default constructor. * + * <p><b>Note:</b> If any child view of presentation triggers a + * {@link RemoteViews#setOnClickPendingIntent(int, android.app.PendingIntent) pending intent + * on click}, such {@link PendingIntent} must follow the restrictions below, otherwise + * it might not be triggered or the Save affordance might not be shown when its activity + * is finished: + * <ul> + * <li>It cannot be created with the {@link PendingIntent#FLAG_IMMUTABLE} flag. + * <li>It must be a PendingIntent for an {@link Activity}. + * <li>The activity must call {@link Activity#finish()} when done. + * <li>The activity should not launch other activities. + * </ul> + * * @param parentPresentation template presentation with (optional) children views. */ public Builder(RemoteViews parentPresentation) { @@ -134,6 +154,9 @@ public final class CustomDescription implements Parcelable { * Adds a transformation to replace the value of a child view with the fields in the * screen. * + * <p>When multiple transformations are added for the same child view, they will be applied + * in the same order as added. + * * @param id view id of the children view. * @param transformation an implementation provided by the Android System. * @return this builder. @@ -144,9 +167,9 @@ public final class CustomDescription implements Parcelable { Preconditions.checkArgument((transformation instanceof InternalTransformation), "not provided by Android System: " + transformation); if (mTransformations == null) { - mTransformations = new SparseArray<>(); + mTransformations = new ArrayList<>(); } - mTransformations.put(id, (InternalTransformation) transformation); + mTransformations.add(new Pair<>(id, (InternalTransformation) transformation)); return this; } @@ -189,8 +212,9 @@ public final class CustomDescription implements Parcelable { final int[] ids = new int[size]; final InternalTransformation[] values = new InternalTransformation[size]; for (int i = 0; i < size; i++) { - ids[i] = mTransformations.keyAt(i); - values[i] = mTransformations.valueAt(i); + final Pair<Integer, InternalTransformation> pair = mTransformations.get(i); + ids[i] = pair.first; + values[i] = pair.second; } dest.writeIntArray(ids); dest.writeParcelableArray(values, flags); diff --git a/core/java/android/service/autofill/FillEventHistory.java b/core/java/android/service/autofill/FillEventHistory.java index f7dc1c58ade1..60c1c9a7e87a 100644 --- a/core/java/android/service/autofill/FillEventHistory.java +++ b/core/java/android/service/autofill/FillEventHistory.java @@ -81,10 +81,13 @@ public final class FillEventHistory implements Parcelable { /** * Returns the client state set in the previous {@link FillResponse}. * - * <p><b>NOTE: </b>the state is associated with the app that was autofilled in the previous + * <p><b>Note: </b>the state is associated with the app that was autofilled in the previous * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)} * , which is not necessary the same app being autofilled now. + * + * @deprecated use {@link #getEvents()} then {@link Event#getClientState()} instead. */ + @Deprecated @Nullable public Bundle getClientState() { return mClientState; } @@ -126,7 +129,6 @@ public final class FillEventHistory implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeBundle(mClientState); - if (mEvents == null) { dest.writeInt(0); } else { @@ -137,6 +139,7 @@ public final class FillEventHistory implements Parcelable { Event event = mEvents.get(i); dest.writeInt(event.getType()); dest.writeString(event.getDatasetId()); + dest.writeBundle(event.getClientState()); } } } @@ -177,6 +180,7 @@ public final class FillEventHistory implements Parcelable { @EventIds private final int mEventType; @Nullable private final String mDatasetId; + @Nullable private final Bundle mClientState; /** * Returns the type of the event. @@ -197,18 +201,32 @@ public final class FillEventHistory implements Parcelable { } /** + * Returns the client state from the {@link FillResponse} used to generate this event. + * + * <p><b>Note: </b>the state is associated with the app that was autofilled in the previous + * {@link + * AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}, + * which is not necessary the same app being autofilled now. + */ + @Nullable public Bundle getClientState() { + return mClientState; + } + + /** * Creates a new event. * * @param eventType The type of the event * @param datasetId The dataset the event was on, or {@code null} if the event was on the * whole response. + * @param clientState The client state associated with the event. * * @hide */ - public Event(int eventType, String datasetId) { + public Event(int eventType, @Nullable String datasetId, @Nullable Bundle clientState) { mEventType = Preconditions.checkArgumentInRange(eventType, 0, TYPE_SAVE_SHOWN, "eventType"); mDatasetId = datasetId; + mClientState = clientState; } } @@ -220,7 +238,8 @@ public final class FillEventHistory implements Parcelable { int numEvents = parcel.readInt(); for (int i = 0; i < numEvents; i++) { - selection.addEvent(new Event(parcel.readInt(), parcel.readString())); + selection.addEvent(new Event(parcel.readInt(), parcel.readString(), + parcel.readBundle())); } return selection; diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java index b6a9a2648470..3b09c678ba8e 100644 --- a/core/java/android/service/autofill/FillResponse.java +++ b/core/java/android/service/autofill/FillResponse.java @@ -302,7 +302,7 @@ public final class FillResponse implements Parcelable { // TODO: create a dump() method instead return new StringBuilder( "FillResponse : [mRequestId=" + mRequestId) - .append(", datasets=").append(mDatasets) + .append(", datasets=").append(mDatasets == null ? "N/A" : mDatasets.getList()) .append(", saveInfo=").append(mSaveInfo) .append(", clientState=").append(mClientState != null) .append(", hasPresentation=").append(mPresentation != null) diff --git a/core/java/android/service/gatekeeper/GateKeeperResponse.java b/core/java/android/service/gatekeeper/GateKeeperResponse.java index 287dc76a9b01..9b529345851b 100644 --- a/core/java/android/service/gatekeeper/GateKeeperResponse.java +++ b/core/java/android/service/gatekeeper/GateKeeperResponse.java @@ -106,6 +106,8 @@ public final class GateKeeperResponse implements Parcelable { if (mPayload != null) { dest.writeInt(mPayload.length); dest.writeByteArray(mPayload); + } else { + dest.writeInt(0); } } } diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java index fbc6fc6c3cd6..8f79bcffa776 100644 --- a/core/java/android/service/voice/VoiceInteractionService.java +++ b/core/java/android/service/voice/VoiceInteractionService.java @@ -262,8 +262,7 @@ public class VoiceInteractionService extends Service { * @param keyphrase The keyphrase that's being used, for example "Hello Android". * @param locale The locale for which the enrollment needs to be performed. * @param callback The callback to notify of detection events. - * @return An always-on hotword detector for the given keyphrase and locale. Is null if the - * keyphrase and locale is not supported. + * @return An always-on hotword detector for the given keyphrase and locale. */ public final AlwaysOnHotwordDetector createAlwaysOnHotwordDetector( String keyphrase, Locale locale, AlwaysOnHotwordDetector.Callback callback) { @@ -273,10 +272,8 @@ public class VoiceInteractionService extends Service { synchronized (mLock) { // Allow only one concurrent recognition via the APIs. safelyShutdownHotwordDetector(); - if (isKeyphraseAndLocaleSupportedForHotword(keyphrase, locale)) { - mHotwordDetector = new AlwaysOnHotwordDetector(keyphrase, locale, callback, - mKeyphraseEnrollmentInfo, mInterface, mSystemService); - } + mHotwordDetector = new AlwaysOnHotwordDetector(keyphrase, locale, callback, + mKeyphraseEnrollmentInfo, mInterface, mSystemService); } return mHotwordDetector; } diff --git a/core/java/android/service/vr/IVrManager.aidl b/core/java/android/service/vr/IVrManager.aidl index 9b37a654ab98..c38fab1f9e2c 100644 --- a/core/java/android/service/vr/IVrManager.aidl +++ b/core/java/android/service/vr/IVrManager.aidl @@ -59,6 +59,13 @@ interface IVrManager { boolean getVrModeState(); /** + * Returns the current Persistent VR mode state. + * + * @return {@code true} if Persistent VR mode is enabled. + */ + boolean getPersistentVrModeEnabled(); + + /** * Sets the persistent VR mode state of a device. When a device is in persistent VR mode it will * remain in VR mode even if the foreground does not specify VR mode being enabled. Mainly used * by VR viewers to indicate that a device is placed in a VR viewer. diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index f548d3b77bf3..1c6275fb8dc1 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -195,7 +195,8 @@ public abstract class WallpaperService extends Service { // Needed for throttling onComputeColors. private long mLastColorInvalidation; private final Runnable mNotifyColorsChanged = this::notifyColorsChanged; - private Supplier<Long> mClockFunction = SystemClock::elapsedRealtime; + private final Supplier<Long> mClockFunction; + private final Handler mHandler; DisplayManager mDisplayManager; Display mDisplay; @@ -362,6 +363,26 @@ public abstract class WallpaperService extends Service { } } }; + + /** + * Default constructor + */ + public Engine() { + this(SystemClock::elapsedRealtime, Handler.getMain()); + } + + /** + * Constructor used for test purposes. + * + * @param clockFunction Supplies current times in millis. + * @param handler Used for posting/deferring asynchronous calls. + * @hide + */ + @VisibleForTesting + public Engine(Supplier<Long> clockFunction, Handler handler) { + mClockFunction = clockFunction; + mHandler = handler; + } /** * Provides access to the surface in which this wallpaper is drawn. @@ -563,18 +584,17 @@ public abstract class WallpaperService extends Service { */ public void notifyColorsChanged() { final long now = mClockFunction.get(); - final Handler mainHandler = Handler.getMain(); if (now - mLastColorInvalidation < NOTIFY_COLORS_RATE_LIMIT_MS) { Log.w(TAG, "This call has been deferred. You should only call " + "notifyColorsChanged() once every " + (NOTIFY_COLORS_RATE_LIMIT_MS / 1000f) + " seconds."); - if (!mainHandler.hasCallbacks(mNotifyColorsChanged)) { - mainHandler.postDelayed(mNotifyColorsChanged, NOTIFY_COLORS_RATE_LIMIT_MS); + if (!mHandler.hasCallbacks(mNotifyColorsChanged)) { + mHandler.postDelayed(mNotifyColorsChanged, NOTIFY_COLORS_RATE_LIMIT_MS); } return; } mLastColorInvalidation = now; - mainHandler.removeCallbacks(mNotifyColorsChanged); + mHandler.removeCallbacks(mNotifyColorsChanged); try { final WallpaperColors newColors = onComputeColors(); @@ -662,14 +682,6 @@ public abstract class WallpaperService extends Service { } } - /** - * @hide - */ - @VisibleForTesting - public void setClockFunction(Supplier<Long> clockFunction) { - mClockFunction = clockFunction; - } - void updateSurface(boolean forceRelayout, boolean forceReport, boolean redrawNeeded) { if (mDestroyed) { Log.w(TAG, "Ignoring updateSurface: destroyed"); diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java index d6a68fb54b7c..5e40935cf6d2 100644 --- a/core/java/android/text/DynamicLayout.java +++ b/core/java/android/text/DynamicLayout.java @@ -16,12 +16,17 @@ package android.text; +import android.annotation.FloatRange; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.graphics.Paint; import android.graphics.Rect; import android.text.style.ReplacementSpan; import android.text.style.UpdateLayout; import android.text.style.WrapTogetherSpan; import android.util.ArraySet; +import android.util.Pools.SynchronizedPool; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; @@ -43,129 +48,418 @@ public class DynamicLayout extends Layout private static final int BLOCK_MINIMUM_CHARACTER_LENGTH = 400; /** - * Make a layout for the specified text that will be updated as - * the text is changed. + * Builder for dynamic layouts. The builder is the preferred pattern for constructing + * DynamicLayout objects and should be preferred over the constructors, particularly to access + * newer features. To build a dynamic layout, first call {@link #obtain} with the required + * arguments (base, paint, and width), then call setters for optional parameters, and finally + * {@link #build} to build the DynamicLayout object. Parameters not explicitly set will get + * default values. */ - public DynamicLayout(CharSequence base, - TextPaint paint, - int width, Alignment align, - float spacingmult, float spacingadd, + public static final class Builder { + private Builder() { + } + + /** + * Obtain a builder for constructing DynamicLayout objects. + */ + @NonNull + public static Builder obtain(@NonNull CharSequence base, @NonNull TextPaint paint, + @IntRange(from = 0) int width) { + Builder b = sPool.acquire(); + if (b == null) { + b = new Builder(); + } + + // set default initial values + b.mBase = base; + b.mDisplay = base; + b.mPaint = paint; + b.mWidth = width; + b.mAlignment = Alignment.ALIGN_NORMAL; + b.mTextDir = TextDirectionHeuristics.FIRSTSTRONG_LTR; + b.mSpacingMult = DEFAULT_LINESPACING_MULTIPLIER; + b.mSpacingAdd = DEFAULT_LINESPACING_ADDITION; + b.mIncludePad = true; + b.mFallbackLineSpacing = false; + b.mEllipsizedWidth = width; + b.mEllipsize = null; + b.mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE; + b.mHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE; + b.mJustificationMode = Layout.JUSTIFICATION_MODE_NONE; + return b; + } + + /** + * This method should be called after the layout is finished getting constructed and the + * builder needs to be cleaned up and returned to the pool. + */ + private static void recycle(@NonNull Builder b) { + b.mBase = null; + b.mDisplay = null; + b.mPaint = null; + sPool.release(b); + } + + /** + * Set the transformed text (password transformation being the primary example of a + * transformation) that will be updated as the base text is changed. The default is the + * 'base' text passed to the builder's constructor. + * + * @param display the transformed text + * @return this builder, useful for chaining + */ + @NonNull + public Builder setDisplayText(@NonNull CharSequence display) { + mDisplay = display; + return this; + } + + /** + * Set the alignment. The default is {@link Layout.Alignment#ALIGN_NORMAL}. + * + * @param alignment Alignment for the resulting {@link DynamicLayout} + * @return this builder, useful for chaining + */ + @NonNull + public Builder setAlignment(@NonNull Alignment alignment) { + mAlignment = alignment; + return this; + } + + /** + * Set the text direction heuristic. The text direction heuristic is used to resolve text + * direction per-paragraph based on the input text. The default is + * {@link TextDirectionHeuristics#FIRSTSTRONG_LTR}. + * + * @param textDir text direction heuristic for resolving bidi behavior. + * @return this builder, useful for chaining + */ + @NonNull + public Builder setTextDirection(@NonNull TextDirectionHeuristic textDir) { + mTextDir = textDir; + return this; + } + + /** + * Set line spacing parameters. Each line will have its line spacing multiplied by + * {@code spacingMult} and then increased by {@code spacingAdd}. The default is 0.0 for + * {@code spacingAdd} and 1.0 for {@code spacingMult}. + * + * @param spacingAdd the amount of line spacing addition + * @param spacingMult the line spacing multiplier + * @return this builder, useful for chaining + * @see android.widget.TextView#setLineSpacing + */ + @NonNull + public Builder setLineSpacing(float spacingAdd, @FloatRange(from = 0.0) float spacingMult) { + mSpacingAdd = spacingAdd; + mSpacingMult = spacingMult; + return this; + } + + /** + * Set whether to include extra space beyond font ascent and descent (which is needed to + * avoid clipping in some languages, such as Arabic and Kannada). The default is + * {@code true}. + * + * @param includePad whether to include padding + * @return this builder, useful for chaining + * @see android.widget.TextView#setIncludeFontPadding + */ + @NonNull + public Builder setIncludePad(boolean includePad) { + mIncludePad = includePad; + return this; + } + + /** + * Set whether to respect the ascent and descent of the fallback fonts that are used in + * displaying the text (which is needed to avoid text from consecutive lines running into + * each other). If set, fallback fonts that end up getting used can increase the ascent + * and descent of the lines that they are used on. + * + * <p>For backward compatibility reasons, the default is {@code false}, but setting this to + * true is strongly recommended. It is required to be true if text could be in languages + * like Burmese or Tibetan where text is typically much taller or deeper than Latin text. + * + * @param useLineSpacingFromFallbacks whether to expand linespacing based on fallback fonts + * @return this builder, useful for chaining + */ + @NonNull + public Builder setUseLineSpacingFromFallbacks(boolean useLineSpacingFromFallbacks) { + mFallbackLineSpacing = useLineSpacingFromFallbacks; + return this; + } + + /** + * Set the width as used for ellipsizing purposes, if it differs from the normal layout + * width. The default is the {@code width} passed to {@link #obtain}. + * + * @param ellipsizedWidth width used for ellipsizing, in pixels + * @return this builder, useful for chaining + * @see android.widget.TextView#setEllipsize + */ + @NonNull + public Builder setEllipsizedWidth(@IntRange(from = 0) int ellipsizedWidth) { + mEllipsizedWidth = ellipsizedWidth; + return this; + } + + /** + * Set ellipsizing on the layout. Causes words that are longer than the view is wide, or + * exceeding the number of lines (see #setMaxLines) in the case of + * {@link android.text.TextUtils.TruncateAt#END} or + * {@link android.text.TextUtils.TruncateAt#MARQUEE}, to be ellipsized instead of broken. + * The default is {@code null}, indicating no ellipsis is to be applied. + * + * @param ellipsize type of ellipsis behavior + * @return this builder, useful for chaining + * @see android.widget.TextView#setEllipsize + */ + public Builder setEllipsize(@Nullable TextUtils.TruncateAt ellipsize) { + mEllipsize = ellipsize; + return this; + } + + /** + * Set break strategy, useful for selecting high quality or balanced paragraph layout + * options. The default is {@link Layout#BREAK_STRATEGY_SIMPLE}. + * + * @param breakStrategy break strategy for paragraph layout + * @return this builder, useful for chaining + * @see android.widget.TextView#setBreakStrategy + */ + @NonNull + public Builder setBreakStrategy(@BreakStrategy int breakStrategy) { + mBreakStrategy = breakStrategy; + return this; + } + + /** + * Set hyphenation frequency, to control the amount of automatic hyphenation used. The + * possible values are defined in {@link Layout}, by constants named with the pattern + * {@code HYPHENATION_FREQUENCY_*}. The default is + * {@link Layout#HYPHENATION_FREQUENCY_NONE}. + * + * @param hyphenationFrequency hyphenation frequency for the paragraph + * @return this builder, useful for chaining + * @see android.widget.TextView#setHyphenationFrequency + */ + @NonNull + public Builder setHyphenationFrequency(@HyphenationFrequency int hyphenationFrequency) { + mHyphenationFrequency = hyphenationFrequency; + return this; + } + + /** + * Set paragraph justification mode. The default value is + * {@link Layout#JUSTIFICATION_MODE_NONE}. If the last line is too short for justification, + * the last line will be displayed with the alignment set by {@link #setAlignment}. + * + * @param justificationMode justification mode for the paragraph. + * @return this builder, useful for chaining. + */ + @NonNull + public Builder setJustificationMode(@JustificationMode int justificationMode) { + mJustificationMode = justificationMode; + return this; + } + + /** + * Build the {@link DynamicLayout} after options have been set. + * + * <p>Note: the builder object must not be reused in any way after calling this method. + * Setting parameters after calling this method, or calling it a second time on the same + * builder object, will likely lead to unexpected results. + * + * @return the newly constructed {@link DynamicLayout} object + */ + @NonNull + public DynamicLayout build() { + final DynamicLayout result = new DynamicLayout(this); + Builder.recycle(this); + return result; + } + + private CharSequence mBase; + private CharSequence mDisplay; + private TextPaint mPaint; + private int mWidth; + private Alignment mAlignment; + private TextDirectionHeuristic mTextDir; + private float mSpacingMult; + private float mSpacingAdd; + private boolean mIncludePad; + private boolean mFallbackLineSpacing; + private int mBreakStrategy; + private int mHyphenationFrequency; + private int mJustificationMode; + private TextUtils.TruncateAt mEllipsize; + private int mEllipsizedWidth; + + private final Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt(); + + private static final SynchronizedPool<Builder> sPool = new SynchronizedPool<Builder>(3); + } + + /** + * Make a layout for the specified text that will be updated as the text is changed. + */ + public DynamicLayout(@NonNull CharSequence base, + @NonNull TextPaint paint, + @IntRange(from = 0) int width, @NonNull Alignment align, + @FloatRange(from = 0.0) float spacingmult, float spacingadd, boolean includepad) { this(base, base, paint, width, align, spacingmult, spacingadd, includepad); } /** - * Make a layout for the transformed text (password transformation - * being the primary example of a transformation) - * that will be updated as the base text is changed. + * Make a layout for the transformed text (password transformation being the primary example of + * a transformation) that will be updated as the base text is changed. */ - public DynamicLayout(CharSequence base, CharSequence display, - TextPaint paint, - int width, Alignment align, - float spacingmult, float spacingadd, + public DynamicLayout(@NonNull CharSequence base, @NonNull CharSequence display, + @NonNull TextPaint paint, + @IntRange(from = 0) int width, @NonNull Alignment align, + @FloatRange(from = 0.0) float spacingmult, float spacingadd, boolean includepad) { this(base, display, paint, width, align, spacingmult, spacingadd, includepad, null, 0); } /** - * Make a layout for the transformed text (password transformation - * being the primary example of a transformation) - * that will be updated as the base text is changed. - * If ellipsize is non-null, the Layout will ellipsize the text - * down to ellipsizedWidth. + * Make a layout for the transformed text (password transformation being the primary example of + * a transformation) that will be updated as the base text is changed. If ellipsize is non-null, + * the Layout will ellipsize the text down to ellipsizedWidth. */ - public DynamicLayout(CharSequence base, CharSequence display, - TextPaint paint, - int width, Alignment align, - float spacingmult, float spacingadd, + public DynamicLayout(@NonNull CharSequence base, @NonNull CharSequence display, + @NonNull TextPaint paint, + @IntRange(from = 0) int width, @NonNull Alignment align, + @FloatRange(from = 0.0) float spacingmult, float spacingadd, boolean includepad, - TextUtils.TruncateAt ellipsize, int ellipsizedWidth) { + @Nullable TextUtils.TruncateAt ellipsize, + @IntRange(from = 0) int ellipsizedWidth) { this(base, display, paint, width, align, TextDirectionHeuristics.FIRSTSTRONG_LTR, spacingmult, spacingadd, includepad, - StaticLayout.BREAK_STRATEGY_SIMPLE, StaticLayout.HYPHENATION_FREQUENCY_NONE, + Layout.BREAK_STRATEGY_SIMPLE, Layout.HYPHENATION_FREQUENCY_NONE, Layout.JUSTIFICATION_MODE_NONE, ellipsize, ellipsizedWidth); } /** - * Make a layout for the transformed text (password transformation - * being the primary example of a transformation) - * that will be updated as the base text is changed. - * If ellipsize is non-null, the Layout will ellipsize the text - * down to ellipsizedWidth. - * * - * *@hide + * Make a layout for the transformed text (password transformation being the primary example of + * a transformation) that will be updated as the base text is changed. If ellipsize is non-null, + * the Layout will ellipsize the text down to ellipsizedWidth. + * + * @hide */ - public DynamicLayout(CharSequence base, CharSequence display, - TextPaint paint, - int width, Alignment align, TextDirectionHeuristic textDir, - float spacingmult, float spacingadd, - boolean includepad, int breakStrategy, int hyphenationFrequency, - int justificationMode, TextUtils.TruncateAt ellipsize, - int ellipsizedWidth) { - super((ellipsize == null) - ? display - : (display instanceof Spanned) - ? new SpannedEllipsizer(display) - : new Ellipsizer(display), + public DynamicLayout(@NonNull CharSequence base, @NonNull CharSequence display, + @NonNull TextPaint paint, + @IntRange(from = 0) int width, + @NonNull Alignment align, @NonNull TextDirectionHeuristic textDir, + @FloatRange(from = 0.0) float spacingmult, float spacingadd, + boolean includepad, @BreakStrategy int breakStrategy, + @HyphenationFrequency int hyphenationFrequency, + @JustificationMode int justificationMode, + @Nullable TextUtils.TruncateAt ellipsize, + @IntRange(from = 0) int ellipsizedWidth) { + super(createEllipsizer(ellipsize, display), paint, width, align, textDir, spacingmult, spacingadd); - mBase = base; + final Builder b = Builder.obtain(base, paint, width) + .setAlignment(align) + .setTextDirection(textDir) + .setLineSpacing(spacingadd, spacingmult) + .setEllipsizedWidth(ellipsizedWidth) + .setEllipsize(ellipsize); mDisplay = display; - - if (ellipsize != null) { - mInts = new PackedIntVector(COLUMNS_ELLIPSIZE); - mEllipsizedWidth = ellipsizedWidth; - mEllipsizeAt = ellipsize; - } else { - mInts = new PackedIntVector(COLUMNS_NORMAL); - mEllipsizedWidth = width; - mEllipsizeAt = null; - } - - mObjects = new PackedObjectVector<Directions>(1); - mIncludePad = includepad; mBreakStrategy = breakStrategy; mJustificationMode = justificationMode; mHyphenationFrequency = hyphenationFrequency; - /* - * This is annoying, but we can't refer to the layout until - * superclass construction is finished, and the superclass - * constructor wants the reference to the display text. - * - * This will break if the superclass constructor ever actually - * cares about the content instead of just holding the reference. - */ - if (ellipsize != null) { - Ellipsizer e = (Ellipsizer) getText(); + generate(b); + + Builder.recycle(b); + } + + private DynamicLayout(@NonNull Builder b) { + super(createEllipsizer(b.mEllipsize, b.mDisplay), + b.mPaint, b.mWidth, b.mAlignment, b.mSpacingMult, b.mSpacingAdd); + + mDisplay = b.mDisplay; + mIncludePad = b.mIncludePad; + mBreakStrategy = b.mBreakStrategy; + mJustificationMode = b.mJustificationMode; + mHyphenationFrequency = b.mHyphenationFrequency; + + generate(b); + } + @NonNull + private static CharSequence createEllipsizer(@Nullable TextUtils.TruncateAt ellipsize, + @NonNull CharSequence display) { + if (ellipsize == null) { + return display; + } else if (display instanceof Spanned) { + return new SpannedEllipsizer(display); + } else { + return new Ellipsizer(display); + } + } + + private void generate(@NonNull Builder b) { + mBase = b.mBase; + mFallbackLineSpacing = b.mFallbackLineSpacing; + if (b.mEllipsize != null) { + mInts = new PackedIntVector(COLUMNS_ELLIPSIZE); + mEllipsizedWidth = b.mEllipsizedWidth; + mEllipsizeAt = b.mEllipsize; + + /* + * This is annoying, but we can't refer to the layout until superclass construction is + * finished, and the superclass constructor wants the reference to the display text. + * + * In other words, the two Ellipsizer classes in Layout.java need a + * (Dynamic|Static)Layout as a parameter to do their calculations, but the Ellipsizers + * also need to be the input to the superclass's constructor (Layout). In order to go + * around the circular dependency, we construct the Ellipsizer with only one of the + * parameters, the text (in createEllipsizer). And we fill in the rest of the needed + * information (layout, width, and method) later, here. + * + * This will break if the superclass constructor ever actually cares about the content + * instead of just holding the reference. + */ + final Ellipsizer e = (Ellipsizer) getText(); e.mLayout = this; - e.mWidth = ellipsizedWidth; - e.mMethod = ellipsize; + e.mWidth = b.mEllipsizedWidth; + e.mMethod = b.mEllipsize; mEllipsize = true; + } else { + mInts = new PackedIntVector(COLUMNS_NORMAL); + mEllipsizedWidth = b.mWidth; + mEllipsizeAt = null; } - // Initial state is a single line with 0 characters (0 to 0), - // with top at 0 and bottom at whatever is natural, and - // undefined ellipsis. + mObjects = new PackedObjectVector<Directions>(1); + + // Initial state is a single line with 0 characters (0 to 0), with top at 0 and bottom at + // whatever is natural, and undefined ellipsis. int[] start; - if (ellipsize != null) { + if (b.mEllipsize != null) { start = new int[COLUMNS_ELLIPSIZE]; start[ELLIPSIS_START] = ELLIPSIS_UNDEFINED; } else { start = new int[COLUMNS_NORMAL]; } - Directions[] dirs = new Directions[] { DIRS_ALL_LEFT_TO_RIGHT }; + final Directions[] dirs = new Directions[] { DIRS_ALL_LEFT_TO_RIGHT }; - Paint.FontMetricsInt fm = paint.getFontMetricsInt(); - int asc = fm.ascent; - int desc = fm.descent; + final Paint.FontMetricsInt fm = b.mFontMetricsInt; + b.mPaint.getFontMetricsInt(fm); + final int asc = fm.ascent; + final int desc = fm.descent; start[DIR] = DIR_LEFT_TO_RIGHT << DIR_SHIFT; start[TOP] = 0; @@ -177,20 +471,22 @@ public class DynamicLayout extends Layout mObjects.insertAt(0, dirs); + final int baseLength = mBase.length(); // Update from 0 characters to whatever the real text is - reflow(base, 0, 0, base.length()); + reflow(mBase, 0, 0, baseLength); - if (base instanceof Spannable) { + if (mBase instanceof Spannable) { if (mWatcher == null) mWatcher = new ChangeWatcher(this); // Strip out any watchers for other DynamicLayouts. - Spannable sp = (Spannable) base; - ChangeWatcher[] spans = sp.getSpans(0, sp.length(), ChangeWatcher.class); - for (int i = 0; i < spans.length; i++) + final Spannable sp = (Spannable) mBase; + final ChangeWatcher[] spans = sp.getSpans(0, baseLength, ChangeWatcher.class); + for (int i = 0; i < spans.length; i++) { sp.removeSpan(spans[i]); + } - sp.setSpan(mWatcher, 0, base.length(), + sp.setSpan(mWatcher, 0, baseLength, Spannable.SPAN_INCLUSIVE_INCLUSIVE | (PRIORITY << Spannable.SPAN_PRIORITY_SHIFT)); } @@ -299,6 +595,7 @@ public class DynamicLayout extends Layout .setWidth(getWidth()) .setTextDirection(getTextDirectionHeuristic()) .setLineSpacing(getSpacingAdd(), getSpacingMultiplier()) + .setUseLineSpacingFromFallbacks(mFallbackLineSpacing) .setEllipsizedWidth(mEllipsizedWidth) .setEllipsize(mEllipsizeAt) .setBreakStrategy(mBreakStrategy) @@ -759,10 +1056,11 @@ public class DynamicLayout extends Layout private void reflow(CharSequence s, int where, int before, int after) { DynamicLayout ml = mLayout.get(); - if (ml != null) + if (ml != null) { ml.reflow(s, where, before, after); - else if (s instanceof Spannable) + } else if (s instanceof Spannable) { ((Spannable) s).removeSpan(this); + } } public void beforeTextChanged(CharSequence s, int where, int before, int after) { @@ -819,6 +1117,7 @@ public class DynamicLayout extends Layout private CharSequence mDisplay; private ChangeWatcher mWatcher; private boolean mIncludePad; + private boolean mFallbackLineSpacing; private boolean mEllipsize; private int mEllipsizedWidth; private TextUtils.TruncateAt mEllipsizeAt; diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java index 5d9c8d88fd1b..62bd6e04bbe0 100644 --- a/core/java/android/text/Layout.java +++ b/core/java/android/text/Layout.java @@ -119,6 +119,16 @@ public abstract class Layout { */ public static final int JUSTIFICATION_MODE_INTER_WORD = 1; + /* + * Line spacing multiplier for default line spacing. + */ + public static final float DEFAULT_LINESPACING_MULTIPLIER = 1.0f; + + /* + * Line spacing addition for default line spacing. + */ + public static final float DEFAULT_LINESPACING_ADDITION = 0.0f; + /** * Return how wide a layout must be in order to display the specified text with one line per * paragraph. @@ -1232,7 +1242,7 @@ public abstract class Layout { final TextPaint paint = mWorkPaint; paint.set(mPaint); paint.setHyphenEdit(getHyphen(line)); - tl.set(mPaint, mText, start, end, dir, directions, hasTabs, tabStops); + tl.set(paint, mText, start, end, dir, directions, hasTabs, tabStops); if (isJustificationRequired(line)) { tl.justify(getJustifyWidth(line)); } @@ -1260,7 +1270,7 @@ public abstract class Layout { final TextPaint paint = mWorkPaint; paint.set(mPaint); paint.setHyphenEdit(getHyphen(line)); - tl.set(mPaint, mText, start, end, dir, directions, hasTabs, tabStops); + tl.set(paint, mText, start, end, dir, directions, hasTabs, tabStops); if (isJustificationRequired(line)) { tl.justify(getJustifyWidth(line)); } diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index 6a7db4ed4e27..c124c7fd6a0c 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -16,6 +16,9 @@ package android.text; +import android.annotation.FloatRange; +import android.annotation.IntRange; +import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.Paint; import android.os.LocaleList; @@ -49,12 +52,11 @@ public class StaticLayout extends Layout { static final String TAG = "StaticLayout"; /** - * Builder for static layouts. The builder is a newer pattern for constructing - * StaticLayout objects and should be preferred over the constructors, - * particularly to access newer features. To build a static layout, first - * call {@link #obtain} with the required arguments (text, paint, and width), - * then call setters for optional parameters, and finally {@link #build} - * to build the StaticLayout object. Parameters not explicitly set will get + * Builder for static layouts. The builder is the preferred pattern for constructing + * StaticLayout objects and should be preferred over the constructors, particularly to access + * newer features. To build a static layout, first call {@link #obtain} with the required + * arguments (text, paint, and width), then call setters for optional parameters, and finally + * {@link #build} to build the StaticLayout object. Parameters not explicitly set will get * default values. */ public final static class Builder { @@ -63,7 +65,7 @@ public class StaticLayout extends Layout { } /** - * Obtain a builder for constructing StaticLayout objects + * Obtain a builder for constructing StaticLayout objects. * * @param source The text to be laid out, optionally with spans * @param start The index of the start of the text @@ -72,8 +74,10 @@ public class StaticLayout extends Layout { * @param width The width in pixels * @return a builder object used for constructing the StaticLayout */ - public static Builder obtain(CharSequence source, int start, int end, TextPaint paint, - int width) { + @NonNull + public static Builder obtain(@NonNull CharSequence source, @IntRange(from = 0) int start, + @IntRange(from = 0) int end, @NonNull TextPaint paint, + @IntRange(from = 0) int width) { Builder b = sPool.acquire(); if (b == null) { b = new Builder(); @@ -87,9 +91,10 @@ public class StaticLayout extends Layout { b.mWidth = width; b.mAlignment = Alignment.ALIGN_NORMAL; b.mTextDir = TextDirectionHeuristics.FIRSTSTRONG_LTR; - b.mSpacingMult = 1.0f; - b.mSpacingAdd = 0.0f; + b.mSpacingMult = DEFAULT_LINESPACING_MULTIPLIER; + b.mSpacingAdd = DEFAULT_LINESPACING_ADDITION; b.mIncludePad = true; + b.mFallbackLineSpacing = false; b.mEllipsizedWidth = width; b.mEllipsize = null; b.mMaxLines = Integer.MAX_VALUE; @@ -101,7 +106,11 @@ public class StaticLayout extends Layout { return b; } - private static void recycle(Builder b) { + /** + * This method should be called after the layout is finished getting constructed and the + * builder needs to be cleaned up and returned to the pool. + */ + private static void recycle(@NonNull Builder b) { b.mPaint = null; b.mText = null; MeasuredText.recycle(b.mMeasuredText); @@ -138,7 +147,8 @@ public class StaticLayout extends Layout { * * @hide */ - public Builder setText(CharSequence source, int start, int end) { + @NonNull + public Builder setText(@NonNull CharSequence source, int start, int end) { mText = source; mStart = start; mEnd = end; @@ -153,7 +163,8 @@ public class StaticLayout extends Layout { * * @hide */ - public Builder setPaint(TextPaint paint) { + @NonNull + public Builder setPaint(@NonNull TextPaint paint) { mPaint = paint; return this; } @@ -166,7 +177,8 @@ public class StaticLayout extends Layout { * * @hide */ - public Builder setWidth(int width) { + @NonNull + public Builder setWidth(@IntRange(from = 0) int width) { mWidth = width; if (mEllipsize == null) { mEllipsizedWidth = width; @@ -180,34 +192,38 @@ public class StaticLayout extends Layout { * @param alignment Alignment for the resulting {@link StaticLayout} * @return this builder, useful for chaining */ - public Builder setAlignment(Alignment alignment) { + @NonNull + public Builder setAlignment(@NonNull Alignment alignment) { mAlignment = alignment; return this; } /** * Set the text direction heuristic. The text direction heuristic is used to - * resolve text direction based per-paragraph based on the input text. The default is + * resolve text direction per-paragraph based on the input text. The default is * {@link TextDirectionHeuristics#FIRSTSTRONG_LTR}. * - * @param textDir text direction heuristic for resolving BiDi behavior. + * @param textDir text direction heuristic for resolving bidi behavior. * @return this builder, useful for chaining */ - public Builder setTextDirection(TextDirectionHeuristic textDir) { + @NonNull + public Builder setTextDirection(@NonNull TextDirectionHeuristic textDir) { mTextDir = textDir; return this; } /** - * Set line spacing parameters. The default is 0.0 for {@code spacingAdd} - * and 1.0 for {@code spacingMult}. + * Set line spacing parameters. Each line will have its line spacing multiplied by + * {@code spacingMult} and then increased by {@code spacingAdd}. The default is 0.0 for + * {@code spacingAdd} and 1.0 for {@code spacingMult}. * - * @param spacingAdd line spacing add - * @param spacingMult line spacing multiplier + * @param spacingAdd the amount of line spacing addition + * @param spacingMult the line spacing multiplier * @return this builder, useful for chaining * @see android.widget.TextView#setLineSpacing */ - public Builder setLineSpacing(float spacingAdd, float spacingMult) { + @NonNull + public Builder setLineSpacing(float spacingAdd, @FloatRange(from = 0.0) float spacingMult) { mSpacingAdd = spacingAdd; mSpacingMult = spacingMult; return this; @@ -222,12 +238,32 @@ public class StaticLayout extends Layout { * @return this builder, useful for chaining * @see android.widget.TextView#setIncludeFontPadding */ + @NonNull public Builder setIncludePad(boolean includePad) { mIncludePad = includePad; return this; } /** + * Set whether to respect the ascent and descent of the fallback fonts that are used in + * displaying the text (which is needed to avoid text from consecutive lines running into + * each other). If set, fallback fonts that end up getting used can increase the ascent + * and descent of the lines that they are used on. + * + * <p>For backward compatibility reasons, the default is {@code false}, but setting this to + * true is strongly recommended. It is required to be true if text could be in languages + * like Burmese or Tibetan where text is typically much taller or deeper than Latin text. + * + * @param useLineSpacingFromFallbacks whether to expand linespacing based on fallback fonts + * @return this builder, useful for chaining + */ + @NonNull + public Builder setUseLineSpacingFromFallbacks(boolean useLineSpacingFromFallbacks) { + mFallbackLineSpacing = useLineSpacingFromFallbacks; + return this; + } + + /** * Set the width as used for ellipsizing purposes, if it differs from the * normal layout width. The default is the {@code width} * passed to {@link #obtain}. @@ -236,7 +272,8 @@ public class StaticLayout extends Layout { * @return this builder, useful for chaining * @see android.widget.TextView#setEllipsize */ - public Builder setEllipsizedWidth(int ellipsizedWidth) { + @NonNull + public Builder setEllipsizedWidth(@IntRange(from = 0) int ellipsizedWidth) { mEllipsizedWidth = ellipsizedWidth; return this; } @@ -246,13 +283,13 @@ public class StaticLayout extends Layout { * is wide, or exceeding the number of lines (see #setMaxLines) in the case * of {@link android.text.TextUtils.TruncateAt#END} or * {@link android.text.TextUtils.TruncateAt#MARQUEE}, to be ellipsized instead - * of broken. The default is - * {@code null}, indicating no ellipsis is to be applied. + * of broken. The default is {@code null}, indicating no ellipsis is to be applied. * * @param ellipsize type of ellipsis behavior * @return this builder, useful for chaining * @see android.widget.TextView#setEllipsize */ + @NonNull public Builder setEllipsize(@Nullable TextUtils.TruncateAt ellipsize) { mEllipsize = ellipsize; return this; @@ -267,7 +304,8 @@ public class StaticLayout extends Layout { * @return this builder, useful for chaining * @see android.widget.TextView#setMaxLines */ - public Builder setMaxLines(int maxLines) { + @NonNull + public Builder setMaxLines(@IntRange(from = 0) int maxLines) { mMaxLines = maxLines; return this; } @@ -280,6 +318,7 @@ public class StaticLayout extends Layout { * @return this builder, useful for chaining * @see android.widget.TextView#setBreakStrategy */ + @NonNull public Builder setBreakStrategy(@BreakStrategy int breakStrategy) { mBreakStrategy = breakStrategy; return this; @@ -287,12 +326,15 @@ public class StaticLayout extends Layout { /** * Set hyphenation frequency, to control the amount of automatic hyphenation used. The - * default is {@link Layout#HYPHENATION_FREQUENCY_NONE}. + * possible values are defined in {@link Layout}, by constants named with the pattern + * {@code HYPHENATION_FREQUENCY_*}. The default is + * {@link Layout#HYPHENATION_FREQUENCY_NONE}. * * @param hyphenationFrequency hyphenation frequency for the paragraph * @return this builder, useful for chaining * @see android.widget.TextView#setHyphenationFrequency */ + @NonNull public Builder setHyphenationFrequency(@HyphenationFrequency int hyphenationFrequency) { mHyphenationFrequency = hyphenationFrequency; return this; @@ -306,18 +348,10 @@ public class StaticLayout extends Layout { * @param rightIndents array of indent values for right margin, in pixels * @return this builder, useful for chaining */ - public Builder setIndents(int[] leftIndents, int[] rightIndents) { + @NonNull + public Builder setIndents(@Nullable int[] leftIndents, @Nullable int[] rightIndents) { mLeftIndents = leftIndents; mRightIndents = rightIndents; - int leftLen = leftIndents == null ? 0 : leftIndents.length; - int rightLen = rightIndents == null ? 0 : rightIndents.length; - int[] indents = new int[Math.max(leftLen, rightLen)]; - for (int i = 0; i < indents.length; i++) { - int leftMargin = i < leftLen ? leftIndents[i] : 0; - int rightMargin = i < rightLen ? rightIndents[i] : 0; - indents[i] = leftMargin + rightMargin; - } - nSetIndents(mNativePtr, indents); return this; } @@ -329,6 +363,7 @@ public class StaticLayout extends Layout { * @param justificationMode justification mode for the paragraph. * @return this builder, useful for chaining. */ + @NonNull public Builder setJustificationMode(@JustificationMode int justificationMode) { mJustificationMode = justificationMode; return this; @@ -340,12 +375,14 @@ public class StaticLayout extends Layout { * * @hide */ + @NonNull /* package */ Builder setAddLastLineLineSpacing(boolean value) { mAddLastLineLineSpacing = value; return this; } - private long[] getHyphenators(LocaleList locales) { + @NonNull + private long[] getHyphenators(@NonNull LocaleList locales) { final int length = locales.size(); final long[] result = new long[length]; for (int i = 0; i < length; i++) { @@ -405,6 +442,7 @@ public class StaticLayout extends Layout { * * @return the newly constructed {@link StaticLayout} object */ + @NonNull public StaticLayout build() { StaticLayout result = new StaticLayout(this); Builder.recycle(this); @@ -422,32 +460,33 @@ public class StaticLayout extends Layout { /* package */ long mNativePtr; - CharSequence mText; - int mStart; - int mEnd; - TextPaint mPaint; - int mWidth; - Alignment mAlignment; - TextDirectionHeuristic mTextDir; - float mSpacingMult; - float mSpacingAdd; - boolean mIncludePad; - int mEllipsizedWidth; - TextUtils.TruncateAt mEllipsize; - int mMaxLines; - int mBreakStrategy; - int mHyphenationFrequency; - int[] mLeftIndents; - int[] mRightIndents; - int mJustificationMode; - boolean mAddLastLineLineSpacing; - - Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt(); + private CharSequence mText; + private int mStart; + private int mEnd; + private TextPaint mPaint; + private int mWidth; + private Alignment mAlignment; + private TextDirectionHeuristic mTextDir; + private float mSpacingMult; + private float mSpacingAdd; + private boolean mIncludePad; + private boolean mFallbackLineSpacing; + private int mEllipsizedWidth; + private TextUtils.TruncateAt mEllipsize; + private int mMaxLines; + private int mBreakStrategy; + private int mHyphenationFrequency; + @Nullable private int[] mLeftIndents; + @Nullable private int[] mRightIndents; + private int mJustificationMode; + private boolean mAddLastLineLineSpacing; + + private final Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt(); // This will go away and be subsumed by native builder code - MeasuredText mMeasuredText; + private MeasuredText mMeasuredText; - LocaleList mLocales; + private LocaleList mLocales; private static final SynchronizedPool<Builder> sPool = new SynchronizedPool<Builder>(3); } @@ -528,12 +567,17 @@ public class StaticLayout extends Layout { .setEllipsize(ellipsize) .setMaxLines(maxLines); /* - * This is annoying, but we can't refer to the layout until - * superclass construction is finished, and the superclass - * constructor wants the reference to the display text. + * This is annoying, but we can't refer to the layout until superclass construction is + * finished, and the superclass constructor wants the reference to the display text. * - * This will break if the superclass constructor ever actually - * cares about the content instead of just holding the reference. + * In other words, the two Ellipsizer classes in Layout.java need a (Dynamic|Static)Layout + * as a parameter to do their calculations, but the Ellipsizers also need to be the input + * to the superclass's constructor (Layout). In order to go around the circular + * dependency, we construct the Ellipsizer with only one of the parameters, the text. And + * we fill in the rest of the needed information (layout, width, and method) later, here. + * + * This will break if the superclass constructor ever actually cares about the content + * instead of just holding the reference. */ if (ellipsize != null) { Ellipsizer e = (Ellipsizer) getText(); @@ -606,6 +650,7 @@ public class StaticLayout extends Layout { TextPaint paint = b.mPaint; int outerWidth = b.mWidth; TextDirectionHeuristic textDir = b.mTextDir; + final boolean fallbackLineSpacing = b.mFallbackLineSpacing; float spacingmult = b.mSpacingMult; float spacingadd = b.mSpacingAdd; float ellipsizedWidth = b.mEllipsizedWidth; @@ -621,7 +666,7 @@ public class StaticLayout extends Layout { mLineCount = 0; mEllipsized = false; - mMaxLineHeight = DEFAULT_MAX_LINE_HEIGHT; + mMaxLineHeight = mMaximumVisibleLineCount < 1 ? 0 : DEFAULT_MAX_LINE_HEIGHT; int v = 0; boolean needMultiply = (spacingmult != 1 || spacingadd != 0); @@ -635,6 +680,22 @@ public class StaticLayout extends Layout { if (source instanceof Spanned) spanned = (Spanned) source; + final int[] indents; + if (mLeftIndents != null || mRightIndents != null) { + final int leftLen = mLeftIndents == null ? 0 : mLeftIndents.length; + final int rightLen = mRightIndents == null ? 0 : mRightIndents.length; + final int indentsLen = Math.max(leftLen, rightLen); + indents = new int[indentsLen]; + for (int i = 0; i < leftLen; i++) { + indents[i] = mLeftIndents[i]; + } + for (int i = 0; i < rightLen; i++) { + indents[i] += mRightIndents[i]; + } + } else { + indents = null; + } + int paraEnd; for (int paraStart = bufStart; paraStart <= bufEnd; paraStart = paraEnd) { paraEnd = TextUtils.indexOf(source, CHAR_NEW_LINE, paraStart, bufEnd); @@ -719,24 +780,7 @@ public class StaticLayout extends Layout { firstWidth, firstWidthLineCount, restWidth, variableTabStops, TAB_INCREMENT, b.mBreakStrategy, b.mHyphenationFrequency, // TODO: Support more justification mode, e.g. letter spacing, stretching. - b.mJustificationMode != Layout.JUSTIFICATION_MODE_NONE); - if (mLeftIndents != null || mRightIndents != null) { - // TODO(performance): it would be better to do this once per layout rather - // than once per paragraph, but that would require a change to the native - // interface. - int leftLen = mLeftIndents == null ? 0 : mLeftIndents.length; - int rightLen = mRightIndents == null ? 0 : mRightIndents.length; - int indentsLen = Math.max(1, Math.max(leftLen, rightLen) - mLineCount); - int[] indents = new int[indentsLen]; - for (int i = 0; i < indentsLen; i++) { - int leftMargin = mLeftIndents == null ? 0 : - mLeftIndents[Math.min(i + mLineCount, leftLen - 1)]; - int rightMargin = mRightIndents == null ? 0 : - mRightIndents[Math.min(i + mLineCount, rightLen - 1)]; - indents[i] = leftMargin + rightMargin; - } - nSetIndents(b.mNativePtr, indents); - } + b.mJustificationMode != Layout.JUSTIFICATION_MODE_NONE, indents, mLineCount); // measurement has to be done before performing line breaking // but we don't want to recompute fontmetrics or span ranges the @@ -784,11 +828,14 @@ public class StaticLayout extends Layout { nGetWidths(b.mNativePtr, widths); int breakCount = nComputeLineBreaks(b.mNativePtr, lineBreaks, lineBreaks.breaks, - lineBreaks.widths, lineBreaks.flags, lineBreaks.breaks.length); + lineBreaks.widths, lineBreaks.ascents, lineBreaks.descents, lineBreaks.flags, + lineBreaks.breaks.length); - int[] breaks = lineBreaks.breaks; - float[] lineWidths = lineBreaks.widths; - int[] flags = lineBreaks.flags; + final int[] breaks = lineBreaks.breaks; + final float[] lineWidths = lineBreaks.widths; + final float[] ascents = lineBreaks.ascents; + final float[] descents = lineBreaks.descents; + final int[] flags = lineBreaks.flags; final int remainingLineCount = mMaximumVisibleLineCount - mLineCount; final boolean ellipsisMayBeApplied = ellipsize != null @@ -799,7 +846,7 @@ public class StaticLayout extends Layout { && ellipsisMayBeApplied) { // Calculate width and flag. float width = 0; - int flag = 0; + int flag = 0; // XXX May need to also have starting hyphen edit for (int i = remainingLineCount - 1; i < breakCount; i++) { if (i == breakCount - 1) { width += lineWidths[i]; @@ -808,7 +855,7 @@ public class StaticLayout extends Layout { width += widths[j]; } } - flag |= flags[i] & TAB_MASK; // XXX May need to also have starting hyphen edit + flag |= flags[i] & TAB_MASK; } // Treat the last line and overflowed lines as a single line. breaks[remainingLineCount - 1] = breaks[breakCount - 1]; @@ -859,8 +906,14 @@ public class StaticLayout extends Layout { boolean moreChars = (endPos < bufEnd); + final int ascent = fallbackLineSpacing + ? Math.min(fmAscent, (int) Math.round(ascents[breakIndex])) + : fmAscent; + final int descent = fallbackLineSpacing + ? Math.max(fmDescent, (int) Math.round(descents[breakIndex])) + : fmDescent; v = out(source, here, endPos, - fmAscent, fmDescent, fmTop, fmBottom, + ascent, descent, fmTop, fmBottom, v, spacingmult, spacingadd, chooseHt, chooseHtv, fm, flags[breakIndex], needMultiply, chdirs, dir, easy, bufEnd, includepad, trackpad, addLastLineSpacing, chs, widths, paraStart, ellipsize, @@ -891,8 +944,6 @@ public class StaticLayout extends Layout { if ((bufEnd == bufStart || source.charAt(bufEnd - 1) == CHAR_NEW_LINE) && mLineCount < mMaximumVisibleLineCount) { - // Log.e("text", "output last " + bufEnd); - measured.setPara(source, bufEnd, bufEnd, textDir, b); paint.getFontMetricsInt(fm); @@ -1446,13 +1497,14 @@ public class StaticLayout extends Layout { private static native void nSetLocales(long nativePtr, String locales, long[] nativeHyphenators); - private static native void nSetIndents(long nativePtr, int[] indents); - // Set up paragraph text and settings; done as one big method to minimize jni crossings - private static native void nSetupParagraph(long nativePtr, char[] text, int length, - float firstWidth, int firstWidthLineCount, float restWidth, - int[] variableTabStops, int defaultTabStop, int breakStrategy, int hyphenationFrequency, - boolean isJustified); + private static native void nSetupParagraph( + @NonNull long nativePtr, @NonNull char[] text, @IntRange(from = 0) int length, + @FloatRange(from = 0.0f) float firstWidth, @IntRange(from = 0) int firstWidthLineCount, + @FloatRange(from = 0.0f) float restWidth, @Nullable int[] variableTabStops, + int defaultTabStop, @BreakStrategy int breakStrategy, + @HyphenationFrequency int hyphenationFrequency, boolean isJustified, + @Nullable int[] indents, @IntRange(from = 0) int indentsOffset); private static native float nAddStyleRun(long nativePtr, long nativePaint, int start, int end, boolean isRtl); @@ -1470,7 +1522,8 @@ public class StaticLayout extends Layout { // to reduce the number of JNI calls in the common case where the // arrays do not have to be resized private static native int nComputeLineBreaks(long nativePtr, LineBreaks recycle, - int[] recycleBreaks, float[] recycleWidths, int[] recycleFlags, int recycleLength); + int[] recycleBreaks, float[] recycleWidths, float[] recycleAscents, + float[] recycleDescents, int[] recycleFlags, int recycleLength); private int mLineCount; private int mTopPadding, mBottomPadding; @@ -1529,10 +1582,12 @@ public class StaticLayout extends Layout { private static final int INITIAL_SIZE = 16; public int[] breaks = new int[INITIAL_SIZE]; public float[] widths = new float[INITIAL_SIZE]; + public float[] ascents = new float[INITIAL_SIZE]; + public float[] descents = new float[INITIAL_SIZE]; public int[] flags = new int[INITIAL_SIZE]; // hasTab // breaks, widths, and flags should all have the same length } - private int[] mLeftIndents; - private int[] mRightIndents; + @Nullable private int[] mLeftIndents; + @Nullable private int[] mRightIndents; } diff --git a/core/java/android/transition/TransitionUtils.java b/core/java/android/transition/TransitionUtils.java index 49ceb3b5365e..4951237e5cc9 100644 --- a/core/java/android/transition/TransitionUtils.java +++ b/core/java/android/transition/TransitionUtils.java @@ -20,12 +20,14 @@ import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.TypeEvaluator; import android.graphics.Bitmap; -import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import android.view.DisplayListCanvas; +import android.view.RenderNode; +import android.view.ThreadedRenderer; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; @@ -126,8 +128,11 @@ public class TransitionUtils { } int bitmapWidth = (int) (width * scale); int bitmapHeight = (int) (height * scale); - Bitmap bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); + final RenderNode node = RenderNode.create("TransitionUtils", null); + node.setLeftTopRightBottom(0, 0, width, height); + node.setClipToBounds(false); + final DisplayListCanvas canvas = node.start(width, height); + // Do stuff with the canvas Rect existingBounds = drawable.getBounds(); int left = existingBounds.left; int top = existingBounds.top; @@ -136,7 +141,8 @@ public class TransitionUtils { drawable.setBounds(0, 0, bitmapWidth, bitmapHeight); drawable.draw(canvas); drawable.setBounds(left, top, right, bottom); - return bitmap; + node.end(canvas); + return ThreadedRenderer.createHardwareBitmap(node, width, height); } /** @@ -162,10 +168,15 @@ public class TransitionUtils { bitmapHeight *= scale; matrix.postTranslate(-bounds.left, -bounds.top); matrix.postScale(scale, scale); - bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); + + final RenderNode node = RenderNode.create("TransitionUtils", null); + node.setLeftTopRightBottom(0, 0, bitmapWidth, bitmapHeight); + node.setClipToBounds(false); + final DisplayListCanvas canvas = node.start(bitmapWidth, bitmapHeight); canvas.concat(matrix); view.draw(canvas); + node.end(canvas); + bitmap = ThreadedRenderer.createHardwareBitmap(node, bitmapWidth, bitmapHeight); } return bitmap; } diff --git a/core/java/android/util/ExceptionUtils.java b/core/java/android/util/ExceptionUtils.java index 44019c32560d..da7387fcae70 100644 --- a/core/java/android/util/ExceptionUtils.java +++ b/core/java/android/util/ExceptionUtils.java @@ -78,4 +78,12 @@ public class ExceptionUtils { propagateIfInstanceOf(t, RuntimeException.class); throw new RuntimeException(t); } + + /** + * Gets the root {@link Throwable#getCause() cause} of {@code t} + */ + public static @NonNull Throwable getRootCause(@NonNull Throwable t) { + while (t.getCause() != null) t = t.getCause(); + return t; + } } diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java new file mode 100644 index 000000000000..5838f9590c9d --- /dev/null +++ b/core/java/android/util/FeatureFlagUtils.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.util; + +import android.os.SystemProperties; +import android.text.TextUtils; + +import java.util.Map; + +/** + * Util class to get feature flag information. + * + * @hide + */ +public class FeatureFlagUtils { + + public static final String FFLAG_PREFIX = "sys.fflag."; + public static final String FFLAG_OVERRIDE_PREFIX = FFLAG_PREFIX + "override."; + + /** + * Whether or not a flag is enabled. + * + * @param feature the flag name + * @return true if the flag is enabled (either by default in system, or override by user) + */ + public static boolean isEnabled(String feature) { + // Tries to get feature flag from system property. + // Step 1: check if feature flag has any override. Flag name: sys.fflag.override.<feature> + String value = SystemProperties.get(FFLAG_OVERRIDE_PREFIX + feature); + if (!TextUtils.isEmpty(value)) { + return Boolean.parseBoolean(value); + } + // Step 2: check if feature flag has any default value. Flag name: sys.fflag.<feature> + value = SystemProperties.get(FFLAG_PREFIX + feature); + return Boolean.parseBoolean(value); + } + + /** + * Returns all feature flags in their raw form. + */ + public static Map<String, String> getAllFeatureFlags() { + return null; + } +} diff --git a/core/java/android/util/IconDrawableFactory.java b/core/java/android/util/IconDrawableFactory.java index b07942ff7f9d..6a6c2ce4838e 100644 --- a/core/java/android/util/IconDrawableFactory.java +++ b/core/java/android/util/IconDrawableFactory.java @@ -21,7 +21,6 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageItemInfo; import android.content.pm.PackageManager; import android.content.res.Resources; -import android.graphics.Color; import android.graphics.drawable.Drawable; import android.os.UserHandle; import android.os.UserManager; @@ -68,8 +67,7 @@ public class IconDrawableFactory { return icon; } - // Before badging, add shadow to adaptive icon if needed. - icon = mLauncherIcons.wrapIconDrawableWithShadow(icon); + icon = getShadowedIcon(icon); if (appInfo.isInstantApp()) { int badgeColor = Resources.getSystem().getColor( com.android.internal.R.color.instant_app_badge, null); @@ -85,6 +83,13 @@ public class IconDrawableFactory { return icon; } + /** + * Add shadow to the icon if {@link AdaptiveIconDrawable} + */ + public Drawable getShadowedIcon(Drawable icon) { + return mLauncherIcons.wrapIconDrawableWithShadow(icon); + } + // Should have enough colors to cope with UserManagerService.getMaxManagedProfiles() @VisibleForTesting public static final int[] CORP_BADGE_COLORS = new int[] { diff --git a/core/java/android/util/PackageUtils.java b/core/java/android/util/PackageUtils.java index 0fe56f6efa21..e2e9d53e7e9e 100644 --- a/core/java/android/util/PackageUtils.java +++ b/core/java/android/util/PackageUtils.java @@ -18,12 +18,13 @@ package android.util; import android.annotation.NonNull; import android.annotation.Nullable; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; import android.content.pm.Signature; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.Arrays; /** * Helper functions applicable to packages. @@ -36,32 +37,67 @@ public final class PackageUtils { } /** - * Computes the SHA256 digest of the signing cert for a package. - * @param packageManager The package manager. - * @param packageName The package for which to generate the digest. - * @param userId The user for which to generate the digest. - * @return The digest or null if the package does not exist for this user. + * Computes the SHA256 digests of a list of signatures. Items in the + * resulting array of hashes correspond to the signatures in the + * input array. + * @param signatures The signatures. + * @return The digest array. */ - public static @Nullable String computePackageCertSha256Digest( - @NonNull PackageManager packageManager, - @NonNull String packageName, int userId) { - final PackageInfo packageInfo; - try { - packageInfo = packageManager.getPackageInfoAsUser(packageName, - PackageManager.GET_SIGNATURES, userId); - } catch (PackageManager.NameNotFoundException e) { - return null; + public static @NonNull String[] computeSignaturesSha256Digests( + @NonNull Signature[] signatures) { + final int signatureCount = signatures.length; + final String[] digests = new String[signatureCount]; + for (int i = 0; i < signatureCount; i++) { + digests[i] = computeSha256Digest(signatures[i].toByteArray()); + } + return digests; + } + /** + * Computes a SHA256 digest of the signatures' SHA256 digests. First, + * individual hashes for each signature is derived in a hexademical + * form, then these strings are sorted based the natural ordering, and + * finally a hash is derived from these strings' bytes. + * @param signatures The signatures. + * @return The digest. + */ + public static @NonNull String computeSignaturesSha256Digest( + @NonNull Signature[] signatures) { + // Shortcut for optimization - most apps singed by a single cert + if (signatures.length == 1) { + return computeSha256Digest(signatures[0].toByteArray()); } - return computeCertSha256Digest(packageInfo.signatures[0]); + + // Make sure these are sorted to handle reversed certificates + final String[] sha256Digests = computeSignaturesSha256Digests(signatures); + return computeSignaturesSha256Digest(sha256Digests); } /** - * Computes the SHA256 digest of a cert. - * @param signature The signature. - * @return The digest or null if an error occurs. + * Computes a SHA256 digest in of the signatures SHA256 digests. First, + * the strings are sorted based the natural ordering, and then a hash is + * derived from these strings' bytes. + * @param sha256Digests Signature SHA256 hashes in hexademical form. + * @return The digest. */ - public static @Nullable String computeCertSha256Digest(@NonNull Signature signature) { - return computeSha256Digest(signature.toByteArray()); + public static @NonNull String computeSignaturesSha256Digest( + @NonNull String[] sha256Digests) { + // Shortcut for optimization - most apps singed by a single cert + if (sha256Digests.length == 1) { + return sha256Digests[0]; + } + + // Make sure these are sorted to handle reversed certificates + Arrays.sort(sha256Digests); + + final ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + for (String sha256Digest : sha256Digests) { + try { + bytes.write(sha256Digest.getBytes()); + } catch (IOException e) { + /* ignore - can't happen */ + } + } + return computeSha256Digest(bytes.toByteArray()); } /** diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java index ca3985449d92..50cd7b18e254 100644 --- a/core/java/android/util/Patterns.java +++ b/core/java/android/util/Patterns.java @@ -406,7 +406,7 @@ public class Patterns { * the local part to be at most 64 octets. */ private static final String EMAIL_ADDRESS_LOCAL_PART = - "[" + EMAIL_CHAR + "]" + "(?:[" + EMAIL_CHAR + "\\.]{1,62}[" + EMAIL_CHAR + "])?"; + "[" + EMAIL_CHAR + "]" + "(?:[" + EMAIL_CHAR + "\\.]{0,62}[" + EMAIL_CHAR + "])?"; /** * Regular expression for the domain part of an email address. RFC5321 section 4.5.3.1.2 limits diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java new file mode 100644 index 000000000000..0be1a8cfabae --- /dev/null +++ b/core/java/android/util/StatsLog.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2007 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.util; + +/** + * Logging access for platform metrics. + * + * <p>This is <b>not</b> the main "logcat" debugging log ({@link android.util.Log})! + * These diagnostic stats are for system integrators, not application authors. + * + * <p>Stats use integer tag codes. + * They carry a payload of one or more int, long, or String values. + * @hide + */ +public class StatsLog { + /** @hide */ public StatsLog() {} + + private static final String TAG = "StatsLog"; + + // We assume that the native methods deal with any concurrency issues. + + /** + * Records an stats log message. + * @param tag The stats type tag code + * @param value A value to log + * @return The number of bytes written + */ + public static native int writeInt(int tag, int value); + + /** + * Records an stats log message. + * @param tag The stats type tag code + * @param value A value to log + * @return The number of bytes written + */ + public static native int writeLong(int tag, long value); + + /** + * Records an stats log message. + * @param tag The stats type tag code + * @param value A value to log + * @return The number of bytes written + */ + public static native int writeFloat(int tag, float value); + + /** + * Records an stats log message. + * @param tag The stats type tag code + * @param str A value to log + * @return The number of bytes written + */ + public static native int writeString(int tag, String str); + + /** + * Records an stats log message. + * @param tag The stats type tag code + * @param list A list of values to log. All values should + * be of type int, long, float or String. + * @return The number of bytes written + */ + public static native int writeArray(int tag, Object... list); +} diff --git a/core/java/android/util/BootTimingsTraceLog.java b/core/java/android/util/TimingsTraceLog.java index 7a702a92d3b1..36e9f77bb831 100644 --- a/core/java/android/util/BootTimingsTraceLog.java +++ b/core/java/android/util/TimingsTraceLog.java @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package android.util; @@ -24,22 +24,26 @@ import java.util.ArrayDeque; import java.util.Deque; /** - * Helper class for reporting boot timing metrics. + * Helper class for reporting boot and shutdown timing metrics. * @hide */ -public class BootTimingsTraceLog { +public class TimingsTraceLog { // Debug boot time for every step if it's non-user build. private static final boolean DEBUG_BOOT_TIME = !Build.IS_USER; - private final Deque<Pair<String, Long>> mStartTimes - = DEBUG_BOOT_TIME ? new ArrayDeque<>() : null; + private final Deque<Pair<String, Long>> mStartTimes = + DEBUG_BOOT_TIME ? new ArrayDeque<>() : null; private final String mTag; private long mTraceTag; - public BootTimingsTraceLog(String tag, long traceTag) { + public TimingsTraceLog(String tag, long traceTag) { mTag = tag; mTraceTag = traceTag; } + /** + * Begin tracing named section + * @param name name to appear in trace + */ public void traceBegin(String name) { Trace.traceBegin(mTraceTag, name); if (DEBUG_BOOT_TIME) { @@ -47,6 +51,10 @@ public class BootTimingsTraceLog { } } + /** + * End tracing previously {@link #traceBegin(String) started} section. + * Also {@link #logDuration logs} the duration. + */ public void traceEnd() { Trace.traceEnd(mTraceTag); if (!DEBUG_BOOT_TIME) { @@ -57,8 +65,13 @@ public class BootTimingsTraceLog { return; } Pair<String, Long> event = mStartTimes.pop(); - // Log the duration so it can be parsed by external tools for performance reporting - Slog.d(mTag, event.first + " took to complete: " - + (SystemClock.elapsedRealtime() - event.second) + "ms"); + logDuration(event.first, (SystemClock.elapsedRealtime() - event.second)); + } + + /** + * Log the duration so it can be parsed by external tools for performance reporting + */ + public void logDuration(String name, long timeMs) { + Slog.d(mTag, name + " took to complete: " + timeMs + "ms"); } } diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java index 597be6864494..2ffa1c5eb4c0 100644 --- a/core/java/android/view/Choreographer.java +++ b/core/java/android/view/Choreographer.java @@ -19,6 +19,7 @@ package android.view; import static android.view.DisplayEventReceiver.VSYNC_SOURCE_APP; import static android.view.DisplayEventReceiver.VSYNC_SOURCE_SURFACE_FLINGER; +import android.annotation.TestApi; import android.hardware.display.DisplayManagerGlobal; import android.os.Handler; import android.os.Looper; @@ -195,6 +196,7 @@ public final class Choreographer { * Callback type: Animation callback. Runs before traversals. * @hide */ + @TestApi public static final int CALLBACK_ANIMATION = 1; /** @@ -286,6 +288,7 @@ public final class Choreographer { * @return the requested time between frames, in milliseconds * @hide */ + @TestApi public static long getFrameDelay() { return sFrameDelay; } @@ -305,6 +308,7 @@ public final class Choreographer { * @param frameDelay the requested time between frames, in milliseconds * @hide */ + @TestApi public static void setFrameDelay(long frameDelay) { sFrameDelay = frameDelay; } diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 97788931ea93..e7c3f92da830 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -26,6 +26,7 @@ import android.content.res.Resources; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.Rect; +import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerGlobal; import android.os.Parcel; import android.os.Parcelable; @@ -200,11 +201,16 @@ public final class Display { * Display flag: Indicates that the display can show its content when non-secure keyguard is * shown. * <p> - * This flag identifies secondary displays that won't show keyguard if it can be dismissed - * without entering credentials. Display content will be shown even if other displays are - * locked. + * This flag identifies secondary displays that will continue showing content if keyguard can be + * dismissed without entering credentials. + * </p><p> + * An example of usage is a virtual display which content is displayed on external hardware + * display that is not visible to the system directly. * </p> * + * @see DisplayManager#VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD + * @see WindowManagerPolicy#isKeyguardSecure(int) + * @see WindowManagerPolicy#isKeyguardTrustedLw() * @see #getFlags * @hide */ diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index 0cec496fa264..b813ddb63859 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -16,12 +16,19 @@ package android.view; +import static android.view.DisplayInfoProto.APP_HEIGHT; +import static android.view.DisplayInfoProto.APP_WIDTH; +import static android.view.DisplayInfoProto.LOGICAL_HEIGHT; +import static android.view.DisplayInfoProto.LOGICAL_WIDTH; + import android.content.res.CompatibilityInfo; import android.content.res.Configuration; +import android.graphics.Rect; import android.os.Parcel; import android.os.Parcelable; import android.util.ArraySet; import android.util.DisplayMetrics; +import android.util.proto.ProtoOutputStream; import libcore.util.Objects; @@ -562,10 +569,10 @@ public final class DisplayInfo implements Parcelable { outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi; outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi; - width = configuration != null && configuration.appBounds != null - ? configuration.appBounds.width() : width; - height = configuration != null && configuration.appBounds != null - ? configuration.appBounds.height() : height; + final Rect appBounds = configuration != null + ? configuration.windowConfiguration.getAppBounds() : null; + width = appBounds != null ? appBounds.width() : width; + height = appBounds != null ? appBounds.height() : height; outMetrics.noncompatWidthPixels = outMetrics.widthPixels = width; outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height; @@ -654,6 +661,22 @@ public final class DisplayInfo implements Parcelable { return sb.toString(); } + /** + * Write to a protocol buffer output stream. + * Protocol buffer message definition at {@link android.view.DisplayInfoProto} + * + * @param protoOutputStream Stream to write the Rect object to. + * @param fieldId Field Id of the DisplayInfoProto as defined in the parent message + */ + public void writeToProto(ProtoOutputStream protoOutputStream, long fieldId) { + final long token = protoOutputStream.start(fieldId); + protoOutputStream.write(LOGICAL_WIDTH, logicalWidth); + protoOutputStream.write(LOGICAL_HEIGHT, logicalHeight); + protoOutputStream.write(APP_WIDTH, appWidth); + protoOutputStream.write(APP_HEIGHT, appHeight); + protoOutputStream.end(token); + } + private static String flagsToString(int flags) { StringBuilder result = new StringBuilder(); if ((flags & Display.FLAG_SECURE) != 0) { diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java index c43132388b56..b14792842be6 100644 --- a/core/java/android/view/HapticFeedbackConstants.java +++ b/core/java/android/view/HapticFeedbackConstants.java @@ -57,16 +57,24 @@ public class HapticFeedbackConstants { public static final int CONTEXT_CLICK = 6; /** - * The user has released a virtual or software keyboard key. - * @hide + * The user has pressed a virtual or software keyboard key. + */ + public static final int KEYBOARD_PRESS = KEYBOARD_TAP; + + /** + * The user has released a virtual keyboard key. */ - public static final int VIRTUAL_KEY_RELEASE = 7; + public static final int KEYBOARD_RELEASE = 7; + + /** + * The user has released a virtual key. + */ + public static final int VIRTUAL_KEY_RELEASE = 8; /** * The user has performed a selection/insertion handle move on text field. - * @hide */ - public static final int TEXT_HANDLE_MOVE = 8; + public static final int TEXT_HANDLE_MOVE = 9; /** * The phone has booted with safe mode enabled. diff --git a/core/java/android/view/IApplicationToken.aidl b/core/java/android/view/IApplicationToken.aidl index b01c0ef55812..a063a70a3181 100644 --- a/core/java/android/view/IApplicationToken.aidl +++ b/core/java/android/view/IApplicationToken.aidl @@ -20,5 +20,6 @@ package android.view; /** {@hide} */ interface IApplicationToken { + String getName(); } diff --git a/core/java/android/view/Menu.java b/core/java/android/view/Menu.java index a8ea4dc1b8a0..6d1f740ad1da 100644 --- a/core/java/android/view/Menu.java +++ b/core/java/android/view/Menu.java @@ -451,5 +451,10 @@ public interface Menu { * will use numeric shortcuts. */ public void setQwertyMode(boolean isQwerty); -} + /** + * Enable or disable the group dividers. + */ + default void setGroupDividerEnabled(boolean groupDividerEnabled) { + } +}
\ No newline at end of file diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 78cdf5d922b4..2c1f73468ca6 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -659,6 +659,8 @@ public class Surface implements Parcelable { * * @see #isSharedBufferModeEnabled() * @see #setAutoRefreshEnabled(boolean) + * + * @hide */ public void setSharedBufferModeEnabled(boolean enabled) { if (mIsSharedBufferModeEnabled != enabled) { @@ -676,6 +678,8 @@ public class Surface implements Parcelable { * @return True if shared buffer mode is enabled on this surface, false otherwise * * @see #setSharedBufferModeEnabled(boolean) + * + * @hide */ public boolean isSharedBufferModeEnabled() { return mIsSharedBufferModeEnabled; @@ -699,6 +703,8 @@ public class Surface implements Parcelable { * * @see #isAutoRefreshEnabled() * @see #setSharedBufferModeEnabled(boolean) + * + * @hide */ public void setAutoRefreshEnabled(boolean enabled) { if (mIsAutoRefreshEnabled != enabled) { @@ -713,6 +719,8 @@ public class Surface implements Parcelable { /** * @return True if auto-refresh is enabled on this surface, false otherwise + * + * @hide */ public boolean isAutoRefreshEnabled() { return mIsAutoRefreshEnabled; diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 1a2968f6345f..91932dd40dd8 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -105,6 +105,8 @@ public class SurfaceControl { long surfaceObject, long frame); private static native void nativeReparentChildren(long nativeObject, IBinder handle); + private static native void nativeReparentChild(long nativeObject, + IBinder parentHandle, IBinder childHandle); private static native void nativeSeverChildren(long nativeObject); private static native void nativeSetOverrideScalingMode(long nativeObject, int scalingMode); @@ -453,6 +455,11 @@ public class SurfaceControl { nativeReparentChildren(mNativeObject, newParentHandle); } + /** Re-parents a specific child layer to a new parent */ + public void reparentChild(IBinder newParentHandle, IBinder childHandle) { + nativeReparentChild(mNativeObject, newParentHandle, childHandle); + } + public void detachChildren() { nativeSeverChildren(mNativeObject); } diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index 489de565acb6..2166f6e4742b 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -914,6 +914,14 @@ public final class ThreadedRenderer { return nCreateHardwareBitmap(node.getNativeDisplayList(), width, height); } + /** + * Sets whether or not high contrast text rendering is enabled. The setting is global + * but only affects content rendered after the change is made. + */ + public static void setHighContrastText(boolean highContrastText) { + nSetHighContrastText(highContrastText); + } + @Override protected void finalize() throws Throwable { try { @@ -1063,4 +1071,5 @@ public final class ThreadedRenderer { int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap); private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height); + private static native void nSetHighContrastText(boolean enabled); } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index d3b03102be07..e5bd5ac076f3 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -3354,6 +3354,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION * FLAG_TRANSLUCENT_NAVIGATION}. + * + * @see android.R.attr#windowLightNavigationBar */ public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010; @@ -7451,7 +7453,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * {@link ViewStructure#setAutofillOptions(CharSequence[])}. * </ul> * - * <p><b>NOTE:</b> the {@code left} and {@code top} values set in + * <p><b>Note:</b> The {@code left} and {@code top} values set in * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure. * @@ -7619,6 +7621,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * <li>Call * {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)} * when the value of a virtual child changed. + * <li>Call {@link + * android.view.autofill.AutofillManager#notifyViewVisibilityChanged(View, int, boolean)} + * when the visibility of a virtual child changed. * <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure * changed and the current context should be committed (for example, when the user tapped * a {@code SUBMIT} button in an HTML page). @@ -7689,6 +7694,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was * changed to the autofilled value. If not, the view will not be considered autofilled. * + * <p><b>Note:</b> After this method is called, the value returned by + * {@link #getAutofillValue()} must be equal to the {@code value} passed to it, otherwise the + * view will not be highlighted as autofilled. + * * @param value value to be autofilled. */ public void autofill(@SuppressWarnings("unused") AutofillValue value) { @@ -7712,7 +7721,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * <b>after</b> the value was changed to the autofilled value. If not, the child will not be * considered autofilled. * - * <p><b>NOTE:</b> to indicate that a virtual view was autofilled, + * <p><b>Note:</b> To indicate that a virtual view was autofilled, * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data * changes. * @@ -7781,8 +7790,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Gets the {@link View}'s current autofill value. * - * <p>By default returns {@code null}, but views should override it to properly support the - * Autofill Framework. + * <p>By default returns {@code null}, but subclasses should override it and return an + * appropriate value to properly support the Autofill Framework. * * @see #onProvideAutofillStructure(ViewStructure, int) * @see #autofill(AutofillValue) @@ -7834,7 +7843,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}. * </ol> * - * <p><b>NOTE:</strong> setting the mode as does {@link #IMPORTANT_FOR_AUTOFILL_NO} or + * <p><b>Note:</b> Setting the mode as {@link #IMPORTANT_FOR_AUTOFILL_NO} or * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its * children) will be always be considered not important; for example, when the user explicitly * makes an autofill request, all views are considered important. See @@ -8079,10 +8088,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, boolean forAutofill, @AutofillFlags int flags) { if (forAutofill) { structure.setAutofillId(getAutofillId()); - if (!isLaidOut()) { - Log.w(VIEW_LOG_TAG, "dispatchProvideAutofillStructure(): not laid out, ignoring"); - return; - } onProvideAutofillStructure(structure, flags); onProvideAutofillVirtualStructure(structure, flags); } else if (!isAssistBlocked()) { @@ -13161,17 +13166,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * Remove the pending callback for sending a - * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event. - */ - private void removeSendViewScrolledAccessibilityEventCallback() { - if (mSendViewScrolledAccessibilityEvent != null) { - removeCallbacks(mSendViewScrolledAccessibilityEvent); - mSendViewScrolledAccessibilityEvent.mIsPending = false; - } - } - - /** * Sets the TouchDelegate for this View. */ public void setTouchDelegate(TouchDelegate delegate) { @@ -13251,6 +13245,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, && ((privateFlags & PFLAG_FOCUSED) != 0)) { /* Give up focus if we are no longer focusable */ clearFocus(); + if (mParent instanceof ViewGroup) { + ((ViewGroup) mParent).clearFocusedInCluster(); + } } else if (((old & FOCUSABLE) == NOT_FOCUSABLE) && ((privateFlags & PFLAG_FOCUSED) == 0)) { /* @@ -13315,7 +13312,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, requestLayout(); if (((mViewFlags & VISIBILITY_MASK) == GONE)) { - if (hasFocus()) clearFocus(); + if (hasFocus()) { + clearFocus(); + if (mParent instanceof ViewGroup) { + ((ViewGroup) mParent).clearFocusedInCluster(); + } + } clearAccessibilityFocus(); destroyDrawingCache(); if (mParent instanceof View) { @@ -13343,7 +13345,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) { // root view becoming invisible shouldn't clear focus and accessibility focus if (getRootView() != this) { - if (hasFocus()) clearFocus(); + if (hasFocus()) { + clearFocus(); + if (mParent instanceof ViewGroup) { + ((ViewGroup) mParent).clearFocusedInCluster(); + } + } clearAccessibilityFocus(); } } @@ -13468,7 +13475,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, notifySubtreeAccessibilityStateChangedIfNeeded(); if (AccessibilityManager.getInstance(mContext).isEnabled()) { - postSendViewScrolledAccessibilityEventCallback(); + postSendViewScrolledAccessibilityEventCallback(l - oldl, t - oldt); } mBackgroundSizeChanged = true; @@ -15998,15 +16005,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * This event is sent at most once every * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}. */ - private void postSendViewScrolledAccessibilityEventCallback() { + private void postSendViewScrolledAccessibilityEventCallback(int dx, int dy) { if (mSendViewScrolledAccessibilityEvent == null) { mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent(); } - if (!mSendViewScrolledAccessibilityEvent.mIsPending) { - mSendViewScrolledAccessibilityEvent.mIsPending = true; - postDelayed(mSendViewScrolledAccessibilityEvent, - ViewConfiguration.getSendRecurringAccessibilityEventsInterval()); - } + mSendViewScrolledAccessibilityEvent.post(dx, dy); } /** @@ -17264,7 +17267,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, removeUnsetPressCallback(); removeLongPressCallback(); removePerformClickCallback(); - removeSendViewScrolledAccessibilityEventCallback(); + cancel(mSendViewScrolledAccessibilityEvent); stopNestedScroll(); // Anything that started animating right before detach should already @@ -18074,7 +18077,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, int layerType = getLayerType(); final DisplayListCanvas canvas = renderNode.start(width, height); - canvas.setHighContrastText(mAttachInfo.mHighContrastText); try { if (layerType == LAYER_TYPE_SOFTWARE) { @@ -25384,11 +25386,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, boolean mViewScrollChanged; /** - * Set to true if high contrast mode enabled - */ - boolean mHighContrastText; - - /** * Set to true if a pointer event is currently being handled. */ boolean mHandlingPointerEvent; @@ -25705,14 +25702,48 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ private class SendViewScrolledAccessibilityEvent implements Runnable { public volatile boolean mIsPending; + public int mDeltaX; + public int mDeltaY; + + public void post(int dx, int dy) { + mDeltaX += dx; + mDeltaY += dy; + if (!mIsPending) { + mIsPending = true; + postDelayed(this, ViewConfiguration.getSendRecurringAccessibilityEventsInterval()); + } + } + @Override public void run() { - sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED); + if (AccessibilityManager.getInstance(mContext).isEnabled()) { + AccessibilityEvent event = AccessibilityEvent.obtain( + AccessibilityEvent.TYPE_VIEW_SCROLLED); + event.setScrollDeltaX(mDeltaX); + event.setScrollDeltaY(mDeltaY); + sendAccessibilityEventUnchecked(event); + } + reset(); + } + + private void reset() { mIsPending = false; + mDeltaX = 0; + mDeltaY = 0; } } /** + * Remove the pending callback for sending a + * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event. + */ + private void cancel(@Nullable SendViewScrolledAccessibilityEvent callback) { + if (callback == null || !callback.mIsPending) return; + removeCallbacks(callback); + callback.reset(); + } + + /** * <p> * This class represents a delegate that can be registered in a {@link View} * to enhance accessibility support via composition rather via inheritance. diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 42e7c792cd01..b2e5a163d872 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -818,6 +818,13 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (mFocusedInCluster != child) { return; } + clearFocusedInCluster(); + } + + /** + * Removes the focusedInCluster chain from this up to the cluster containing it. + */ + void clearFocusedInCluster() { View top = findKeyboardNavigationCluster(); ViewParent parent = this; do { @@ -3400,6 +3407,13 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (childrenCount <= 0) { return; } + + if (!isLaidOut()) { + Log.v(VIEW_LOG_TAG, "dispatchProvideStructure(): not laid out, ignoring " + + childrenCount + " children of " + getAccessibilityViewId()); + return; + } + structure.setChildCount(childrenCount); ArrayList<View> preorderedList = buildOrderedChildList(); boolean customOrder = preorderedList == null @@ -3476,6 +3490,13 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (structure.getChildCount() != 0) { return; } + + if (!isLaidOut()) { + Log.v(VIEW_LOG_TAG, "dispatchProvideAutofillStructure(): not laid out, ignoring " + + mChildrenCount + " children of " + getAutofillId()); + return; + } + final ChildListForAutoFill children = getChildrenForAutofill(flags); final int childrenCount = children.size(); structure.setChildCount(childrenCount); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 6bf48450fc71..415aad54ee78 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -259,6 +259,9 @@ public final class ViewRootImpl implements ViewParent, // visibility to control drawing. The decor view visibility will get adjusted when the app get // stopped and that's when the app will stop drawing further frames. private boolean mForceDecorViewVisibility = false; + // Used for tracking app visibility updates separately in case we get double change. This will + // make sure that we always call relayout for the corresponding window. + private boolean mAppVisibilityChanged; int mOrigWindowType = -1; /** Whether the window had focus during the most recent traversal. */ @@ -1058,6 +1061,7 @@ public final class ViewRootImpl implements ViewParent, void handleAppVisibility(boolean visible) { if (mAppVisible != visible) { mAppVisible = visible; + mAppVisibilityChanged = true; scheduleTraversals(); if (!mAppVisible) { WindowManagerGlobal.trimForeground(); @@ -1600,7 +1604,11 @@ public final class ViewRootImpl implements ViewParent, final int viewVisibility = getHostVisibility(); final boolean viewVisibilityChanged = !mFirst - && (mViewVisibility != viewVisibility || mNewSurfaceNeeded); + && (mViewVisibility != viewVisibility || mNewSurfaceNeeded + // Also check for possible double visibility update, which will make current + // viewVisibility value equal to mViewVisibility and we may miss it. + || mAppVisibilityChanged); + mAppVisibilityChanged = false; final boolean viewUserVisibilityChanged = !mFirst && ((mViewVisibility == View.VISIBLE) != (viewVisibility == View.VISIBLE)); @@ -7741,11 +7749,11 @@ public final class ViewRootImpl implements ViewParent, final class HighContrastTextManager implements HighTextContrastChangeListener { HighContrastTextManager() { - mAttachInfo.mHighContrastText = mAccessibilityManager.isHighTextContrastEnabled(); + ThreadedRenderer.setHighContrastText(mAccessibilityManager.isHighTextContrastEnabled()); } @Override public void onHighTextContrastStateChanged(boolean enabled) { - mAttachInfo.mHighContrastText = enabled; + ThreadedRenderer.setHighContrastText(enabled); // Destroy Displaylists so they can be recreated with high contrast recordings destroyHardwareResources(); diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 3d6af414a3a0..176927fef0eb 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -26,6 +26,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.StyleRes; import android.annotation.SystemApi; +import android.app.WindowConfiguration; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Configuration; @@ -487,7 +488,7 @@ public abstract class Window { public void onAttachedToWindow(); /** - * Called when the window has been attached to the window manager. + * Called when the window has been detached from the window manager. * See {@link View#onDetachedFromWindow() View.onDetachedFromWindow()} * for more information. */ @@ -611,8 +612,8 @@ public abstract class Window { public interface WindowControllerCallback { /** * Moves the activity from - * {@link android.app.ActivityManager.StackId#FREEFORM_WORKSPACE_STACK_ID} to - * {@link android.app.ActivityManager.StackId#FULLSCREEN_WORKSPACE_STACK_ID} stack. + * Moves the activity from {@link WindowConfiguration#WINDOWING_MODE_FREEFORM} windowing + * mode to {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}. */ void exitFreeformMode() throws RemoteException; @@ -622,9 +623,6 @@ public abstract class Window { */ void enterPictureInPictureModeIfPossible(); - /** Returns the current stack Id for the window. */ - int getWindowStackId() throws RemoteException; - /** Returns whether the window belongs to the task root. */ boolean isTaskRoot(); } diff --git a/core/java/android/view/WindowInfo.java b/core/java/android/view/WindowInfo.java index 95a63944b3bc..bb9e391ddcb4 100644 --- a/core/java/android/view/WindowInfo.java +++ b/core/java/android/view/WindowInfo.java @@ -41,6 +41,7 @@ public class WindowInfo implements Parcelable { public int layer; public IBinder token; public IBinder parentToken; + public IBinder activityToken; public boolean focused; public final Rect boundsInScreen = new Rect(); public List<IBinder> childTokens; @@ -66,6 +67,7 @@ public class WindowInfo implements Parcelable { window.layer = other.layer; window.token = other.token; window.parentToken = other.parentToken; + window.activityToken = other.activityToken; window.focused = other.focused; window.boundsInScreen.set(other.boundsInScreen); window.title = other.title; @@ -99,6 +101,7 @@ public class WindowInfo implements Parcelable { parcel.writeInt(layer); parcel.writeStrongBinder(token); parcel.writeStrongBinder(parentToken); + parcel.writeStrongBinder(activityToken); parcel.writeInt(focused ? 1 : 0); boundsInScreen.writeToParcel(parcel, flags); parcel.writeCharSequence(title); @@ -135,6 +138,7 @@ public class WindowInfo implements Parcelable { layer = parcel.readInt(); token = parcel.readStrongBinder(); parentToken = parcel.readStrongBinder(); + activityToken = parcel.readStrongBinder(); focused = (parcel.readInt() == 1); boundsInScreen.readFromParcel(parcel); title = parcel.readCharSequence(); @@ -155,6 +159,7 @@ public class WindowInfo implements Parcelable { layer = 0; token = null; parentToken = null; + activityToken = null; focused = false; boundsInScreen.setEmpty(); if (childTokens != null) { diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 1e50a85833ec..e56a82ffabd2 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -16,6 +16,7 @@ package android.view; +import android.Manifest.permission; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresPermission; @@ -34,6 +35,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import android.util.Log; +import android.util.proto.ProtoOutputStream; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -1424,6 +1426,15 @@ public interface WindowManager extends ViewManager { public static final int PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY = 0x00100000; /** + * If this flag is set on the window, window manager will acquire a sleep token that puts + * all activities to sleep as long as this window is visible. When this flag is set, the + * window needs to occlude all activity windows. + * @hide + */ + @RequiresPermission(permission.DEVICE_POWER) + public static final int PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN = 0x00200000; + + /** * Control flags that are private to the platform. * @hide */ @@ -2545,6 +2556,15 @@ public interface WindowManager extends ViewManager { } /** + * @hide + */ + public void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + proto.write(WindowLayoutParamsProto.TYPE, type); + proto.end(token); + } + + /** * Scale the layout params' coordinates and size. * @hide */ diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 49b7ed8bac0e..66506a18296b 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -16,6 +16,7 @@ package android.view; +import static android.Manifest.permission; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; @@ -77,6 +78,7 @@ import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.util.Slog; +import android.util.proto.ProtoOutputStream; import android.view.animation.Animation; import com.android.internal.policy.IKeyguardDismissCallback; @@ -485,11 +487,17 @@ public interface WindowManagerPolicy { /** * Returns true if the window owner can add internal system windows. - * That is, they have {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW}. + * That is, they have {@link permission#INTERNAL_SYSTEM_WINDOW}. */ default boolean canAddInternalSystemWindow() { return false; } + + /** + * Returns true if the window owner has the permission to acquire a sleep token when it's + * visible. That is, they have the permission {@link permission#DEVICE_POWER}. + */ + boolean canAcquireSleepToken(); } /** @@ -774,7 +782,7 @@ public interface WindowManagerPolicy { * @param type The type of window being assigned. * @param canAddInternalSystemWindow If the owner window associated with the type we are * evaluating can add internal system windows. I.e they have - * {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW}. If true, alert window + * {@link permission#INTERNAL_SYSTEM_WINDOW}. If true, alert window * types {@link android.view.WindowManager.LayoutParams#isSystemAlertWindowType(int)} * can be assigned layers greater than the layer for * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY} Else, their @@ -1646,6 +1654,14 @@ public interface WindowManagerPolicy { public void dump(String prefix, PrintWriter writer, String[] args); /** + * Write the WindowManagerPolicy's state into the protocol buffer. + * The message is described in {@link com.android.server.wm.proto.WindowManagerPolicyProto} + * + * @param proto The protocol buffer output stream to write to. + */ + void writeToProto(ProtoOutputStream proto, long fieldId); + + /** * Returns whether a given window type can be magnified. * * @param windowType The window type. diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java index eaa4b4b3ba08..5adea669314c 100644 --- a/core/java/android/view/accessibility/AccessibilityEvent.java +++ b/core/java/android/view/accessibility/AccessibilityEvent.java @@ -1118,6 +1118,8 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par record.mToIndex = parcel.readInt(); record.mScrollX = parcel.readInt(); record.mScrollY = parcel.readInt(); + record.mScrollDeltaX = parcel.readInt(); + record.mScrollDeltaY = parcel.readInt(); record.mMaxScrollX = parcel.readInt(); record.mMaxScrollY = parcel.readInt(); record.mAddedCount = parcel.readInt(); @@ -1170,6 +1172,8 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par parcel.writeInt(record.mToIndex); parcel.writeInt(record.mScrollX); parcel.writeInt(record.mScrollY); + parcel.writeInt(record.mScrollDeltaX); + parcel.writeInt(record.mScrollDeltaY); parcel.writeInt(record.mMaxScrollX); parcel.writeInt(record.mMaxScrollY); parcel.writeInt(record.mAddedCount); diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index d9128d8014bb..0b9bc5760fa8 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -23,7 +23,6 @@ import android.accessibilityservice.AccessibilityServiceInfo; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SdkConstant; -import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.ComponentName; import android.content.Context; @@ -1113,9 +1112,7 @@ public final class AccessibilityManager { * * @return {@code true} if the accessibility button is supported on this device, * {@code false} otherwise - * @hide */ - @SystemApi public static boolean isAccessibilityButtonSupported() { final Resources res = Resources.getSystem(); return res.getBoolean(com.android.internal.R.bool.config_showNavigationBar); diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index ec6797ccee06..9bdd3ffc9fb2 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -651,7 +651,7 @@ public class AccessibilityNodeInfo implements Parcelable { private static AtomicInteger sNumInstancesInUse; /** - * Gets the accessibility view id which identifies a View in the view tree. + * Gets the accessibility view id which identifies a View in the view three. * * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}. * @return The accessibility view id part of the node id. @@ -743,7 +743,6 @@ public class AccessibilityNodeInfo implements Parcelable { private RangeInfo mRangeInfo; private CollectionInfo mCollectionInfo; private CollectionItemInfo mCollectionItemInfo; - private boolean mRecycled; /** * Hide constructor from clients. @@ -786,7 +785,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @param virtualDescendantId The id of the virtual descendant. */ public void setSource(View root, int virtualDescendantId) { - enforceNotRecycled(); enforceNotSealed(); mWindowId = (root != null) ? root.getAccessibilityWindowId() : UNDEFINED_ITEM_ID; final int rootAccessibilityViewId = @@ -806,7 +804,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @see #FOCUS_ACCESSIBILITY */ public AccessibilityNodeInfo findFocus(int focus) { - enforceNotRecycled(); enforceSealed(); enforceValidFocusType(focus); if (!canPerformRequestOverConnection(mSourceNodeId)) { @@ -831,7 +828,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The node info for the view that can take accessibility focus. */ public AccessibilityNodeInfo focusSearch(int direction) { - enforceNotRecycled(); enforceSealed(); enforceValidFocusDirection(direction); if (!canPerformRequestOverConnection(mSourceNodeId)) { @@ -847,7 +843,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The window id. */ public int getWindowId() { - enforceNotRecycled(); return mWindowId; } @@ -865,7 +860,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @hide */ public boolean refresh(Bundle arguments, boolean bypassCache) { - enforceNotRecycled(); enforceSealed(); if (!canPerformRequestOverConnection(mSourceNodeId)) { return false; @@ -876,6 +870,11 @@ public class AccessibilityNodeInfo implements Parcelable { if (refreshedInfo == null) { return false; } + // Hard-to-reproduce bugs seem to be due to some tools recycling a node on another + // thread. If that happens, the init will re-seal the node, which then is in a bad state + // when it is obtained. Enforce sealing again before we init to fail when a node has been + // recycled during a refresh to catch such errors earlier. + enforceSealed(); init(refreshedInfo); refreshedInfo.recycle(); return true; @@ -929,7 +928,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @hide */ public long getChildId(int index) { - enforceNotRecycled(); if (mChildNodeIds == null) { throw new IndexOutOfBoundsException(); } @@ -942,7 +940,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The child count. */ public int getChildCount() { - enforceNotRecycled(); return mChildNodeIds == null ? 0 : mChildNodeIds.size(); } @@ -961,7 +958,6 @@ public class AccessibilityNodeInfo implements Parcelable { * */ public AccessibilityNodeInfo getChild(int index) { - enforceNotRecycled(); enforceSealed(); if (mChildNodeIds == null) { return null; @@ -1038,7 +1034,6 @@ public class AccessibilityNodeInfo implements Parcelable { } private void addChildInternal(View root, int virtualDescendantId, boolean checked) { - enforceNotRecycled(); enforceNotSealed(); if (mChildNodeIds == null) { mChildNodeIds = new LongArray(); @@ -1064,7 +1059,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @see #addChild(View, int) */ public boolean removeChild(View root, int virtualDescendantId) { - enforceNotRecycled(); enforceNotSealed(); final LongArray childIds = mChildNodeIds; if (childIds == null) { @@ -1085,7 +1079,6 @@ public class AccessibilityNodeInfo implements Parcelable { * Gets the actions that can be performed on the node. */ public List<AccessibilityAction> getActionList() { - enforceNotRecycled(); return CollectionUtils.emptyIfNull(mActions); } @@ -1113,7 +1106,6 @@ public class AccessibilityNodeInfo implements Parcelable { */ @Deprecated public int getActions() { - enforceNotRecycled(); int returnValue = 0; if (mActions == null) { @@ -1152,7 +1144,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @throws IllegalStateException If called from an AccessibilityService. */ public void addAction(AccessibilityAction action) { - enforceNotRecycled(); enforceNotSealed(); addActionUnchecked(action); @@ -1188,7 +1179,6 @@ public class AccessibilityNodeInfo implements Parcelable { */ @Deprecated public void addAction(int action) { - enforceNotRecycled(); enforceNotSealed(); if ((action & ACTION_TYPE_MASK) != 0) { @@ -1215,7 +1205,6 @@ public class AccessibilityNodeInfo implements Parcelable { */ @Deprecated public void removeAction(int action) { - enforceNotRecycled(); enforceNotSealed(); removeAction(getActionSingleton(action)); @@ -1236,7 +1225,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @throws IllegalStateException If called from an AccessibilityService. */ public boolean removeAction(AccessibilityAction action) { - enforceNotRecycled(); enforceNotSealed(); if (mActions == null || action == null) { @@ -1252,7 +1240,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @hide */ public void removeAllActions() { - enforceNotRecycled(); if (mActions != null) { mActions.clear(); } @@ -1268,7 +1255,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @see #setTraversalBefore(android.view.View, int) */ public AccessibilityNodeInfo getTraversalBefore() { - enforceNotRecycled(); enforceSealed(); return getNodeForAccessibilityId(mTraversalBefore); } @@ -1313,7 +1299,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @param virtualDescendantId The id of the virtual descendant. */ public void setTraversalBefore(View root, int virtualDescendantId) { - enforceNotRecycled(); enforceNotSealed(); final int rootAccessibilityViewId = (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID; @@ -1331,7 +1316,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @see #setTraversalAfter(android.view.View, int) */ public AccessibilityNodeInfo getTraversalAfter() { - enforceNotRecycled(); enforceSealed(); return getNodeForAccessibilityId(mTraversalAfter); } @@ -1375,7 +1359,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @param virtualDescendantId The id of the virtual descendant. */ public void setTraversalAfter(View root, int virtualDescendantId) { - enforceNotRecycled(); enforceNotSealed(); final int rootAccessibilityViewId = (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID; @@ -1393,7 +1376,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @see #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY */ public List<String> getAvailableExtraData() { - enforceNotRecycled(); if (mExtraDataKeys != null) { return Collections.unmodifiableList(mExtraDataKeys); } else { @@ -1418,7 +1400,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @throws IllegalStateException If called from an AccessibilityService. */ public void setAvailableExtraData(List<String> extraDataKeys) { - enforceNotRecycled(); enforceNotSealed(); mExtraDataKeys = new ArrayList<>(extraDataKeys); } @@ -1439,7 +1420,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @throws IllegalStateException If called from an AccessibilityService. */ public void setMaxTextLength(int max) { - enforceNotRecycled(); enforceNotSealed(); mMaxTextLength = max; } @@ -1451,7 +1431,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @see #setMaxTextLength(int) */ public int getMaxTextLength() { - enforceNotRecycled(); return mMaxTextLength; } @@ -1468,7 +1447,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @throws IllegalStateException If called from an AccessibilityService. */ public void setMovementGranularities(int granularities) { - enforceNotRecycled(); enforceNotSealed(); mMovementGranularities = granularities; } @@ -1479,7 +1457,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The bit mask with granularities. */ public int getMovementGranularities() { - enforceNotRecycled(); return mMovementGranularities; } @@ -1496,7 +1473,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @throws IllegalStateException If called outside of an AccessibilityService. */ public boolean performAction(int action) { - enforceNotRecycled(); enforceSealed(); if (!canPerformRequestOverConnection(mSourceNodeId)) { return false; @@ -1520,7 +1496,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @throws IllegalStateException If called outside of an AccessibilityService. */ public boolean performAction(int action, Bundle arguments) { - enforceNotRecycled(); enforceSealed(); if (!canPerformRequestOverConnection(mSourceNodeId)) { return false; @@ -1545,7 +1520,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return A list of node info. */ public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text) { - enforceNotRecycled(); enforceSealed(); if (!canPerformRequestOverConnection(mSourceNodeId)) { return Collections.emptyList(); @@ -1577,7 +1551,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return A list of node info. */ public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId(String viewId) { - enforceNotRecycled(); enforceSealed(); if (!canPerformRequestOverConnection(mSourceNodeId)) { return Collections.emptyList(); @@ -1595,7 +1568,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @see android.accessibilityservice.AccessibilityService#getWindows() */ public AccessibilityWindowInfo getWindow() { - enforceNotRecycled(); enforceSealed(); if (!canPerformRequestOverConnection(mSourceNodeId)) { return null; @@ -1615,7 +1587,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The parent. */ public AccessibilityNodeInfo getParent() { - enforceNotRecycled(); enforceSealed(); return getNodeForAccessibilityId(mParentNodeId); } @@ -1665,7 +1636,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @param virtualDescendantId The id of the virtual descendant. */ public void setParent(View root, int virtualDescendantId) { - enforceNotRecycled(); enforceNotSealed(); final int rootAccessibilityViewId = (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID; @@ -1678,7 +1648,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @param outBounds The output node bounds. */ public void getBoundsInParent(Rect outBounds) { - enforceNotRecycled(); outBounds.set(mBoundsInParent.left, mBoundsInParent.top, mBoundsInParent.right, mBoundsInParent.bottom); } @@ -1696,7 +1665,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @throws IllegalStateException If called from an AccessibilityService. */ public void setBoundsInParent(Rect bounds) { - enforceNotRecycled(); enforceNotSealed(); mBoundsInParent.set(bounds.left, bounds.top, bounds.right, bounds.bottom); } @@ -1707,7 +1675,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @param outBounds The output node bounds. */ public void getBoundsInScreen(Rect outBounds) { - enforceNotRecycled(); outBounds.set(mBoundsInScreen.left, mBoundsInScreen.top, mBoundsInScreen.right, mBoundsInScreen.bottom); } @@ -1718,7 +1685,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @hide Not safe to expose outside the framework. */ public Rect getBoundsInScreen() { - enforceNotRecycled(); return mBoundsInScreen; } @@ -1735,7 +1701,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @throws IllegalStateException If called from an AccessibilityService. */ public void setBoundsInScreen(Rect bounds) { - enforceNotRecycled(); enforceNotSealed(); mBoundsInScreen.set(bounds.left, bounds.top, bounds.right, bounds.bottom); } @@ -2077,7 +2042,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The drawing position of the view corresponding to this node relative to its siblings. */ public int getDrawingOrder() { - enforceNotRecycled(); return mDrawingOrderInParent; } @@ -2093,7 +2057,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @throws IllegalStateException If called from an AccessibilityService. */ public void setDrawingOrder(int drawingOrderInParent) { - enforceNotRecycled(); enforceNotSealed(); mDrawingOrderInParent = drawingOrderInParent; } @@ -2105,7 +2068,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The collection info. */ public CollectionInfo getCollectionInfo() { - enforceNotRecycled(); return mCollectionInfo; } @@ -2121,7 +2083,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @param collectionInfo The collection info. */ public void setCollectionInfo(CollectionInfo collectionInfo) { - enforceNotRecycled(); enforceNotSealed(); mCollectionInfo = collectionInfo; } @@ -2133,7 +2094,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The collection item info. */ public CollectionItemInfo getCollectionItemInfo() { - enforceNotRecycled(); return mCollectionItemInfo; } @@ -2147,7 +2107,6 @@ public class AccessibilityNodeInfo implements Parcelable { * </p> */ public void setCollectionItemInfo(CollectionItemInfo collectionItemInfo) { - enforceNotRecycled(); enforceNotSealed(); mCollectionItemInfo = collectionItemInfo; } @@ -2158,7 +2117,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The range. */ public RangeInfo getRangeInfo() { - enforceNotRecycled(); return mRangeInfo; } @@ -2173,7 +2131,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @param rangeInfo The range info. */ public void setRangeInfo(RangeInfo rangeInfo) { - enforceNotRecycled(); enforceNotSealed(); mRangeInfo = rangeInfo; } @@ -2246,7 +2203,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @see android.view.View#getAccessibilityLiveRegion() */ public int getLiveRegion() { - enforceNotRecycled(); return mLiveRegion; } @@ -2263,7 +2219,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @see android.view.View#setAccessibilityLiveRegion(int) */ public void setLiveRegion(int mode) { - enforceNotRecycled(); enforceNotSealed(); mLiveRegion = mode; } @@ -2311,6 +2266,7 @@ public class AccessibilityNodeInfo implements Parcelable { * @param opensPopup If the the node opens a popup. */ public void setCanOpenPopup(boolean opensPopup) { + enforceNotSealed(); setBooleanProperty(BOOLEAN_PROPERTY_OPENS_POPUP, opensPopup); } @@ -2397,7 +2353,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The package name. */ public CharSequence getPackageName() { - enforceNotRecycled(); return mPackageName; } @@ -2414,7 +2369,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @throws IllegalStateException If called from an AccessibilityService. */ public void setPackageName(CharSequence packageName) { - enforceNotRecycled(); enforceNotSealed(); mPackageName = packageName; } @@ -2425,7 +2379,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The class name. */ public CharSequence getClassName() { - enforceNotRecycled(); return mClassName; } @@ -2442,7 +2395,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @throws IllegalStateException If called from an AccessibilityService. */ public void setClassName(CharSequence className) { - enforceNotRecycled(); enforceNotSealed(); mClassName = className; } @@ -2466,7 +2418,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The text. */ public CharSequence getText() { - enforceNotRecycled(); // Attach this node to any spans that need it if (mText instanceof Spanned) { Spanned spanned = (Spanned) mText; @@ -2489,7 +2440,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @hide */ public CharSequence getOriginalText() { - enforceNotRecycled(); return mOriginalText; } @@ -2506,7 +2456,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @throws IllegalStateException If called from an AccessibilityService. */ public void setText(CharSequence text) { - enforceNotRecycled(); enforceNotSealed(); mOriginalText = text; // Replace any ClickableSpans in mText with placeholders @@ -2545,7 +2494,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The hint text. */ public CharSequence getHintText() { - enforceNotRecycled(); return mHintText; } @@ -2562,7 +2510,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @throws IllegalStateException If called from an AccessibilityService. */ public void setHintText(CharSequence hintText) { - enforceNotRecycled(); enforceNotSealed(); mHintText = (hintText == null) ? null : hintText.subSequence(0, hintText.length()); } @@ -2580,7 +2527,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @throws IllegalStateException If called from an AccessibilityService. */ public void setError(CharSequence error) { - enforceNotRecycled(); enforceNotSealed(); mError = (error == null) ? null : error.subSequence(0, error.length()); } @@ -2591,7 +2537,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The error text. */ public CharSequence getError() { - enforceNotRecycled(); return mError; } @@ -2601,7 +2546,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The content description. */ public CharSequence getContentDescription() { - enforceNotRecycled(); return mContentDescription; } @@ -2618,7 +2562,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @throws IllegalStateException If called from an AccessibilityService. */ public void setContentDescription(CharSequence contentDescription) { - enforceNotRecycled(); enforceNotSealed(); mContentDescription = (contentDescription == null) ? null : contentDescription.subSequence(0, contentDescription.length()); @@ -2631,7 +2574,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @param labeled The view for which this info serves as a label. */ public void setLabelFor(View labeled) { - enforceNotRecycled(); setLabelFor(labeled, AccessibilityNodeProvider.HOST_VIEW_ID); } @@ -2655,7 +2597,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @param virtualDescendantId The id of the virtual descendant. */ public void setLabelFor(View root, int virtualDescendantId) { - enforceNotRecycled(); enforceNotSealed(); final int rootAccessibilityViewId = (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID; @@ -2674,7 +2615,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The labeled info. */ public AccessibilityNodeInfo getLabelFor() { - enforceNotRecycled(); enforceSealed(); return getNodeForAccessibilityId(mLabelForId); } @@ -2709,7 +2649,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @param virtualDescendantId The id of the virtual descendant. */ public void setLabeledBy(View root, int virtualDescendantId) { - enforceNotRecycled(); enforceNotSealed(); final int rootAccessibilityViewId = (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID; @@ -2728,7 +2667,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The label. */ public AccessibilityNodeInfo getLabeledBy() { - enforceNotRecycled(); enforceSealed(); return getNodeForAccessibilityId(mLabeledById); } @@ -2745,7 +2683,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @param viewIdResName The id resource name. */ public void setViewIdResourceName(String viewIdResName) { - enforceNotRecycled(); enforceNotSealed(); mViewIdResourceName = viewIdResName; } @@ -2763,7 +2700,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The id resource name. */ public String getViewIdResourceName() { - enforceNotRecycled(); return mViewIdResourceName; } @@ -2779,7 +2715,6 @@ public class AccessibilityNodeInfo implements Parcelable { * there is no text selection and no cursor. */ public int getTextSelectionStart() { - enforceNotRecycled(); return mTextSelectionStart; } @@ -2795,7 +2730,6 @@ public class AccessibilityNodeInfo implements Parcelable { * there is no text selection and no cursor. */ public int getTextSelectionEnd() { - enforceNotRecycled(); return mTextSelectionEnd; } @@ -2813,7 +2747,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @throws IllegalStateException If called from an AccessibilityService. */ public void setTextSelection(int start, int end) { - enforceNotRecycled(); enforceNotSealed(); mTextSelectionStart = start; mTextSelectionEnd = end; @@ -2825,7 +2758,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The input type. */ public int getInputType() { - enforceNotRecycled(); return mInputType; } @@ -2843,7 +2775,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @throws IllegalStateException If called from an AccessibilityService. */ public void setInputType(int inputType) { - enforceNotRecycled(); enforceNotSealed(); mInputType = inputType; } @@ -2862,7 +2793,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The bundle. */ public Bundle getExtras() { - enforceNotRecycled(); if (mExtras == null) { mExtras = new Bundle(); } @@ -2884,7 +2814,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @return The value. */ private boolean getBooleanProperty(int property) { - enforceNotRecycled(); return (mBooleanProperties & property) != 0; } @@ -2897,7 +2826,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @throws IllegalStateException If called from an AccessibilityService. */ private void setBooleanProperty(int property, boolean value) { - enforceNotRecycled(); enforceNotSealed(); if (value) { mBooleanProperties |= property; @@ -2927,7 +2855,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @hide */ public int getConnectionId() { - enforceNotRecycled(); return mConnectionId; } @@ -2948,7 +2875,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @hide */ public void setSourceNodeId(long sourceId, int windowId) { - enforceNotRecycled(); enforceNotSealed(); mSourceNodeId = sourceId; mWindowId = windowId; @@ -2962,7 +2888,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @hide */ public long getSourceNodeId() { - enforceNotRecycled(); return mSourceNodeId; } @@ -2974,7 +2899,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @hide */ public void setSealed(boolean sealed) { - enforceNotRecycled(); mSealed = sealed; } @@ -3041,11 +2965,6 @@ public class AccessibilityNodeInfo implements Parcelable { } } - private void enforceNotRecycled() { - if (mRecycled) { - throw new IllegalStateException("Cannot interact with recycled instance"); - } - } /** * Returns a cached instance if such is available otherwise a new one * and sets the source. @@ -3087,11 +3006,7 @@ public class AccessibilityNodeInfo implements Parcelable { if (sNumInstancesInUse != null) { sNumInstancesInUse.incrementAndGet(); } - if (info != null) { - info.mRecycled = false; - return info; - } - return new AccessibilityNodeInfo(); + return (info != null) ? info : new AccessibilityNodeInfo(); } /** @@ -3117,7 +3032,6 @@ public class AccessibilityNodeInfo implements Parcelable { */ public void recycle() { clear(); - mRecycled = true; sPool.release(this); if (sNumInstancesInUse != null) { sNumInstancesInUse.decrementAndGet(); @@ -3143,7 +3057,6 @@ public class AccessibilityNodeInfo implements Parcelable { */ @Override public void writeToParcel(Parcel parcel, int flags) { - enforceNotRecycled(); // Write bit set of indices of fields with values differing from default long nonDefaultFields = 0; int fieldIndex = 0; // index of the current field @@ -3378,7 +3291,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @param other The other instance. */ private void init(AccessibilityNodeInfo other) { - enforceNotRecycled(); mSealed = other.mSealed; mSourceNodeId = other.mSourceNodeId; mParentNodeId = other.mParentNodeId; @@ -3450,7 +3362,6 @@ public class AccessibilityNodeInfo implements Parcelable { * @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}. */ private void initFromParcel(Parcel parcel) { - enforceNotRecycled(); // Bit mask of non-default-valued field indices long nonDefaultFields = parcel.readLong(); int fieldIndex = 0; diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java index 02b618503250..fa505c97ba48 100644 --- a/core/java/android/view/accessibility/AccessibilityRecord.java +++ b/core/java/android/view/accessibility/AccessibilityRecord.java @@ -86,6 +86,9 @@ public class AccessibilityRecord { int mToIndex = UNDEFINED; int mScrollX = UNDEFINED; int mScrollY = UNDEFINED; + + int mScrollDeltaX = UNDEFINED; + int mScrollDeltaY = UNDEFINED; int mMaxScrollX = UNDEFINED; int mMaxScrollY = UNDEFINED; @@ -465,6 +468,48 @@ public class AccessibilityRecord { } /** + * Gets the difference in pixels between the horizontal position before the scroll and the + * current horizontal position + * + * @return the scroll delta x + */ + public int getScrollDeltaX() { + return mScrollDeltaX; + } + + /** + * Sets the difference in pixels between the horizontal position before the scroll and the + * current horizontal position + * + * @param scrollDeltaX the scroll delta x + */ + public void setScrollDeltaX(int scrollDeltaX) { + enforceNotSealed(); + mScrollDeltaX = scrollDeltaX; + } + + /** + * Gets the difference in pixels between the vertical position before the scroll and the + * current vertical position + * + * @return the scroll delta y + */ + public int getScrollDeltaY() { + return mScrollDeltaY; + } + + /** + * Sets the difference in pixels between the vertical position before the scroll and the + * current vertical position + * + * @param scrollDeltaY the scroll delta y + */ + public void setScrollDeltaY(int scrollDeltaY) { + enforceNotSealed(); + mScrollDeltaY = scrollDeltaY; + } + + /** * Gets the max scroll offset of the source left edge in pixels. * * @return The max scroll. diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 29e5523ceb7c..61cbce976844 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -30,12 +30,14 @@ import android.content.IntentSender; import android.graphics.Rect; import android.metrics.LogMaker; import android.os.Bundle; +import android.os.IBinder; import android.os.Parcelable; import android.os.RemoteException; import android.service.autofill.AutofillService; import android.service.autofill.FillEventHistory; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.DebugUtils; import android.util.Log; import android.util.SparseArray; import android.view.View; @@ -44,6 +46,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; +import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; @@ -154,8 +157,15 @@ public final class AutofillManager { public static final String EXTRA_CLIENT_STATE = "android.view.autofill.extra.CLIENT_STATE"; - static final String SESSION_ID_TAG = "android:sessionId"; - static final String LAST_AUTOFILLED_DATA_TAG = "android:lastAutoFilledData"; + + /** @hide */ + public static final String EXTRA_RESTORE_SESSION_TOKEN = + "android.view.autofill.extra.RESTORE_SESSION_TOKEN"; + + private static final String SESSION_ID_TAG = "android:sessionId"; + private static final String STATE_TAG = "android:state"; + private static final String LAST_AUTOFILLED_DATA_TAG = "android:lastAutoFilledData"; + /** @hide */ public static final int ACTION_START_SESSION = 1; /** @hide */ public static final int ACTION_VIEW_ENTERED = 2; @@ -175,6 +185,44 @@ public final class AutofillManager { public static final int AUTHENTICATION_ID_DATASET_ID_UNDEFINED = 0xFFFF; /** + * Used on {@link #onPendingSaveUi(int, IBinder)} to cancel the pending UI. + * + * @hide + */ + public static final int PENDING_UI_OPERATION_CANCEL = 1; + + /** + * Used on {@link #onPendingSaveUi(int, IBinder)} to restore the pending UI. + * + * @hide + */ + public static final int PENDING_UI_OPERATION_RESTORE = 2; + + /** + * Initial state of the autofill context, set when there is no session (i.e., when + * {@link #mSessionId} is {@link #NO_SESSION}). + * + * @hide + */ + public static final int STATE_UNKNOWN = 1; + + /** + * State where the autofill context hasn't been {@link #commit() finished} nor + * {@link #cancel() canceled} yet. + * + * @hide + */ + public static final int STATE_ACTIVE = 2; + + /** + * State where the autofill context has been {@link #commit() finished} but the server still has + * a session because the Save UI hasn't been dismissed yet. + * + * @hide + */ + public static final int STATE_SHOWING_SAVE_UI = 4; + + /** * Makes an authentication id from a request id and a dataset id. * * @param requestId The request id. @@ -233,6 +281,9 @@ public final class AutofillManager { private int mSessionId = NO_SESSION; @GuardedBy("mLock") + private int mState = STATE_UNKNOWN; + + @GuardedBy("mLock") private boolean mEnabled; /** If a view changes to this mapping the autofill operation was successful */ @@ -344,12 +395,13 @@ public final class AutofillManager { synchronized (mLock) { mLastAutofilledData = savedInstanceState.getParcelable(LAST_AUTOFILLED_DATA_TAG); - if (mSessionId != NO_SESSION) { + if (isActiveLocked()) { Log.w(TAG, "New session was started before onCreate()"); return; } mSessionId = savedInstanceState.getInt(SESSION_ID_TAG, NO_SESSION); + mState = savedInstanceState.getInt(STATE_TAG, STATE_UNKNOWN); if (mSessionId != NO_SESSION) { ensureServiceClientAddedIfNeededLocked(); @@ -363,6 +415,7 @@ public final class AutofillManager { if (!sessionWasRestored) { Log.w(TAG, "Session " + mSessionId + " could not be restored"); mSessionId = NO_SESSION; + mState = STATE_UNKNOWN; } else { if (sDebug) { Log.d(TAG, "session " + mSessionId + " was restored"); @@ -387,7 +440,7 @@ public final class AutofillManager { */ public void onVisibleForAutofill() { synchronized (mLock) { - if (mEnabled && mSessionId != NO_SESSION && mTrackedViews != null) { + if (mEnabled && isActiveLocked() && mTrackedViews != null) { mTrackedViews.onVisibleForAutofillLocked(); } } @@ -408,7 +461,9 @@ public final class AutofillManager { if (mSessionId != NO_SESSION) { outState.putInt(SESSION_ID_TAG, mSessionId); } - + if (mState != STATE_UNKNOWN) { + outState.putInt(STATE_TAG, mState); + } if (mLastAutofilledData != null) { outState.putParcelable(LAST_AUTOFILLED_DATA_TAG, mLastAutofilledData); } @@ -514,7 +569,7 @@ public final class AutofillManager { final AutofillId id = getAutofillId(view); final AutofillValue value = view.getAutofillValue(); - if (mSessionId == NO_SESSION) { + if (!isActiveLocked()) { // Starts new session. startSessionLocked(id, null, value, flags); } else { @@ -541,7 +596,7 @@ public final class AutofillManager { synchronized (mLock) { ensureServiceClientAddedIfNeededLocked(); - if (mEnabled && mSessionId != NO_SESSION) { + if (mEnabled && isActiveLocked()) { final AutofillId id = getAutofillId(view); // Update focus on existing session. @@ -582,7 +637,7 @@ public final class AutofillManager { private void notifyViewVisibilityChangedInternal(@NonNull View view, int virtualId, boolean isVisible, boolean virtual) { synchronized (mLock) { - if (mEnabled && mSessionId != NO_SESSION) { + if (mEnabled && isActiveLocked()) { final AutofillId id = virtual ? getAutofillId(view, virtualId) : view.getAutofillId(); if (!isVisible && mFillableIds != null) { @@ -636,7 +691,7 @@ public final class AutofillManager { } else { final AutofillId id = getAutofillId(view, virtualId); - if (mSessionId == NO_SESSION) { + if (!isActiveLocked()) { // Starts new session. startSessionLocked(id, bounds, null, flags); } else { @@ -665,7 +720,7 @@ public final class AutofillManager { synchronized (mLock) { ensureServiceClientAddedIfNeededLocked(); - if (mEnabled && mSessionId != NO_SESSION) { + if (mEnabled && isActiveLocked()) { final AutofillId id = getAutofillId(view, virtualId); // Update focus on existing session. @@ -709,7 +764,7 @@ public final class AutofillManager { } } - if (!mEnabled || mSessionId == NO_SESSION) { + if (!mEnabled || !isActiveLocked()) { return; } @@ -737,7 +792,7 @@ public final class AutofillManager { return; } synchronized (mLock) { - if (!mEnabled || mSessionId == NO_SESSION) { + if (!mEnabled || !isActiveLocked()) { return; } @@ -762,7 +817,7 @@ public final class AutofillManager { return; } synchronized (mLock) { - if (!mEnabled && mSessionId == NO_SESSION) { + if (!mEnabled && !isActiveLocked()) { return; } @@ -786,7 +841,7 @@ public final class AutofillManager { return; } synchronized (mLock) { - if (!mEnabled && mSessionId == NO_SESSION) { + if (!mEnabled && !isActiveLocked()) { return; } @@ -868,7 +923,7 @@ public final class AutofillManager { if (sDebug) Log.d(TAG, "onAuthenticationResult(): d=" + data); synchronized (mLock) { - if (mSessionId == NO_SESSION || data == null) { + if (!isActiveLocked() || data == null) { return; } final Parcelable result = data.getParcelableExtra(EXTRA_AUTHENTICATION_RESULT); @@ -895,13 +950,19 @@ public final class AutofillManager { @NonNull AutofillValue value, int flags) { if (sVerbose) { Log.v(TAG, "startSessionLocked(): id=" + id + ", bounds=" + bounds + ", value=" + value - + ", flags=" + flags); + + ", flags=" + flags + ", state=" + mState); + } + if (mState != STATE_UNKNOWN) { + if (sDebug) Log.d(TAG, "not starting session for " + id + " on state " + mState); + return; } - try { mSessionId = mService.startSession(mContext.getActivityToken(), mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(), mCallback != null, flags, mContext.getOpPackageName()); + if (mSessionId != NO_SESSION) { + mState = STATE_ACTIVE; + } final AutofillClient client = getClientLocked(); if (client != null) { client.autofillCallbackResetableStateAvailable(); @@ -912,7 +973,9 @@ public final class AutofillManager { } private void finishSessionLocked() { - if (sVerbose) Log.v(TAG, "finishSessionLocked()"); + if (sVerbose) Log.v(TAG, "finishSessionLocked(): " + mState); + + if (!isActiveLocked()) return; try { mService.finishSession(mSessionId, mContext.getUserId()); @@ -920,12 +983,13 @@ public final class AutofillManager { throw e.rethrowFromSystemServer(); } - mTrackedViews = null; - mSessionId = NO_SESSION; + resetSessionLocked(); } private void cancelSessionLocked() { - if (sVerbose) Log.v(TAG, "cancelSessionLocked()"); + if (sVerbose) Log.v(TAG, "cancelSessionLocked(): " + mState); + + if (!isActiveLocked()) return; try { mService.cancelSession(mSessionId, mContext.getUserId()); @@ -938,7 +1002,9 @@ public final class AutofillManager { private void resetSessionLocked() { mSessionId = NO_SESSION; + mState = STATE_UNKNOWN; mTrackedViews = null; + mFillableIds = null; } private void updateSessionLocked(AutofillId id, Rect bounds, AutofillValue value, int action, @@ -947,7 +1013,6 @@ public final class AutofillManager { Log.v(TAG, "updateSessionLocked(): id=" + id + ", bounds=" + bounds + ", value=" + value + ", action=" + action + ", flags=" + flags); } - boolean restartIfNecessary = (flags & FLAG_MANUAL_REQUEST) != 0; try { @@ -958,6 +1023,7 @@ public final class AutofillManager { if (newId != mSessionId) { if (sDebug) Log.d(TAG, "Session restarted: " + mSessionId + "=>" + newId); mSessionId = newId; + mState = (mSessionId == NO_SESSION) ? STATE_UNKNOWN : STATE_ACTIVE; final AutofillClient client = getClientLocked(); if (client != null) { client.autofillCallbackResetableStateAvailable(); @@ -1219,6 +1285,27 @@ public final class AutofillManager { } } + private void setSaveUiState(int sessionId, boolean shown) { + if (sDebug) Log.d(TAG, "setSaveUiState(" + sessionId + "): " + shown); + synchronized (mLock) { + if (mSessionId != NO_SESSION) { + // Race condition: app triggered a new session after the previous session was + // finished but before server called setSaveUiState() - need to cancel the new + // session to avoid further inconsistent behavior. + Log.w(TAG, "setSaveUiState(" + sessionId + ", " + shown + + ") called on existing session " + mSessionId + "; cancelling it"); + cancelSessionLocked(); + } + if (shown) { + mSessionId = sessionId; + mState = STATE_SHOWING_SAVE_UI; + } else { + mSessionId = NO_SESSION; + mState = STATE_UNKNOWN; + } + } + } + private void requestHideFillUi(AutofillId id) { final View anchor = findView(id); if (sVerbose) Log.v(TAG, "requestHideFillUi(" + id + "): anchor = " + anchor); @@ -1329,6 +1416,46 @@ public final class AutofillManager { return mService != null; } + /** @hide */ + public void onPendingSaveUi(int operation, IBinder token) { + if (sVerbose) Log.v(TAG, "onPendingSaveUi(" + operation + "): " + token); + + synchronized (mLock) { + try { + mService.onPendingSaveUi(operation, token); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + } + + /** @hide */ + public void dump(String outerPrefix, PrintWriter pw) { + pw.print(outerPrefix); pw.println("AutofillManager:"); + final String pfx = outerPrefix + " "; + pw.print(pfx); pw.print("sessionId: "); pw.println(mSessionId); + pw.print(pfx); pw.print("state: "); pw.println( + DebugUtils.flagsToString(AutofillManager.class, "STATE_", mState)); + pw.print(pfx); pw.print("enabled: "); pw.println(mEnabled); + pw.print(pfx); pw.print("hasService: "); pw.println(mService != null); + pw.print(pfx); pw.print("hasCallback: "); pw.println(mCallback != null); + pw.print(pfx); pw.print("last autofilled data: "); pw.println(mLastAutofilledData); + pw.print(pfx); pw.print("tracked views: "); + if (mTrackedViews == null) { + pw.println("null"); + } else { + final String pfx2 = pfx + " "; + pw.println(); + pw.print(pfx2); pw.print("visible:"); pw.println(mTrackedViews.mVisibleTrackedIds); + pw.print(pfx2); pw.print("invisible:"); pw.println(mTrackedViews.mInvisibleTrackedIds); + } + pw.print(pfx); pw.print("fillable ids: "); pw.println(mFillableIds); + } + + private boolean isActiveLocked() { + return mState == STATE_ACTIVE; + } + private void post(Runnable runnable) { final AutofillClient client = getClientLocked(); if (client == null) { @@ -1668,12 +1795,12 @@ public final class AutofillManager { } @Override - public void startIntentSender(IntentSender intentSender) { + public void startIntentSender(IntentSender intentSender, Intent intent) { final AutofillManager afm = mAfm.get(); if (afm != null) { afm.post(() -> { try { - afm.mContext.startIntentSender(intentSender, null, 0, 0, 0); + afm.mContext.startIntentSender(intentSender, intent, 0, 0, 0); } catch (IntentSender.SendIntentException e) { Log.e(TAG, "startIntentSender() failed for intent:" + intentSender, e); } @@ -1691,5 +1818,13 @@ public final class AutofillManager { ); } } + + @Override + public void setSaveUiState(int sessionId, boolean shown) { + final AutofillManager afm = mAfm.get(); + if (afm != null) { + afm.post(() ->afm.setSaveUiState(sessionId, shown)); + } + } } } diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl index 627afa7f8364..6bd9bec368c8 100644 --- a/core/java/android/view/autofill/IAutoFillManager.aidl +++ b/core/java/android/view/autofill/IAutoFillManager.aidl @@ -49,4 +49,5 @@ interface IAutoFillManager { void disableOwnedAutofillServices(int userId); boolean isServiceSupported(int userId); boolean isServiceEnabled(int userId, String packageName); + void onPendingSaveUi(int operation, IBinder token); } diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl index d18b1816e09e..0eae85860383 100644 --- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl +++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl @@ -72,7 +72,12 @@ oneway interface IAutoFillManagerClient { void notifyNoFillUi(int sessionId, in AutofillId id); /** - * Starts the provided intent sender + * Starts the provided intent sender. */ - void startIntentSender(in IntentSender intentSender); + void startIntentSender(in IntentSender intentSender, in Intent intent); + + /** + * Sets the state of the Autofill Save UI for a given session. + */ + void setSaveUiState(int sessionId, boolean shown); } diff --git a/core/java/android/view/textclassifier/TextClassification.java b/core/java/android/view/textclassifier/TextClassification.java index d1e0ae5917f4..fa7b9a59c669 100644 --- a/core/java/android/view/textclassifier/TextClassification.java +++ b/core/java/android/view/textclassifier/TextClassification.java @@ -48,6 +48,7 @@ public final class TextClassification { @NonNull private final EntityConfidence<String> mEntityConfidence; @NonNull private final List<String> mEntities; private int mLogType; + @NonNull private final String mVersionInfo; private TextClassification( @Nullable String text, @@ -56,7 +57,8 @@ public final class TextClassification { @Nullable Intent intent, @Nullable OnClickListener onClickListener, @NonNull EntityConfidence<String> entityConfidence, - int logType) { + int logType, + @NonNull String versionInfo) { mText = text; mIcon = icon; mLabel = label; @@ -65,6 +67,7 @@ public final class TextClassification { mEntityConfidence = new EntityConfidence<>(entityConfidence); mEntities = mEntityConfidence.getEntities(); mLogType = logType; + mVersionInfo = versionInfo; } /** @@ -145,6 +148,15 @@ public final class TextClassification { return mLogType; } + /** + * Returns information about the classifier model used to generate this TextClassification. + * @hide + */ + @NonNull + public String getVersionInfo() { + return mVersionInfo; + } + @Override public String toString() { return String.format("TextClassification {" @@ -179,6 +191,7 @@ public final class TextClassification { @NonNull private final EntityConfidence<String> mEntityConfidence = new EntityConfidence<>(); private int mLogType; + @NonNull private String mVersionInfo = ""; /** * Sets the classified text. @@ -244,11 +257,21 @@ public final class TextClassification { } /** + * Sets information about the classifier model used to generate this TextClassification. + * @hide + */ + Builder setVersionInfo(@NonNull String versionInfo) { + mVersionInfo = Preconditions.checkNotNull(mVersionInfo); + return this; + } + + /** * Builds and returns a {@link TextClassification} object. */ public TextClassification build() { return new TextClassification( - mText, mIcon, mLabel, mIntent, mOnClickListener, mEntityConfidence, mLogType); + mText, mIcon, mLabel, mIntent, mOnClickListener, mEntityConfidence, + mLogType, mVersionInfo); } } } diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java index ab1d034bb916..bb1e693fbf43 100644 --- a/core/java/android/view/textclassifier/TextClassifier.java +++ b/core/java/android/view/textclassifier/TextClassifier.java @@ -34,6 +34,11 @@ import java.lang.annotation.RetentionPolicy; */ public interface TextClassifier { + /** @hide */ + String DEFAULT_LOG_TAG = "TextClassifierImpl"; + + /** @hide */ + String TYPE_UNKNOWN = ""; // TODO: Make this public API. String TYPE_OTHER = "other"; String TYPE_EMAIL = "email"; String TYPE_PHONE = "phone"; @@ -43,7 +48,7 @@ public interface TextClassifier { /** @hide */ @Retention(RetentionPolicy.SOURCE) @StringDef({ - TYPE_OTHER, TYPE_EMAIL, TYPE_PHONE, TYPE_ADDRESS, TYPE_URL + TYPE_UNKNOWN, TYPE_OTHER, TYPE_EMAIL, TYPE_PHONE, TYPE_ADDRESS, TYPE_URL }) @interface EntityType {} diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java index 290d811d01ac..7e93b78c4809 100644 --- a/core/java/android/view/textclassifier/TextClassifierImpl.java +++ b/core/java/android/view/textclassifier/TextClassifierImpl.java @@ -70,7 +70,7 @@ import java.util.regex.Pattern; */ final class TextClassifierImpl implements TextClassifier { - private static final String LOG_TAG = "TextClassifierImpl"; + private static final String LOG_TAG = DEFAULT_LOG_TAG; private static final String MODEL_DIR = "/etc/textclassifier/"; private static final String MODEL_FILE_REGEX = "textclassifier\\.smartselection\\.(.*)\\.model"; private static final String UPDATED_MODEL_FILE_PATH = @@ -86,6 +86,8 @@ final class TextClassifierImpl implements TextClassifier { @GuardedBy("mSmartSelectionLock") // Do not access outside this lock. private Locale mLocale; @GuardedBy("mSmartSelectionLock") // Do not access outside this lock. + private int mVersion; + @GuardedBy("mSmartSelectionLock") // Do not access outside this lock. private SmartSelection mSmartSelection; TextClassifierImpl(Context context) { @@ -108,8 +110,7 @@ final class TextClassifierImpl implements TextClassifier { if (start <= end && start >= 0 && end <= string.length() && start <= selectionStartIndex && end >= selectionEndIndex) { - final TextSelection.Builder tsBuilder = new TextSelection.Builder(start, end) - .setLogSource(LOG_TAG); + final TextSelection.Builder tsBuilder = new TextSelection.Builder(start, end); final SmartSelection.ClassificationResult[] results = smartSelection.classifyText( string, start, end, @@ -118,7 +119,10 @@ final class TextClassifierImpl implements TextClassifier { for (int i = 0; i < size; i++) { tsBuilder.setEntityType(results[i].mCollection, results[i].mScore); } - return tsBuilder.build(); + return tsBuilder + .setLogSource(LOG_TAG) + .setVersionInfo(getVersionInfo()) + .build(); } else { // We can not trust the result. Log the issue and ignore the result. Log.d(LOG_TAG, "Got bad indices for input text. Ignoring result."); @@ -202,6 +206,16 @@ final class TextClassifierImpl implements TextClassifier { } } + @NonNull + private String getVersionInfo() { + synchronized (mSmartSelectionLock) { + if (mLocale != null) { + return String.format("%s_v%d", mLocale.toLanguageTag(), mVersion); + } + return ""; + } + } + @GuardedBy("mSmartSelectionLock") // Do not call outside this lock. private ParcelFileDescriptor getFdLocked(Locale locale) throws FileNotFoundException { ParcelFileDescriptor updateFd; @@ -256,9 +270,11 @@ final class TextClassifierImpl implements TextClassifier { final int factoryVersion = SmartSelection.getVersion(factoryFd.getFd()); if (updateVersion > factoryVersion) { closeAndLogError(factoryFd); + mVersion = updateVersion; return updateFd; } else { closeAndLogError(updateFd); + mVersion = factoryVersion; return factoryFd; } } @@ -374,7 +390,7 @@ final class TextClassifierImpl implements TextClassifier { builder.setLabel(label != null ? label.toString() : null); } } - return builder.build(); + return builder.setVersionInfo(getVersionInfo()).build(); } private static int getHintFlags(CharSequence text, int start, int end) { diff --git a/core/java/android/view/textclassifier/TextSelection.java b/core/java/android/view/textclassifier/TextSelection.java index 9a66693a93fa..085dd32966b0 100644 --- a/core/java/android/view/textclassifier/TextSelection.java +++ b/core/java/android/view/textclassifier/TextSelection.java @@ -35,15 +35,17 @@ public final class TextSelection { @NonNull private final EntityConfidence<String> mEntityConfidence; @NonNull private final List<String> mEntities; @NonNull private final String mLogSource; + @NonNull private final String mVersionInfo; private TextSelection( int startIndex, int endIndex, @NonNull EntityConfidence<String> entityConfidence, - @NonNull String logSource) { + @NonNull String logSource, @NonNull String versionInfo) { mStartIndex = startIndex; mEndIndex = endIndex; mEntityConfidence = new EntityConfidence<>(entityConfidence); mEntities = mEntityConfidence.getEntities(); mLogSource = logSource; + mVersionInfo = versionInfo; } /** @@ -94,10 +96,20 @@ public final class TextSelection { * Returns a tag for the source classifier used to generate this result. * @hide */ + @NonNull public String getSourceClassifier() { return mLogSource; } + /** + * Returns information about the classifier model used to generate this TextSelection. + * @hide + */ + @NonNull + public String getVersionInfo() { + return mVersionInfo; + } + @Override public String toString() { return String.format("TextSelection {%d, %d, %s}", @@ -114,6 +126,7 @@ public final class TextSelection { @NonNull private final EntityConfidence<String> mEntityConfidence = new EntityConfidence<>(); @NonNull private String mLogSource = ""; + @NonNull private String mVersionInfo = ""; /** * Creates a builder used to build {@link TextSelection} objects. @@ -152,10 +165,20 @@ public final class TextSelection { } /** + * Sets information about the classifier model used to generate this TextSelection. + * @hide + */ + Builder setVersionInfo(@NonNull String versionInfo) { + mVersionInfo = Preconditions.checkNotNull(mVersionInfo); + return this; + } + + /** * Builds and returns {@link TextSelection} object. */ public TextSelection build() { - return new TextSelection(mStartIndex, mEndIndex, mEntityConfidence, mLogSource); + return new TextSelection( + mStartIndex, mEndIndex, mEntityConfidence, mLogSource, mVersionInfo); } } } diff --git a/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java b/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java new file mode 100644 index 000000000000..45baf912ebb2 --- /dev/null +++ b/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java @@ -0,0 +1,560 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.textclassifier.logging; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.metrics.LogMaker; +import android.util.Log; +import android.view.textclassifier.TextClassification; +import android.view.textclassifier.TextClassifier; +import android.view.textclassifier.TextSelection; + +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.internal.util.Preconditions; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Objects; +import java.util.UUID; + +/** + * A selection event tracker. + * @hide + */ +//TODO: Do not allow any crashes from this class. +public final class SmartSelectionEventTracker { + + private static final String LOG_TAG = "SmartSelectionEventTracker"; + private static final boolean DEBUG_LOG_ENABLED = true; + + private static final int START_EVENT_DELTA = MetricsEvent.NOTIFICATION_SINCE_CREATE_MILLIS; + private static final int PREV_EVENT_DELTA = MetricsEvent.NOTIFICATION_SINCE_UPDATE_MILLIS; + private static final int ENTITY_TYPE = MetricsEvent.NOTIFICATION_TAG; + private static final int INDEX = MetricsEvent.NOTIFICATION_SHADE_INDEX; + private static final int TAG = MetricsEvent.FIELD_CLASS_NAME; + private static final int SMART_INDICES = MetricsEvent.FIELD_GESTURE_LENGTH; + private static final int EVENT_INDICES = MetricsEvent.FIELD_CONTEXT; + private static final int SESSION_ID = MetricsEvent.FIELD_INSTANT_APP_LAUNCH_TOKEN; + + private static final String ZERO = "0"; + private static final String TEXTVIEW = "textview"; + private static final String EDITTEXT = "edittext"; + private static final String WEBVIEW = "webview"; + private static final String EDIT_WEBVIEW = "edit-webview"; + private static final String UNKNOWN = "unknown"; + + @Retention(RetentionPolicy.SOURCE) + @IntDef({WidgetType.UNSPECIFIED, WidgetType.TEXTVIEW, WidgetType.WEBVIEW, + WidgetType.EDITTEXT, WidgetType.EDIT_WEBVIEW}) + public @interface WidgetType { + int UNSPECIFIED = 0; + int TEXTVIEW = 1; + int WEBVIEW = 2; + int EDITTEXT = 3; + int EDIT_WEBVIEW = 4; + } + + private final MetricsLogger mMetricsLogger = new MetricsLogger(); + private final int mWidgetType; + private final Context mContext; + + @Nullable private String mSessionId; + private final int[] mSmartIndices = new int[2]; + private final int[] mPrevIndices = new int[2]; + private int mOrigStart; + private int mIndex; + private long mSessionStartTime; + private long mLastEventTime; + private boolean mSmartSelectionTriggered; + + public SmartSelectionEventTracker(@NonNull Context context, @WidgetType int widgetType) { + mWidgetType = widgetType; + mContext = Preconditions.checkNotNull(context); + } + + /** + * Logs a selection event. + * + * @param event the selection event + */ + public void logEvent(@NonNull SelectionEvent event) { + Preconditions.checkNotNull(event); + + if (event.mEventType != SelectionEvent.EventType.SELECTION_STARTED && mSessionId == null) { + Log.d(LOG_TAG, "Selection session not yet started. Ignoring event"); + return; + } + + final long now = System.currentTimeMillis(); + switch (event.mEventType) { + case SelectionEvent.EventType.SELECTION_STARTED: + mSessionId = startNewSession(); + Preconditions.checkArgument(event.mEnd == event.mStart + 1); + mOrigStart = event.mStart; + mSessionStartTime = now; + break; + case SelectionEvent.EventType.SMART_SELECTION_SINGLE: // fall through + case SelectionEvent.EventType.SMART_SELECTION_MULTI: + mSmartSelectionTriggered = true; + mSmartIndices[0] = event.mStart; + mSmartIndices[1] = event.mEnd; + break; + case SelectionEvent.EventType.SELECTION_MODIFIED: // fall through + case SelectionEvent.EventType.AUTO_SELECTION: + if (mPrevIndices[0] == event.mStart && mPrevIndices[1] == event.mEnd) { + // Selection did not change. Ignore event. + return; + } + } + writeEvent(event, now); + + if (event.isTerminal()) { + endSession(); + } + } + + private void writeEvent(SelectionEvent event, long now) { + final LogMaker log = new LogMaker(MetricsEvent.TEXT_SELECTION_MENU_ITEM_ASSIST) + .setType(getLogType(event)) + .setSubtype(event.mEventType) + .setPackageName(mContext.getPackageName()) + .setTimestamp(now) + .addTaggedData(START_EVENT_DELTA, now - mSessionStartTime) + .addTaggedData(PREV_EVENT_DELTA, now - mLastEventTime) + .addTaggedData(ENTITY_TYPE, event.mEntityType) + .addTaggedData(INDEX, mIndex) + .addTaggedData(TAG, getTag(event)) + .addTaggedData(SMART_INDICES, getSmartDelta()) + .addTaggedData(EVENT_INDICES, getEventDelta(event)) + .addTaggedData(SESSION_ID, mSessionId); + mMetricsLogger.write(log); + debugLog(log); + mLastEventTime = now; + mPrevIndices[0] = event.mStart; + mPrevIndices[1] = event.mEnd; + mIndex++; + } + + private String startNewSession() { + endSession(); + mSessionId = createSessionId(); + return mSessionId; + } + + private void endSession() { + // Reset fields. + mOrigStart = 0; + mSmartIndices[0] = mSmartIndices[1] = 0; + mPrevIndices[0] = mPrevIndices[1] = 0; + mIndex = 0; + mSessionStartTime = 0; + mLastEventTime = 0; + mSmartSelectionTriggered = false; + mSessionId = null; + } + + private int getLogType(SelectionEvent event) { + switch (event.mEventType) { + case SelectionEvent.EventType.SELECTION_STARTED: // fall through + case SelectionEvent.EventType.SMART_SELECTION_SINGLE: // fall through + case SelectionEvent.EventType.SMART_SELECTION_MULTI: // fall through + case SelectionEvent.EventType.AUTO_SELECTION: + return MetricsEvent.TYPE_OPEN; + case SelectionEvent.ActionType.ABANDON: + return MetricsEvent.TYPE_CLOSE; + } + if (event.isActionType()) { + if (event.isTerminal() && mSmartSelectionTriggered) { + if (matchesSmartSelectionBounds(event)) { + // Smart selection accepted. + return MetricsEvent.TYPE_SUCCESS; + } else if (containsOriginalSelection(event)) { + // Smart selection rejected. + return MetricsEvent.TYPE_FAILURE; + } + // User changed the original selection entirely. + } + return MetricsEvent.TYPE_ACTION; + } else { + return MetricsEvent.TYPE_UPDATE; + } + } + + private boolean matchesSmartSelectionBounds(SelectionEvent event) { + return event.mStart == mSmartIndices[0] && event.mEnd == mSmartIndices[1]; + } + + private boolean containsOriginalSelection(SelectionEvent event) { + return event.mStart <= mOrigStart && event.mEnd > mOrigStart; + } + + private int getSmartDelta() { + if (mSmartSelectionTriggered) { + return (clamp(mSmartIndices[0] - mOrigStart) << 16) + | (clamp(mSmartIndices[1] - mOrigStart) & 0xffff); + } + // If no smart selection, return start selection indices (i.e. [0, 1]) + return /* (0 << 16) | */ (1 & 0xffff); + } + + private int getEventDelta(SelectionEvent event) { + return (clamp(event.mStart - mOrigStart) << 16) + | (clamp(event.mEnd - mOrigStart) & 0xffff); + } + + private String getTag(SelectionEvent event) { + final String widgetType; + switch (mWidgetType) { + case WidgetType.TEXTVIEW: + widgetType = TEXTVIEW; + break; + case WidgetType.WEBVIEW: + widgetType = WEBVIEW; + break; + case WidgetType.EDITTEXT: + widgetType = EDITTEXT; + break; + case WidgetType.EDIT_WEBVIEW: + widgetType = EDIT_WEBVIEW; + break; + default: + widgetType = UNKNOWN; + } + final String version = Objects.toString(event.mVersionTag, SelectionEvent.NO_VERSION_TAG); + return String.format("%s/%s", widgetType, version); + } + + private static String createSessionId() { + return UUID.randomUUID().toString(); + } + + private static int clamp(int val) { + return Math.max(Math.min(val, Short.MAX_VALUE), Short.MIN_VALUE); + } + + private static void debugLog(LogMaker log) { + if (!DEBUG_LOG_ENABLED) return; + + final int index = Integer.parseInt(Objects.toString(log.getTaggedData(INDEX), ZERO)); + + final String event; + switch (log.getSubtype()) { + case SelectionEvent.ActionType.OVERTYPE: + event = "OVERTYPE"; + break; + case SelectionEvent.ActionType.COPY: + event = "COPY"; + break; + case SelectionEvent.ActionType.PASTE: + event = "PASTE"; + break; + case SelectionEvent.ActionType.CUT: + event = "CUT"; + break; + case SelectionEvent.ActionType.SHARE: + event = "SHARE"; + break; + case SelectionEvent.ActionType.SMART_SHARE: + event = "SMART_SHARE"; + break; + case SelectionEvent.ActionType.DRAG: + event = "DRAG"; + break; + case SelectionEvent.ActionType.ABANDON: + event = "ABANDON"; + break; + case SelectionEvent.ActionType.OTHER: + event = "OTHER"; + break; + case SelectionEvent.ActionType.SELECT_ALL: + event = "SELECT_ALL"; + break; + case SelectionEvent.ActionType.RESET: + event = "RESET"; + break; + case SelectionEvent.EventType.SELECTION_STARTED: + final String tag = Objects.toString(log.getTaggedData(TAG), "tag"); + String sessionId = Objects.toString(log.getTaggedData(SESSION_ID), ""); + sessionId = sessionId.substring(sessionId.lastIndexOf("-") + 1); + Log.d(LOG_TAG, String.format("New selection session: %s(%s)", tag, sessionId)); + event = "SELECTION_STARTED"; + break; + case SelectionEvent.EventType.SELECTION_MODIFIED: + event = "SELECTION_MODIFIED"; + break; + case SelectionEvent.EventType.SMART_SELECTION_SINGLE: + event = "SMART_SELECTION_SINGLE"; + break; + case SelectionEvent.EventType.SMART_SELECTION_MULTI: + event = "SMART_SELECTION_MULTI"; + break; + case SelectionEvent.EventType.AUTO_SELECTION: + event = "AUTO_SELECTION"; + break; + default: + event = "UNKNOWN"; + } + + final int smartIndices = Integer.parseInt( + Objects.toString(log.getTaggedData(SMART_INDICES), ZERO)); + final int smartStart = (short) ((smartIndices & 0xffff0000) >> 16); + final int smartEnd = (short) (smartIndices & 0xffff); + + final int eventIndices = Integer.parseInt( + Objects.toString(log.getTaggedData(EVENT_INDICES), ZERO)); + final int eventStart = (short) ((eventIndices & 0xffff0000) >> 16); + final int eventEnd = (short) (eventIndices & 0xffff); + + final String entity = Objects.toString( + log.getTaggedData(ENTITY_TYPE), TextClassifier.TYPE_UNKNOWN); + + Log.d(LOG_TAG, String.format("%2d: %s, context=%d,%d - old=%d,%d [%s]", + index, event, eventStart, eventEnd, smartStart, smartEnd, entity)); + } + + /** + * A selection event. + * Specify index parameters as word token indices. + */ + public static final class SelectionEvent { + + /** + * Use this to specify an indeterminate positive index. + */ + public static final int OUT_OF_BOUNDS = Short.MAX_VALUE; + + /** + * Use this to specify an indeterminate negative index. + */ + public static final int OUT_OF_BOUNDS_NEGATIVE = Short.MIN_VALUE; + + private static final String NO_VERSION_TAG = ""; + + @Retention(RetentionPolicy.SOURCE) + @IntDef({ActionType.OVERTYPE, ActionType.COPY, ActionType.PASTE, ActionType.CUT, + ActionType.SHARE, ActionType.SMART_SHARE, ActionType.DRAG, ActionType.ABANDON, + ActionType.OTHER, ActionType.SELECT_ALL, ActionType.RESET}) + public @interface ActionType { + /** User typed over the selection. */ + int OVERTYPE = 100; + /** User copied the selection. */ + int COPY = 101; + /** User pasted over the selection. */ + int PASTE = 102; + /** User cut the selection. */ + int CUT = 103; + /** User shared the selection. */ + int SHARE = 104; + /** User clicked the textAssist menu item. */ + int SMART_SHARE = 105; + /** User dragged+dropped the selection. */ + int DRAG = 106; + /** User abandoned the selection. */ + int ABANDON = 107; + /** User performed an action on the selection. */ + int OTHER = 108; + + /* Non-terminal actions. */ + /** User activated Select All */ + int SELECT_ALL = 200; + /** User reset the smart selection. */ + int RESET = 201; + } + + @Retention(RetentionPolicy.SOURCE) + @IntDef({ActionType.OVERTYPE, ActionType.COPY, ActionType.PASTE, ActionType.CUT, + ActionType.SHARE, ActionType.SMART_SHARE, ActionType.DRAG, ActionType.ABANDON, + ActionType.OTHER, ActionType.SELECT_ALL, ActionType.RESET, + EventType.SELECTION_STARTED, EventType.SELECTION_MODIFIED, + EventType.SMART_SELECTION_SINGLE, EventType.SMART_SELECTION_MULTI, + EventType.AUTO_SELECTION}) + private @interface EventType { + /** User started a new selection. */ + int SELECTION_STARTED = 1; + /** User modified an existing selection. */ + int SELECTION_MODIFIED = 2; + /** Smart selection triggered for a single token (word). */ + int SMART_SELECTION_SINGLE = 3; + /** Smart selection triggered spanning multiple tokens (words). */ + int SMART_SELECTION_MULTI = 4; + /** Something else other than User or the default TextClassifier triggered a selection. */ + int AUTO_SELECTION = 5; + } + + private final int mStart; + private final int mEnd; + private @EventType int mEventType; + private final @TextClassifier.EntityType String mEntityType; + private final String mVersionTag; + + private SelectionEvent( + int start, int end, int eventType, + @TextClassifier.EntityType String entityType, String versionTag) { + Preconditions.checkArgument(end >= start, "end cannot be less than start"); + mStart = start; + mEnd = end; + mEventType = eventType; + mEntityType = Preconditions.checkNotNull(entityType); + mVersionTag = Preconditions.checkNotNull(versionTag); + } + + /** + * Creates a "selection started" event. + * + * @param start the word index of the selected word + */ + public static SelectionEvent selectionStarted(int start) { + return new SelectionEvent( + start, start + 1, EventType.SELECTION_STARTED, + TextClassifier.TYPE_UNKNOWN, NO_VERSION_TAG); + } + + /** + * Creates a "selection modified" event. + * Use when the user modifies the selection. + * + * @param start the start word (inclusive) index of the selection + * @param end the end word (exclusive) index of the selection + */ + public static SelectionEvent selectionModified(int start, int end) { + return new SelectionEvent( + start, end, EventType.SELECTION_MODIFIED, + TextClassifier.TYPE_UNKNOWN, NO_VERSION_TAG); + } + + /** + * Creates a "selection modified" event. + * Use when the user modifies the selection and the selection's entity type is known. + * + * @param start the start word (inclusive) index of the selection + * @param end the end word (exclusive) index of the selection + * @param classification the TextClassification object returned by the TextClassifier that + * classified the selected text + */ + public static SelectionEvent selectionModified( + int start, int end, @NonNull TextClassification classification) { + final String entityType = classification.getEntityCount() > 0 + ? classification.getEntity(0) + : TextClassifier.TYPE_UNKNOWN; + final String versionTag = classification.getVersionInfo(); + return new SelectionEvent( + start, end, EventType.SELECTION_MODIFIED, entityType, versionTag); + } + + /** + * Creates a "selection modified" event. + * Use when a TextClassifier modifies the selection. + * + * @param start the start word (inclusive) index of the selection + * @param end the end word (exclusive) index of the selection + * @param selection the TextSelection object returned by the TextClassifier for the + * specified selection + */ + public static SelectionEvent selectionModified( + int start, int end, @NonNull TextSelection selection) { + final boolean smartSelection = selection.getSourceClassifier() + .equals(TextClassifier.DEFAULT_LOG_TAG); + final int eventType; + if (smartSelection) { + eventType = end - start > 1 + ? EventType.SMART_SELECTION_MULTI + : EventType.SMART_SELECTION_SINGLE; + + } else { + eventType = EventType.AUTO_SELECTION; + } + final String entityType = selection.getEntityCount() > 0 + ? selection.getEntity(0) + : TextClassifier.TYPE_UNKNOWN; + final String versionTag = selection.getVersionInfo(); + return new SelectionEvent(start, end, eventType, entityType, versionTag); + } + + /** + * Creates an event specifying an action taken on a selection. + * Use when the user clicks on an action to act on the selected text. + * + * @param start the start word (inclusive) index of the selection + * @param end the end word (exclusive) index of the selection + * @param actionType the action that was performed on the selection + */ + public static SelectionEvent selectionAction( + int start, int end, @ActionType int actionType) { + return new SelectionEvent( + start, end, actionType, TextClassifier.TYPE_UNKNOWN, NO_VERSION_TAG); + } + + /** + * Creates an event specifying an action taken on a selection. + * Use when the user clicks on an action to act on the selected text and the selection's + * entity type is known. + * + * @param start the start word (inclusive) index of the selection + * @param end the end word (exclusive) index of the selection + * @param actionType the action that was performed on the selection + * @param classification the TextClassification object returned by the TextClassifier that + * classified the selected text + */ + public static SelectionEvent selectionAction( + int start, int end, @ActionType int actionType, + @NonNull TextClassification classification) { + final String entityType = classification.getEntityCount() > 0 + ? classification.getEntity(0) + : TextClassifier.TYPE_UNKNOWN; + final String versionTag = classification.getVersionInfo(); + return new SelectionEvent(start, end, actionType, entityType, versionTag); + } + + private boolean isActionType() { + switch (mEventType) { + case ActionType.OVERTYPE: // fall through + case ActionType.COPY: // fall through + case ActionType.PASTE: // fall through + case ActionType.CUT: // fall through + case ActionType.SHARE: // fall through + case ActionType.SMART_SHARE: // fall through + case ActionType.DRAG: // fall through + case ActionType.ABANDON: // fall through + case ActionType.SELECT_ALL: // fall through + case ActionType.RESET: // fall through + return true; + default: + return false; + } + } + + private boolean isTerminal() { + switch (mEventType) { + case ActionType.OVERTYPE: // fall through + case ActionType.COPY: // fall through + case ActionType.PASTE: // fall through + case ActionType.CUT: // fall through + case ActionType.SHARE: // fall through + case ActionType.SMART_SHARE: // fall through + case ActionType.DRAG: // fall through + case ActionType.ABANDON: // fall through + return true; + default: + return false; + } + } + } +} diff --git a/core/java/android/webkit/UserPackage.java b/core/java/android/webkit/UserPackage.java index 892008948e87..9da64559d0fe 100644 --- a/core/java/android/webkit/UserPackage.java +++ b/core/java/android/webkit/UserPackage.java @@ -83,7 +83,7 @@ public class UserPackage { * supported by the current framework version. */ public static boolean hasCorrectTargetSdkVersion(PackageInfo packageInfo) { - return packageInfo.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O; + return packageInfo.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O_MR1; } public UserInfo getUserInfo() { diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java index 5735f29b056f..81aa2f3a05fc 100644 --- a/core/java/android/webkit/WebChromeClient.java +++ b/core/java/android/webkit/WebChromeClient.java @@ -414,7 +414,7 @@ public class WebChromeClient { * @param webView The WebView instance that is initiating the request. * @param filePathCallback Invoke this callback to supply the list of paths to files to upload, * or NULL to cancel. Must only be called if the - * <code>showFileChooser</code> implementations returns true. + * {@link #onShowFileChooser} implementation returns true. * @param fileChooserParams Describes the mode of file chooser to be opened, and options to be * used with it. * @return true if filePathCallback will be invoked, false to use default handling. @@ -517,7 +517,7 @@ public class WebChromeClient { * @param capture The value of the 'capture' attribute of the input tag * associated with this file picker. * - * @deprecated Use {@link #showFileChooser} instead. + * @deprecated Use {@link #onShowFileChooser} instead. * @hide This method was not published in any SDK version. */ @SystemApi diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 650c7d97d357..f918cadde87c 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -1628,56 +1628,41 @@ public class WebView extends AbsoluteLayout } /** - * Starts Safe Browsing initialization. This should only be called once. - * + * Starts Safe Browsing initialization. * <p> - * Because the Safe Browsing feature takes time to initialize, WebView may temporarily whitelist - * URLs until the feature is ready. The callback will be invoked with true once initialization - * is complete. - * </p> - * + * URL loads are not guaranteed to be protected by Safe Browsing until after {@code callback} is + * invoked with {@code true}. Safe Browsing is not fully supported on all devices. For those + * devices {@code callback} will receive {@code false}. * <p> - * This does not enable the Safe Browsing feature itself, and should only be used if the feature - * is otherwise enabled. - * </p> - * + * This does not enable the Safe Browsing feature itself, and should only be called if Safe + * Browsing is enabled by the manifest tag or {@link WebSettings#setSafeBrowsingEnabled}. This + * prepares resources used for Safe Browsing. * <p> - * This does not require an Activity Context, and will always use the application Context to do - * its work. - * </p> + * This should be called with the Application Context (and will always use the Application + * context to do its work regardless). * * @param context Application Context. - * @param callback will be called with the value true if initialization is - * successful. The callback will be run on the UI thread. + * @param callback will be called on the UI thread with {@code true} if initialization is + * successful, {@code false} otherwise. */ - public static void initSafeBrowsing(Context context, ValueCallback<Boolean> callback) { + public static void startSafeBrowsing(Context context, ValueCallback<Boolean> callback) { getFactory().getStatics().initSafeBrowsing(context, callback); } /** - * Shuts down Safe Browsing. This should only be called once. This does not disable the feature, - * it only frees resources used by Safe Browsing code. To disable Safe Browsing on an individual - * WebView, see {@link WebSettings#setSafeBrowsingEnabled} - */ - public static void shutdownSafeBrowsing() { - getFactory().getStatics().shutdownSafeBrowsing(); - } - - /** * Sets the list of domains that are exempt from SafeBrowsing checks. The list is * global for all the WebViews. * <p> * Each rule should take one of these: * <table> * <tr><th> Rule </th> <th> Example </th> <th> Matches Subdomain</th> </tr> - * <tr><th> HOSTNAME </th> <th> example.com </th> <th> Yes </th> </tr> - * <tr><th>.HOSTNAME</th> <th> .example.com </th> <th> No </th> </tr> - * <tr><th> IPV4_LITERAL </th> <th> 192.168.1.1 </th> <th> No </th></tr> - * <tr><th> IPV6_LITERAL_WITH_BRACKETS</th><th>[10:20:30:40:50:60:70:80]</th><th>No</th></tr> + * <tr><td> HOSTNAME </td> <td> example.com </td> <td> Yes </td> </tr> + * <tr><td> .HOSTNAME </td> <td> .example.com </td> <td> No </td> </tr> + * <tr><td> IPV4_LITERAL </td> <td> 192.168.1.1 </td> <td> No </td></tr> + * <tr><td> IPV6_LITERAL_WITH_BRACKETS </td><td>[10:20:30:40:50:60:70:80]</td><td>No</td></tr> * </table> * <p> * All other rules, including wildcards, are invalid. - * <p> * * @param urls the list of URLs * @param callback will be called with true if URLs are successfully added to the whitelist. @@ -1940,13 +1925,14 @@ public class WebView extends AbsoluteLayout * For applications targeted to API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN} or below, * all public methods (including the inherited ones) can be accessed, see the * important security note below for implications. - * <p> Note that injected objects will not - * appear in JavaScript until the page is next (re)loaded. For example: + * <p> Note that injected objects will not appear in JavaScript until the page is next + * (re)loaded. JavaScript should be enabled before injecting the object. For example: * <pre> * class JsObject { * {@literal @}JavascriptInterface * public String toString() { return "injectedObject"; } * } + * webview.getSettings().setJavaScriptEnabled(true); * webView.addJavascriptInterface(new JsObject(), "injectedObject"); * webView.loadData("<!DOCTYPE html><title></title>", "text/html", null); * webView.loadUrl("javascript:alert(injectedObject.toString())");</pre> @@ -2725,6 +2711,18 @@ public class WebView extends AbsoluteLayout * understood by the {@link android.service.autofill.AutofillService} implementations: * * <ol> + * <li>Only the HTML nodes inside a {@code FORM} are generated. + * <li>The source of the HTML is set using {@link ViewStructure#setWebDomain(String)} in the + * node representing the WebView. + * <li>If a web page has multiple {@code FORM}s, only the data for the current form is + * represented—if the user taps a field from another form, then the current autofill + * context is canceled (by calling {@link android.view.autofill.AutofillManager#cancel()} and + * a new context is created for that {@code FORM}. + * <li>Similarly, if the page has {@code IFRAME} nodes, they are not initially represented in + * the view structure until the user taps a field from a {@code FORM} inside the + * {@code IFRAME}, in which case it would be treated the same way as multiple forms described + * above, except that the {@link ViewStructure#setWebDomain(String) web domain} of the + * {@code FORM} contains the {@code src} attribute from the {@code IFRAME} node. * <li>If the Android SDK provides a similar View, then should be set with the * fully-qualified class name of such view. * <li>The W3C autofill field ({@code autocomplete} tag attribute) maps to diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java index 6a482423e043..668cfba94071 100644 --- a/core/java/android/webkit/WebViewFactory.java +++ b/core/java/android/webkit/WebViewFactory.java @@ -47,7 +47,7 @@ public final class WebViewFactory { // visible for WebViewZygoteInit to look up the class by reflection and call preloadInZygote. /** @hide */ private static final String CHROMIUM_WEBVIEW_FACTORY = - "com.android.webview.chromium.WebViewChromiumFactoryProviderForO"; + "com.android.webview.chromium.WebViewChromiumFactoryProviderForOMR1"; private static final String CHROMIUM_WEBVIEW_FACTORY_METHOD = "create"; diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java index 4f6513fe1bc8..4c47abc65a65 100644 --- a/core/java/android/webkit/WebViewFactoryProvider.java +++ b/core/java/android/webkit/WebViewFactoryProvider.java @@ -80,17 +80,11 @@ public interface WebViewFactoryProvider { /** * Implement the API method - * {@link android.webkit.WebView#initSafeBrowsing(Context , ValueCallback<Boolean>)} + * {@link android.webkit.WebView#startSafeBrowsing(Context , ValueCallback<Boolean>)} */ void initSafeBrowsing(Context context, ValueCallback<Boolean> callback); /** - * Implement the API method - * {@link android.webkit.WebView#shutdownSafeBrowsing()} - */ - void shutdownSafeBrowsing(); - - /** * Implement the API method * {@link android.webkit.WebView#setSafeBrowsingWhitelist(List<String>, * ValueCallback<Boolean>)} diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 91e2f7d4ddd0..170582b3c3f5 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -1480,11 +1480,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te /** @hide */ @Override - public void sendAccessibilityEventInternal(int eventType) { + public void sendAccessibilityEventUnchecked(AccessibilityEvent event) { // Since this class calls onScrollChanged even if the mFirstPosition and the // child count have not changed we will avoid sending duplicate accessibility // events. - if (eventType == AccessibilityEvent.TYPE_VIEW_SCROLLED) { + if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) { final int firstVisiblePosition = getFirstVisiblePosition(); final int lastVisiblePosition = getLastVisiblePosition(); if (mLastAccessibilityScrollEventFromIndex == firstVisiblePosition @@ -1495,7 +1495,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mLastAccessibilityScrollEventToIndex = lastVisiblePosition; } } - super.sendAccessibilityEventInternal(eventType); + super.sendAccessibilityEventUnchecked(event); } @Override diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java index 690067b48133..f18f2172b455 100644 --- a/core/java/android/widget/ArrayAdapter.java +++ b/core/java/android/widget/ArrayAdapter.java @@ -152,7 +152,8 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable, ThemedSp } /** - * Constructor + * Constructor. This constructor will result in the underlying data collection being + * immutable, so methods such as {@link #clear()} will throw an exception. * * @param context The current context. * @param resource The resource ID for a layout file containing a TextView to use when @@ -164,7 +165,8 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable, ThemedSp } /** - * Constructor + * Constructor. This constructor will result in the underlying data collection being + * immutable, so methods such as {@link #clear()} will throw an exception. * * @param context The current context. * @param resource The resource ID for a layout file containing a layout to use when @@ -218,6 +220,7 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable, ThemedSp * Adds the specified object at the end of the array. * * @param object The object to add at the end of the array. + * @throws UnsupportedOperationException if the underlying data collection is immutable */ public void add(@Nullable T object) { synchronized (mLock) { @@ -261,6 +264,7 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable, ThemedSp * Adds the specified items at the end of the array. * * @param items The items to add at the end of the array. + * @throws UnsupportedOperationException if the underlying data collection is immutable */ public void addAll(T ... items) { synchronized (mLock) { @@ -279,6 +283,7 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable, ThemedSp * * @param object The object to insert into the array. * @param index The index at which the object must be inserted. + * @throws UnsupportedOperationException if the underlying data collection is immutable */ public void insert(@Nullable T object, int index) { synchronized (mLock) { @@ -296,6 +301,7 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable, ThemedSp * Removes the specified object from the array. * * @param object The object to remove. + * @throws UnsupportedOperationException if the underlying data collection is immutable */ public void remove(@Nullable T object) { synchronized (mLock) { @@ -311,6 +317,8 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable, ThemedSp /** * Remove all elements from the list. + * + * @throws UnsupportedOperationException if the underlying data collection is immutable */ public void clear() { synchronized (mLock) { diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java index 8094bfc6eeb8..dfb36423ea94 100644 --- a/core/java/android/widget/DatePicker.java +++ b/core/java/android/widget/DatePicker.java @@ -524,12 +524,13 @@ public class DatePicker extends FrameLayout { void setAutoFillChangeListener(OnDateChangedListener onDateChangedListener); void updateDate(int year, int month, int dayOfMonth); - void updateDate(long date); int getYear(); int getMonth(); int getDayOfMonth(); - long getDate(); + + void autofill(AutofillValue value); + AutofillValue getAutofillValue(); void setFirstDayOfWeek(int firstDayOfWeek); int getFirstDayOfWeek(); @@ -572,6 +573,7 @@ public class DatePicker extends FrameLayout { // The context protected Context mContext; + // NOTE: when subclasses change this variable, they must call resetAutofilledValue(). protected Calendar mCurrentDate; // The current locale @@ -582,6 +584,11 @@ public class DatePicker extends FrameLayout { protected OnDateChangedListener mAutoFillChangeListener; protected ValidationCallback mValidationCallback; + // The value that was passed to autofill() - it must be stored because it getAutofillValue() + // must return the exact same value that was autofilled, otherwise the widget will not be + // properly highlighted after autofill(). + private long mAutofilledValue; + public AbstractDatePickerDelegate(DatePicker delegator, Context context) { mDelegator = delegator; mContext = context; @@ -612,16 +619,38 @@ public class DatePicker extends FrameLayout { } @Override - public void updateDate(long date) { - Calendar cal = Calendar.getInstance(mCurrentLocale); - cal.setTimeInMillis(date); + public final void autofill(AutofillValue value) { + if (value == null || !value.isDate()) { + Log.w(LOG_TAG, value + " could not be autofilled into " + this); + return; + } + + final long time = value.getDateValue(); + + final Calendar cal = Calendar.getInstance(mCurrentLocale); + cal.setTimeInMillis(time); updateDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH)); + + // Must set mAutofilledValue *after* calling subclass method to make sure the value + // returned by getAutofillValue() matches it. + mAutofilledValue = time; } @Override - public long getDate() { - return mCurrentDate.getTimeInMillis(); + public final AutofillValue getAutofillValue() { + final long time = mAutofilledValue != 0 + ? mAutofilledValue + : mCurrentDate.getTimeInMillis(); + return AutofillValue.forDate(time); + } + + /** + * This method must be called every time the value of the year, month, and/or day is + * changed by a subclass method. + */ + protected void resetAutofilledValue() { + mAutofilledValue = 0; } protected void onValidationChanged(boolean valid) { @@ -777,12 +806,7 @@ public class DatePicker extends FrameLayout { public void autofill(AutofillValue value) { if (!isEnabled()) return; - if (!value.isDate()) { - Log.w(LOG_TAG, value + " could not be autofilled into " + this); - return; - } - - mDelegate.updateDate(value.getDateValue()); + mDelegate.autofill(value); } @Override @@ -792,6 +816,6 @@ public class DatePicker extends FrameLayout { @Override public AutofillValue getAutofillValue() { - return isEnabled() ? AutofillValue.forDate(mDelegate.getDate()) : null; + return isEnabled() ? mDelegate.getAutofillValue() : null; } } diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java index 636519b197e7..60b4757216af 100755 --- a/core/java/android/widget/DatePickerCalendarDelegate.java +++ b/core/java/android/widget/DatePickerCalendarDelegate.java @@ -368,12 +368,9 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate { } @Override - public void init(int year, int monthOfYear, int dayOfMonth, + public void init(int year, int month, int dayOfMonth, DatePicker.OnDateChangedListener callBack) { - mCurrentDate.set(Calendar.YEAR, year); - mCurrentDate.set(Calendar.MONTH, monthOfYear); - mCurrentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); - + setDate(year, month, dayOfMonth); onDateChanged(false, false); mOnDateChangedListener = callBack; @@ -381,11 +378,15 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate { @Override public void updateDate(int year, int month, int dayOfMonth) { + setDate(year, month, dayOfMonth); + onDateChanged(false, true); + } + + private void setDate(int year, int month, int dayOfMonth) { mCurrentDate.set(Calendar.YEAR, year); mCurrentDate.set(Calendar.MONTH, month); mCurrentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); - - onDateChanged(false, true); + resetAutofilledValue(); } private void onDateChanged(boolean fromUser, boolean callbackToClient) { diff --git a/core/java/android/widget/DatePickerSpinnerDelegate.java b/core/java/android/widget/DatePickerSpinnerDelegate.java index 4f9316f881cd..dba74b191b09 100644 --- a/core/java/android/widget/DatePickerSpinnerDelegate.java +++ b/core/java/android/widget/DatePickerSpinnerDelegate.java @@ -504,6 +504,7 @@ class DatePickerSpinnerDelegate extends AbstractDatePickerDelegate { private void setDate(int year, int month, int dayOfMonth) { mCurrentDate.set(year, month, dayOfMonth); + resetAutofilledValue(); if (mCurrentDate.before(mMinDate)) { mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis()); } else if (mCurrentDate.after(mMaxDate)) { diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index d02d6ff9a9b0..f9bdb0fe040c 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -260,6 +260,7 @@ public class Editor { private PositionListener mPositionListener; private float mLastDownPositionX, mLastDownPositionY; + private float mLastUpPositionX, mLastUpPositionY; private float mContextMenuAnchorX, mContextMenuAnchorY; Callback mCustomSelectionActionModeCallback; Callback mCustomInsertionActionModeCallback; @@ -754,14 +755,18 @@ public class Editor { } } - private void chooseSize(PopupWindow pop, CharSequence text, TextView tv) { - int wid = tv.getPaddingLeft() + tv.getPaddingRight(); - int ht = tv.getPaddingTop() + tv.getPaddingBottom(); + private void chooseSize(@NonNull PopupWindow pop, @NonNull CharSequence text, + @NonNull TextView tv) { + final int wid = tv.getPaddingLeft() + tv.getPaddingRight(); + final int ht = tv.getPaddingTop() + tv.getPaddingBottom(); - int defaultWidthInPixels = mTextView.getResources().getDimensionPixelSize( + final int defaultWidthInPixels = mTextView.getResources().getDimensionPixelSize( com.android.internal.R.dimen.textview_error_popup_default_width); - Layout l = new StaticLayout(text, tv.getPaint(), defaultWidthInPixels, - Layout.Alignment.ALIGN_NORMAL, 1, 0, true); + final StaticLayout l = StaticLayout.Builder.obtain(text, 0, text.length(), tv.getPaint(), + defaultWidthInPixels) + .setUseLineSpacingFromFallbacks(tv.mUseFallbackLineSpacing) + .build(); + float max = 0; for (int i = 0; i < l.getLineCount(); i++) { max = Math.max(max, l.getLineWidth(i)); @@ -1130,6 +1135,14 @@ public class Editor { return handled; } + float getLastUpPositionX() { + return mLastUpPositionX; + } + + float getLastUpPositionY() { + return mLastUpPositionY; + } + private long getLastTouchOffsets() { SelectionModifierCursorController selectionController = getSelectionController(); final int minOffset = selectionController.getMinTouchOffset(); @@ -1371,6 +1384,11 @@ public class Editor { mShowSuggestionRunnable = null; } + if (event.getActionMasked() == MotionEvent.ACTION_UP) { + mLastUpPositionX = event.getX(); + mLastUpPositionY = event.getY(); + } + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { mLastDownPositionX = event.getX(); mLastDownPositionY = event.getY(); diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index 5845719ee537..fc9e8e70c20a 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -624,9 +624,9 @@ public class ListView extends AbsListView { for (int i = 0; i < count; i++) { final View child = infos.get(i).view; - final LayoutParams p = (LayoutParams) child.getLayoutParams(); - if (p != null) { - p.recycledHeaderFooter = false; + final ViewGroup.LayoutParams params = child.getLayoutParams(); + if (checkLayoutParams(params)) { + ((LayoutParams) params).recycledHeaderFooter = false; } } } diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index b77aa1c6888a..46742b8852ff 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -64,6 +64,7 @@ import android.view.ViewStub; import android.widget.AdapterView.OnItemClickListener; import com.android.internal.R; +import com.android.internal.util.NotificationColorUtil; import com.android.internal.util.Preconditions; import libcore.util.Objects; @@ -72,9 +73,13 @@ import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; +import java.util.Stack; import java.util.concurrent.Executor; /** @@ -118,6 +123,7 @@ public class RemoteViews implements Parcelable, Filter { private static final int TEXT_VIEW_DRAWABLE_COLOR_FILTER_ACTION_TAG = 17; private static final int SET_REMOTE_INPUTS_ACTION_TAG = 18; private static final int LAYOUT_PARAM_ACTION_TAG = 19; + private static final int OVERRIDE_TEXT_COLORS_TAG = 20; /** * Application that hosts the remote views. @@ -154,6 +160,12 @@ public class RemoteViews implements Parcelable, Filter { private boolean mIsRoot = true; /** + * Whether reapply is disallowed on this remoteview. This maybe be true if some actions modify + * the layout in a way that isn't recoverable, since views are being removed. + */ + private boolean mReapplyDisallowed; + + /** * Constants to whether or not this RemoteViews is composed of a landscape and portrait * RemoteViews. */ @@ -179,17 +191,12 @@ public class RemoteViews implements Parcelable, Filter { private static final OnClickHandler DEFAULT_ON_CLICK_HANDLER = new OnClickHandler(); - private static final Object[] sMethodsLock = new Object[0]; - private static final ArrayMap<Class<? extends View>, ArrayMap<MutablePair<String, Class<?>>, Method>> sMethods = - new ArrayMap<Class<? extends View>, ArrayMap<MutablePair<String, Class<?>>, Method>>(); - private static final ArrayMap<Method, Method> sAsyncMethods = new ArrayMap<>(); + private static final ArrayMap<MethodKey, MethodArgs> sMethods = new ArrayMap<>(); - private static final ThreadLocal<Object[]> sInvokeArgsTls = new ThreadLocal<Object[]>() { - @Override - protected Object[] initialValue() { - return new Object[1]; - } - }; + /** + * This key is used to perform lookups in sMethods without causing allocations. + */ + private static final MethodKey sLookupKey = new MethodKey(); /** * @hide @@ -215,37 +222,78 @@ public class RemoteViews implements Parcelable, Filter { } /** - * Handle with care! + * Override all text colors in this layout and replace them by the given text color. + * + * @param textColor The color to use. + * + * @hide + */ + public void overrideTextColors(int textColor) { + addAction(new OverrideTextColorsAction(textColor)); + } + + /** + * Set that it is disallowed to reapply another remoteview with the same layout as this view. + * This should be done if an action is destroying the view tree of the base layout. + * + * @hide */ - static class MutablePair<F, S> { - F first; - S second; + public void setReapplyDisallowed() { + mReapplyDisallowed = true; + } - MutablePair(F first, S second) { - this.first = first; - this.second = second; - } + /** + * @return Whether it is disallowed to reapply another remoteview with the same layout as this + * view. True if this remoteview has actions that destroyed view tree of the base layout. + * + * @hide + */ + public boolean isReapplyDisallowed() { + return mReapplyDisallowed; + } + + /** + * Stores information related to reflection method lookup. + */ + static class MethodKey { + public Class targetClass; + public Class paramClass; + public String methodName; @Override public boolean equals(Object o) { - if (!(o instanceof MutablePair)) { + if (!(o instanceof MethodKey)) { return false; } - MutablePair<?, ?> p = (MutablePair<?, ?>) o; - return Objects.equal(p.first, first) && Objects.equal(p.second, second); + MethodKey p = (MethodKey) o; + return Objects.equal(p.targetClass, targetClass) + && Objects.equal(p.paramClass, paramClass) + && Objects.equal(p.methodName, methodName); } @Override public int hashCode() { - return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode()); + return Objects.hashCode(targetClass) ^ Objects.hashCode(paramClass) + ^ Objects.hashCode(methodName); + } + + public void set(Class targetClass, Class paramClass, String methodName) { + this.targetClass = targetClass; + this.paramClass = paramClass; + this.methodName = methodName; } } + /** - * This pair is used to perform lookups in sMethods without causing allocations. + * Stores information related to reflection method lookup result. */ - private final MutablePair<String, Class<?>> mPair = - new MutablePair<String, Class<?>>(null, null); + static class MethodArgs { + public MethodHandle syncMethod; + public MethodHandle asyncMethod; + public String asyncMethodName; + } + /** * This annotation indicates that a subclass of View is allowed to be used @@ -267,6 +315,12 @@ public class RemoteViews implements Parcelable, Filter { public ActionException(String message) { super(message); } + /** + * @hide + */ + public ActionException(Throwable t) { + super(t); + } } /** @hide */ @@ -903,73 +957,66 @@ public class RemoteViews implements Parcelable, Filter { return rect; } - private Method getMethod(View view, String methodName, Class<?> paramType) { - Method method; + private MethodHandle getMethod(View view, String methodName, Class<?> paramType, + boolean async) { + MethodArgs result; Class<? extends View> klass = view.getClass(); - synchronized (sMethodsLock) { - ArrayMap<MutablePair<String, Class<?>>, Method> methods = sMethods.get(klass); - if (methods == null) { - methods = new ArrayMap<MutablePair<String, Class<?>>, Method>(); - sMethods.put(klass, methods); - } - - mPair.first = methodName; - mPair.second = paramType; + synchronized (sMethods) { + // The key is defined by the view class, param class and method name. + sLookupKey.set(klass, paramType, methodName); + result = sMethods.get(sLookupKey); - method = methods.get(mPair); - if (method == null) { + if (result == null) { + Method method; try { if (paramType == null) { method = klass.getMethod(methodName); } else { method = klass.getMethod(methodName, paramType); } - } catch (NoSuchMethodException ex) { - throw new ActionException("view: " + klass.getName() + " doesn't have method: " - + methodName + getParameters(paramType)); - } + if (!method.isAnnotationPresent(RemotableViewMethod.class)) { + throw new ActionException("view: " + klass.getName() + + " can't use method with RemoteViews: " + + methodName + getParameters(paramType)); + } - if (!method.isAnnotationPresent(RemotableViewMethod.class)) { - throw new ActionException("view: " + klass.getName() - + " can't use method with RemoteViews: " + result = new MethodArgs(); + result.syncMethod = MethodHandles.publicLookup().unreflect(method); + result.asyncMethodName = + method.getAnnotation(RemotableViewMethod.class).asyncImpl(); + } catch (NoSuchMethodException | IllegalAccessException ex) { + throw new ActionException("view: " + klass.getName() + " doesn't have method: " + methodName + getParameters(paramType)); } - methods.put(new MutablePair<String, Class<?>>(methodName, paramType), method); + MethodKey key = new MethodKey(); + key.set(klass, paramType, methodName); + sMethods.put(key, result); } - } - - return method; - } - /** - * @return the async implementation of the provided method. - */ - private Method getAsyncMethod(Method method) { - synchronized (sAsyncMethods) { - int valueIndex = sAsyncMethods.indexOfKey(method); - if (valueIndex >= 0) { - return sAsyncMethods.valueAt(valueIndex); + if (!async) { + return result.syncMethod; } - - RemotableViewMethod annotation = method.getAnnotation(RemotableViewMethod.class); - Method asyncMethod = null; - if (!annotation.asyncImpl().isEmpty()) { + // Check this so see if async method is implemented or not. + if (result.asyncMethodName.isEmpty()) { + return null; + } + // Async method is lazily loaded. If it is not yet loaded, load now. + if (result.asyncMethod == null) { + MethodType asyncType = result.syncMethod.type() + .dropParameterTypes(0, 1).changeReturnType(Runnable.class); try { - asyncMethod = method.getDeclaringClass() - .getMethod(annotation.asyncImpl(), method.getParameterTypes()); - if (!asyncMethod.getReturnType().equals(Runnable.class)) { - throw new ActionException("Async implementation for " + method.getName() + - " does not return a Runnable"); - } - } catch (NoSuchMethodException ex) { - throw new ActionException("Async implementation declared but not defined for " + - method.getName()); + result.asyncMethod = MethodHandles.publicLookup().findVirtual( + klass, result.asyncMethodName, asyncType); + } catch (NoSuchMethodException | IllegalAccessException ex) { + throw new ActionException("Async implementation declared as " + + result.asyncMethodName + " but not defined for " + methodName + + ": public Runnable " + result.asyncMethodName + " (" + + TextUtils.join(",", asyncType.parameterArray()) + ")"); } } - sAsyncMethods.put(method, asyncMethod); - return asyncMethod; + return result.asyncMethod; } } @@ -978,12 +1025,6 @@ public class RemoteViews implements Parcelable, Filter { return "(" + paramType + ")"; } - private static Object[] wrapArg(Object value) { - Object[] args = sInvokeArgsTls.get(); - args[0] = value; - return args; - } - /** * Equivalent to calling a combination of {@link Drawable#setAlpha(int)}, * {@link Drawable#setColorFilter(int, android.graphics.PorterDuff.Mode)}, @@ -1100,10 +1141,8 @@ public class RemoteViews implements Parcelable, Filter { if (view == null) return; try { - getMethod(view, this.methodName, null).invoke(view); - } catch (ActionException e) { - throw e; - } catch (Exception ex) { + getMethod(view, this.methodName, null, false /* async */).invoke(view); + } catch (Throwable ex) { throw new ActionException(ex); } } @@ -1476,12 +1515,9 @@ public class RemoteViews implements Parcelable, Filter { if (param == null) { throw new ActionException("bad type: " + this.type); } - try { - getMethod(view, this.methodName, param).invoke(view, wrapArg(this.value)); - } catch (ActionException e) { - throw e; - } catch (Exception ex) { + getMethod(view, this.methodName, param, false /* async */).invoke(view, this.value); + } catch (Throwable ex) { throw new ActionException(ex); } } @@ -1497,11 +1533,10 @@ public class RemoteViews implements Parcelable, Filter { } try { - Method method = getMethod(view, this.methodName, param); - Method asyncMethod = getAsyncMethod(method); + MethodHandle method = getMethod(view, this.methodName, param, true /* async */); - if (asyncMethod != null) { - Runnable endAction = (Runnable) asyncMethod.invoke(view, wrapArg(this.value)); + if (method != null) { + Runnable endAction = (Runnable) method.invoke(view, this.value); if (endAction == null) { return ACTION_NOOP; } else { @@ -1515,9 +1550,7 @@ public class RemoteViews implements Parcelable, Filter { return new RunnableAction(endAction); } } - } catch (ActionException e) { - throw e; - } catch (Exception ex) { + } catch (Throwable ex) { throw new ActionException(ex); } @@ -2223,6 +2256,52 @@ public class RemoteViews implements Parcelable, Filter { } /** + * Helper action to override all textViewColors + */ + private class OverrideTextColorsAction extends Action { + + private final int textColor; + + public OverrideTextColorsAction(int textColor) { + this.textColor = textColor; + } + + public OverrideTextColorsAction(Parcel parcel) { + textColor = parcel.readInt(); + } + + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(OVERRIDE_TEXT_COLORS_TAG); + dest.writeInt(textColor); + } + + @Override + public void apply(View root, ViewGroup rootParent, OnClickHandler handler) { + // Let's traverse the viewtree and override all textColors! + Stack<View> viewsToProcess = new Stack<>(); + viewsToProcess.add(root); + while (!viewsToProcess.isEmpty()) { + View v = viewsToProcess.pop(); + if (v instanceof TextView) { + TextView textView = (TextView) v; + textView.setText(NotificationColorUtil.clearColorSpans(textView.getText())); + textView.setTextColor(textColor); + } + if (v instanceof ViewGroup) { + ViewGroup viewGroup = (ViewGroup) v; + for (int i = 0; i < viewGroup.getChildCount(); i++) { + viewsToProcess.push(viewGroup.getChildAt(i)); + } + } + } + } + + public String getActionName() { + return "OverrideTextColorsAction"; + } + } + + /** * Simple class used to keep track of memory usage in a RemoteViews. * */ @@ -2417,6 +2496,9 @@ public class RemoteViews implements Parcelable, Filter { case LAYOUT_PARAM_ACTION_TAG: mActions.add(new LayoutParamAction(parcel)); break; + case OVERRIDE_TEXT_COLORS_TAG: + mActions.add(new OverrideTextColorsAction(parcel)); + break; default: throw new ActionException("Tag " + tag + " not found"); } @@ -2429,6 +2511,7 @@ public class RemoteViews implements Parcelable, Filter { mApplication = mPortrait.mApplication; mLayoutId = mPortrait.getLayoutId(); } + mReapplyDisallowed = parcel.readInt() == 0; // setup the memory usage statistics mMemoryUsageCounter = new MemoryUsageCounter(); @@ -2582,7 +2665,7 @@ public class RemoteViews implements Parcelable, Filter { * given {@link RemoteViews}. * * @param viewId The id of the parent {@link ViewGroup} to add the child into. - * @param nestedView {@link RemoveViews} of the child to add. + * @param nestedView {@link RemoteViews} of the child to add. * @param index The position at which to add the child. * * @hide @@ -3738,6 +3821,7 @@ public class RemoteViews implements Parcelable, Filter { // Both RemoteViews already share the same package and user mPortrait.writeToParcel(dest, flags | PARCELABLE_ELIDE_DUPLICATES); } + dest.writeInt(mReapplyDisallowed ? 1 : 0); } private static ApplicationInfo getApplicationInfo(String packageName, int userId) { diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java index 240271e5906a..cbb8d885837f 100644 --- a/core/java/android/widget/SelectionActionModeHelper.java +++ b/core/java/android/widget/SelectionActionModeHelper.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UiThread; import android.annotation.WorkerThread; +import android.graphics.PointF; import android.graphics.RectF; import android.os.AsyncTask; import android.os.LocaleList; @@ -27,13 +28,13 @@ import android.text.Layout; import android.text.Selection; import android.text.Spannable; import android.text.TextUtils; -import android.util.Pair; import android.view.ActionMode; import android.view.textclassifier.TextClassification; import android.view.textclassifier.TextClassifier; import android.view.textclassifier.TextSelection; import android.widget.Editor.SelectionModifierCursorController; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; import java.util.ArrayList; @@ -45,8 +46,10 @@ import java.util.function.Supplier; /** * Helper class for starting selection action mode * (synchronously without the TextClassifier, asynchronously with the TextClassifier). + * @hide */ @UiThread +@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) final class SelectionActionModeHelper { /** @@ -55,7 +58,7 @@ final class SelectionActionModeHelper { // TODO: Consider making this a ViewConfiguration. private static final int TIMEOUT_DURATION = 200; - private static final boolean SMART_SELECT_ANIMATION_ENABLED = false; + private static final boolean SMART_SELECT_ANIMATION_ENABLED = true; private final Editor mEditor; private final TextClassificationHelper mTextClassificationHelper; @@ -189,8 +192,8 @@ final class SelectionActionModeHelper { final Runnable onAnimationEndCallback = () -> startActionMode(result); // TODO do not trigger the animation if the change included only non-printable characters final boolean didSelectionChange = - textView.getSelectionStart() != result.mStart - || textView.getSelectionEnd() != result.mEnd; + result != null && (textView.getSelectionStart() != result.mStart + || textView.getSelectionEnd() != result.mEnd); if (!didSelectionChange) { onAnimationEndCallback.run(); @@ -201,6 +204,17 @@ final class SelectionActionModeHelper { convertSelectionToRectangles(layout, result.mStart, result.mEnd); /* + * Do not run the Smart Select animation when there are multiple lines involved, as this + * behavior is currently broken. + * + * TODO fix Smart Select Animation when the selection spans multiple lines + */ + if (selectionRectangles.size() != 1) { + onAnimationEndCallback.run(); + return; + } + + /* * TODO Figure out a more robust approach for this * We have to translate all the generated rectangles by the top-left padding of the * TextView because the padding influences the rendering of the ViewOverlay, but is not @@ -213,18 +227,15 @@ final class SelectionActionModeHelper { rectangle.bottom += textView.getPaddingTop(); } - final RectF firstRectangle = selectionRectangles.get(0); + final PointF touchPoint = new PointF( + mEditor.getLastUpPositionX(), + mEditor.getLastUpPositionY()); - // TODO use the original touch point instead of the hardcoded point generated here - final Pair<Float, Float> halfPoint = new Pair<>( - firstRectangle.centerX(), - firstRectangle.centerY()); + final PointF animationStartPoint = + movePointInsideNearestRectangle(touchPoint, selectionRectangles); mSmartSelectSprite.startAnimation( - // TODO replace with colorControlActivated taken from the view attributes - // Color GBLUE700 - 0xFF3367D6, - halfPoint, + animationStartPoint, selectionRectangles, onAnimationEndCallback); } @@ -237,9 +248,45 @@ final class SelectionActionModeHelper { // with the Smart Select animation layout.getSelection(start, end, (left, top, right, bottom) -> result.add(new RectF(left, top, right, bottom))); + + result.sort(SmartSelectSprite.RECTANGLE_COMPARATOR); + return result; } + /** @hide */ + @VisibleForTesting + public static PointF movePointInsideNearestRectangle(final PointF point, + final List<RectF> rectangles) { + float bestX = -1; + float bestY = -1; + double bestDistance = Double.MAX_VALUE; + + for (final RectF rectangle : rectangles) { + final float candidateY = rectangle.centerY(); + final float candidateX; + + if (point.x > rectangle.right) { + candidateX = rectangle.right; + } else if (point.x < rectangle.left) { + candidateX = rectangle.left; + } else { + candidateX = point.x; + } + + final double candidateDistance = Math.pow(point.x - candidateX, 2) + + Math.pow(point.y - candidateY, 2); + + if (candidateDistance < bestDistance) { + bestX = candidateX; + bestY = candidateY; + bestDistance = candidateDistance; + } + } + + return new PointF(bestX, bestY); + } + private void invalidateActionMode(@Nullable SelectionResult result) { cancelSmartSelectAnimation(); mTextClassification = result != null ? result.mClassification : null; diff --git a/core/java/android/widget/SmartSelectSprite.java b/core/java/android/widget/SmartSelectSprite.java index 5eed985c36e7..45466c225e14 100644 --- a/core/java/android/widget/SmartSelectSprite.java +++ b/core/java/android/widget/SmartSelectSprite.java @@ -26,14 +26,15 @@ import android.annotation.ColorInt; import android.annotation.FloatRange; import android.annotation.IntDef; import android.content.Context; +import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; +import android.graphics.PointF; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.graphics.drawable.ShapeDrawable; import android.graphics.drawable.shapes.Shape; -import android.util.Pair; import android.util.TypedValue; import android.view.View; import android.view.ViewOverlay; @@ -59,14 +60,25 @@ final class SmartSelectSprite { private static final int CORNER_DURATION = 150; private static final float STROKE_WIDTH_DP = 1.5F; private static final int POINTS_PER_LINE = 4; + + // GBLUE700 + @ColorInt + private static final int DEFAULT_STROKE_COLOR = 0xFF3367D6; + private final Interpolator mExpandInterpolator; private final Interpolator mCornerInterpolator; private final float mStrokeWidth; private final View mView; private Animator mActiveAnimator = null; + @ColorInt + private final int mStrokeColor; private Set<Drawable> mExistingAnimationDrawables = new HashSet<>(); + static final Comparator<RectF> RECTANGLE_COMPARATOR = Comparator + .<RectF>comparingDouble(e -> e.bottom) + .thenComparingDouble(e -> e.left); + /** * Represents a set of points connected by lines. */ @@ -74,16 +86,16 @@ final class SmartSelectSprite { private final float[] mLineCoordinates; - private PolygonShape(final List<Pair<Float, Float>> points) { + private PolygonShape(final List<PointF> points) { mLineCoordinates = new float[points.size() * POINTS_PER_LINE]; int index = 0; - Pair<Float, Float> currentPoint = points.get(0); - for (final Pair<Float, Float> nextPoint : points) { - mLineCoordinates[index] = currentPoint.first; - mLineCoordinates[index + 1] = currentPoint.second; - mLineCoordinates[index + 2] = nextPoint.first; - mLineCoordinates[index + 3] = nextPoint.second; + PointF currentPoint = points.get(0); + for (final PointF nextPoint : points) { + mLineCoordinates[index] = currentPoint.x; + mLineCoordinates[index + 1] = currentPoint.y; + mLineCoordinates[index + 2] = nextPoint.x; + mLineCoordinates[index + 3] = nextPoint.y; index += POINTS_PER_LINE; currentPoint = nextPoint; @@ -102,7 +114,7 @@ final class SmartSelectSprite { */ private static final class RoundedRectangleShape extends Shape { - private static final String PROPERTY_ROUND_PERCENTAGE = "roundPercentage"; + private static final String PROPERTY_ROUND_RATIO = "roundRatio"; @Retention(SOURCE) @IntDef({ExpansionDirection.LEFT, ExpansionDirection.CENTER, ExpansionDirection.RIGHT}) @@ -126,7 +138,7 @@ final class SmartSelectSprite { private final float mStrokeWidth; private final RectF mBoundingRectangle; - private float mRoundPercentage = 1.0f; + private float mRoundRatio = 1.0f; private final @ExpansionDirection int mExpansionDirection; private final @RectangleBorderType int mRectangleBorderType; @@ -148,6 +160,12 @@ final class SmartSelectSprite { mExpansionDirection = expansionDirection; mRectangleBorderType = rectangleBorderType; mStrokeWidth = strokeWidth; + + if (boundingRectangle.height() > boundingRectangle.width()) { + setRoundRatio(0.0f); + } else { + setRoundRatio(1.0f); + } } /* @@ -187,10 +205,7 @@ final class SmartSelectSprite { canvas.save(); mClipRect.set(mBoundingRectangle); - mClipRect.top -= mStrokeWidth; - mClipRect.bottom += mStrokeWidth; - mClipRect.left -= mStrokeWidth; - mClipRect.right += mStrokeWidth; + mClipRect.inset(-mStrokeWidth, -mStrokeWidth); canvas.clipRect(mClipRect); canvas.drawRoundRect(mDrawRect, adjustedCornerRadius, adjustedCornerRadius, paint); canvas.restore(); @@ -207,9 +222,12 @@ final class SmartSelectSprite { canvas.restore(); } - public void setRoundPercentage( - @FloatRange(from = 0.0, to = 1.0) final float newPercentage) { - mRoundPercentage = newPercentage; + public void setRoundRatio(@FloatRange(from = 0.0, to = 1.0) final float roundRatio) { + mRoundRatio = roundRatio; + } + + public float getRoundRatio() { + return mRoundRatio; } private void setLeftBoundary(final float leftBoundary) { @@ -225,7 +243,7 @@ final class SmartSelectSprite { } private float getAdjustedCornerRadius() { - return (getCornerRadius() * mRoundPercentage); + return (getCornerRadius() * mRoundRatio); } private float getBoundingWidth() { @@ -252,13 +270,6 @@ final class SmartSelectSprite { private RectangleList(List<RoundedRectangleShape> rectangles) { mRectangles = new LinkedList<>(rectangles); - mRectangles.sort((o1, o2) -> { - if (o1.mBoundingRectangle.top == o2.mBoundingRectangle.top) { - return Float.compare(o1.mBoundingRectangle.left, o2.mBoundingRectangle.left); - } else { - return Float.compare(o1.mBoundingRectangle.top, o2.mBoundingRectangle.top); - } - }); mReversedRectangles = new LinkedList<>(rectangles); Collections.reverse(mReversedRectangles); } @@ -322,6 +333,7 @@ final class SmartSelectSprite { context, android.R.interpolator.fast_out_linear_in); mStrokeWidth = dpToPixel(context, STROKE_WIDTH_DP); + mStrokeColor = getStrokeColor(context); mView = view; } @@ -333,9 +345,9 @@ final class SmartSelectSprite { final List<RectF> rectangles, final int color) { final List<Drawable> drawables = new LinkedList<>(); - final Set<List<Pair<Float, Float>>> mergedPaths = calculateMergedPolygonPoints(rectangles); + final Set<List<PointF>> mergedPaths = calculateMergedPolygonPoints(rectangles); - for (List<Pair<Float, Float>> path : mergedPaths) { + for (List<PointF> path : mergedPaths) { // Add the starting point to the end of the polygon so that it ends up closed. path.add(path.get(0)); @@ -352,7 +364,7 @@ final class SmartSelectSprite { return drawables; } - private static Set<List<Pair<Float, Float>>> calculateMergedPolygonPoints( + private static Set<List<PointF>> calculateMergedPolygonPoints( List<RectF> rectangles) { final Set<List<RectF>> partitions = new HashSet<>(); final LinkedList<RectF> listOfRects = new LinkedList<>(rectangles); @@ -380,20 +392,20 @@ final class SmartSelectSprite { partitions.add(partition); } - final Set<List<Pair<Float, Float>>> result = new HashSet<>(); + final Set<List<PointF>> result = new HashSet<>(); for (List<RectF> partition : partitions) { - final List<Pair<Float, Float>> points = new LinkedList<>(); + final List<PointF> points = new LinkedList<>(); final Stack<RectF> rects = new Stack<>(); for (RectF rect : partition) { - points.add(new Pair<>(rect.right, rect.top)); - points.add(new Pair<>(rect.right, rect.bottom)); + points.add(new PointF(rect.right, rect.top)); + points.add(new PointF(rect.right, rect.bottom)); rects.add(rect); } while (!rects.isEmpty()) { final RectF rect = rects.pop(); - points.add(new Pair<>(rect.left, rect.bottom)); - points.add(new Pair<>(rect.left, rect.top)); + points.add(new PointF(rect.left, rect.bottom)); + points.add(new PointF(rect.left, rect.top)); } result.add(points); @@ -406,11 +418,12 @@ final class SmartSelectSprite { /** * Performs the Smart Select animation on the view bound to this SmartSelectSprite. * - * @param color The color of the stroke used. * @param start The point from which the animation will start. Must be inside * destinationRectangles. * @param destinationRectangles The rectangles which the animation will fill out by its - * "selection" and finally join them into a single polygon. + * "selection" and finally join them into a single polygon. In + * order to get the correct visual behavior, these rectangles + * should be sorted according to {@link #RECTANGLE_COMPARATOR}. * @param onAnimationEnd The callback which will be invoked once the whole animation * completes. * @throws IllegalArgumentException if the given start point is not in any of the @@ -418,8 +431,7 @@ final class SmartSelectSprite { * @see #cancelAnimation() */ public void startAnimation( - final @ColorInt int color, - final Pair<Float, Float> start, + final PointF start, final List<RectF> destinationRectangles, final Runnable onAnimationEnd) throws IllegalArgumentException { cancelAnimation(); @@ -432,7 +444,7 @@ final class SmartSelectSprite { final RectF centerRectangle = destinationRectangles .stream() - .filter((r) -> r.contains(start.first, start.second)) + .filter((r) -> contains(r, start)) .findFirst() .orElseThrow(() -> new IllegalArgumentException( "Center point is not inside any of the rectangles!")); @@ -445,7 +457,7 @@ final class SmartSelectSprite { startingOffset += rectangle.width(); } - startingOffset += start.first - centerRectangle.left; + startingOffset += start.x - centerRectangle.left; final float centerRectangleHalfHeight = centerRectangle.height() / 2; final float startingOffsetLeft = startingOffset - centerRectangleHalfHeight; @@ -474,13 +486,13 @@ final class SmartSelectSprite { final ShapeDrawable shapeDrawable = new ShapeDrawable(rectangleList); final Paint paint = shapeDrawable.getPaint(); - paint.setColor(color); + paint.setColor(mStrokeColor); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(mStrokeWidth); addToOverlay(shapeDrawable); - mActiveAnimator = createAnimator(color, destinationRectangles, rectangleList, + mActiveAnimator = createAnimator(mStrokeColor, destinationRectangles, rectangleList, startingOffsetLeft, startingOffsetRight, cornerAnimators, updateListener, onAnimationEnd); mActiveAnimator.start(); @@ -569,8 +581,8 @@ final class SmartSelectSprite { final ValueAnimator.AnimatorUpdateListener listener) { final ObjectAnimator animator = ObjectAnimator.ofFloat( shape, - RoundedRectangleShape.PROPERTY_ROUND_PERCENTAGE, - 1.0F, 0.0F); + RoundedRectangleShape.PROPERTY_ROUND_RATIO, + shape.getRoundRatio(), 0.0F); animator.setDuration(CORNER_DURATION); animator.addUpdateListener(listener); animator.setInterpolator(mCornerInterpolator); @@ -578,8 +590,7 @@ final class SmartSelectSprite { } private static @RoundedRectangleShape.ExpansionDirection int[] generateDirections( - final RectF centerRectangle, - final List<RectF> rectangles) throws IllegalArgumentException { + final RectF centerRectangle, final List<RectF> rectangles) { final @RoundedRectangleShape.ExpansionDirection int[] result = new int[rectangles.size()]; final int centerRectangleIndex = rectangles.indexOf(centerRectangle); @@ -587,7 +598,17 @@ final class SmartSelectSprite { for (int i = 0; i < centerRectangleIndex - 1; ++i) { result[i] = RoundedRectangleShape.ExpansionDirection.LEFT; } - result[centerRectangleIndex] = RoundedRectangleShape.ExpansionDirection.CENTER; + + if (rectangles.size() == 1) { + result[centerRectangleIndex] = RoundedRectangleShape.ExpansionDirection.CENTER; + } else if (centerRectangleIndex == 0) { + result[centerRectangleIndex] = RoundedRectangleShape.ExpansionDirection.LEFT; + } else if (centerRectangleIndex == rectangles.size() - 1) { + result[centerRectangleIndex] = RoundedRectangleShape.ExpansionDirection.RIGHT; + } else { + result[centerRectangleIndex] = RoundedRectangleShape.ExpansionDirection.CENTER; + } + for (int i = centerRectangleIndex + 1; i < result.length; ++i) { result[i] = RoundedRectangleShape.ExpansionDirection.RIGHT; } @@ -615,6 +636,31 @@ final class SmartSelectSprite { context.getResources().getDisplayMetrics()); } + @ColorInt + private static int getStrokeColor(final Context context) { + final TypedValue typedValue = new TypedValue(); + final TypedArray array = context.obtainStyledAttributes(typedValue.data, new int[]{ + android.R.attr.colorControlActivated}); + final int result = array.getColor(0, DEFAULT_STROKE_COLOR); + array.recycle(); + return result; + } + + /** + * A variant of {@link RectF#contains(float, float)} that also allows the point to reside on + * the right boundary of the rectangle. + * + * @param rectangle the rectangle inside which the point should be to be considered "contained" + * @param point the point which will be tested + * @return whether the point is inside the rectangle (or on it's right boundary) + */ + private static boolean contains(final RectF rectangle, final PointF point) { + final float x = point.x; + final float y = point.y; + return x >= rectangle.left && x <= rectangle.right && y >= rectangle.top + && y <= rectangle.bottom; + } + private void addToOverlay(final Drawable drawable) { mView.getOverlay().add(drawable); mExistingAnimationDrawables.add(drawable); diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java index 40253a187177..2e1e96365f2a 100644 --- a/core/java/android/widget/Switch.java +++ b/core/java/android/widget/Switch.java @@ -33,6 +33,7 @@ import android.graphics.Rect; import android.graphics.Region.Op; import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.os.Build.VERSION_CODES; import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; @@ -111,6 +112,7 @@ public class Switch extends CompoundButton { private CharSequence mTextOn; private CharSequence mTextOff; private boolean mShowText; + private boolean mUseFallbackLineSpacing; private int mTouchMode; private int mTouchSlop; @@ -246,6 +248,11 @@ public class Switch extends CompoundButton { com.android.internal.R.styleable.Switch_switchPadding, 0); mSplitTrack = a.getBoolean(com.android.internal.R.styleable.Switch_splitTrack, false); + // TODO: replace CUR_DEVELOPMENT with P once P is added to android.os.Build.VERSION_CODES. + // STOPSHIP if the above TODO is not done. + mUseFallbackLineSpacing = + context.getApplicationInfo().targetSdkVersion >= VERSION_CODES.CUR_DEVELOPMENT; + ColorStateList thumbTintList = a.getColorStateList( com.android.internal.R.styleable.Switch_thumbTint); if (thumbTintList != null) { @@ -894,8 +901,9 @@ public class Switch extends CompoundButton { int width = (int) Math.ceil(Layout.getDesiredWidth(transformed, 0, transformed.length(), mTextPaint, getTextDirectionHeuristic())); - return new StaticLayout(transformed, mTextPaint, width, - Layout.Alignment.ALIGN_NORMAL, 1.f, 0, true); + return StaticLayout.Builder.obtain(transformed, 0, transformed.length(), mTextPaint, width) + .setUseLineSpacingFromFallbacks(mUseFallbackLineSpacing) + .build(); } /** diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index bbfa6e04f85a..140ecc161057 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -650,6 +650,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private boolean mListenerChanged = false; // True if internationalized input should be used for numbers and date and time. private final boolean mUseInternationalizedInput; + // True if fallback fonts that end up getting used should be allowed to affect line spacing. + /* package */ final boolean mUseFallbackLineSpacing; @ViewDebug.ExportedProperty(category = "text") private int mGravity = Gravity.TOP | Gravity.START; @@ -1252,8 +1254,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final boolean numberPasswordInputType = variation == (EditorInfo.TYPE_CLASS_NUMBER | EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD); - mUseInternationalizedInput = - context.getApplicationInfo().targetSdkVersion >= VERSION_CODES.O; + final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion; + mUseInternationalizedInput = targetSdkVersion >= VERSION_CODES.O; + // TODO: replace CUR_DEVELOPMENT with P once P is added to android.os.Build.VERSION_CODES. + // STOPSHIP if the above TODO is not done. + mUseFallbackLineSpacing = targetSdkVersion >= VERSION_CODES.CUR_DEVELOPMENT; if (inputMethod != null) { Class<?> c; @@ -7914,6 +7919,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener .setTextDirection(mTextDir) .setLineSpacing(mSpacingAdd, mSpacingMult) .setIncludePad(mIncludePad) + .setUseLineSpacingFromFallbacks(mUseFallbackLineSpacing) .setBreakStrategy(mBreakStrategy) .setHyphenationFrequency(mHyphenationFrequency) .setJustificationMode(mJustificationMode) @@ -7956,10 +7962,20 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener boolean useSaved) { Layout result = null; if (mText instanceof Spannable) { - result = new DynamicLayout(mText, mTransformed, mTextPaint, wantWidth, - alignment, mTextDir, mSpacingMult, mSpacingAdd, mIncludePad, - mBreakStrategy, mHyphenationFrequency, mJustificationMode, - getKeyListener() == null ? effectiveEllipsize : null, ellipsisWidth); + final DynamicLayout.Builder builder = DynamicLayout.Builder.obtain(mText, mTextPaint, + wantWidth) + .setDisplayText(mTransformed) + .setAlignment(alignment) + .setTextDirection(mTextDir) + .setLineSpacing(mSpacingAdd, mSpacingMult) + .setIncludePad(mIncludePad) + .setUseLineSpacingFromFallbacks(mUseFallbackLineSpacing) + .setBreakStrategy(mBreakStrategy) + .setHyphenationFrequency(mHyphenationFrequency) + .setJustificationMode(mJustificationMode) + .setEllipsize(getKeyListener() == null ? effectiveEllipsize : null) + .setEllipsizedWidth(ellipsisWidth); + result = builder.build(); } else { if (boring == UNKNOWN_BORING) { boring = BoringLayout.isBoring(mTransformed, mTextPaint, mTextDir, mBoring); @@ -8006,6 +8022,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener .setTextDirection(mTextDir) .setLineSpacing(mSpacingAdd, mSpacingMult) .setIncludePad(mIncludePad) + .setUseLineSpacingFromFallbacks(mUseFallbackLineSpacing) .setBreakStrategy(mBreakStrategy) .setHyphenationFrequency(mHyphenationFrequency) .setJustificationMode(mJustificationMode) @@ -8365,6 +8382,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener layoutBuilder.setAlignment(getLayoutAlignment()) .setLineSpacing(getLineSpacingExtra(), getLineSpacingMultiplier()) .setIncludePad(getIncludeFontPadding()) + .setUseLineSpacingFromFallbacks(mUseFallbackLineSpacing) .setBreakStrategy(getBreakStrategy()) .setHyphenationFrequency(getHyphenationFrequency()) .setJustificationMode(getJustificationMode()) @@ -10761,13 +10779,18 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mEditor.mProcessTextIntentActionsHandler.initializeAccessibilityActions(); } + super.sendAccessibilityEventInternal(eventType); + } + + @Override + public void sendAccessibilityEventUnchecked(AccessibilityEvent event) { // Do not send scroll events since first they are not interesting for // accessibility and second such events a generated too frequently. // For details see the implementation of bringTextIntoView(). - if (eventType == AccessibilityEvent.TYPE_VIEW_SCROLLED) { + if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) { return; } - super.sendAccessibilityEventInternal(eventType); + super.sendAccessibilityEventUnchecked(event); } /** diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java index de289bb9a27a..ae6881e4e28c 100644 --- a/core/java/android/widget/TimePicker.java +++ b/core/java/android/widget/TimePicker.java @@ -366,8 +366,11 @@ public class TimePicker extends FrameLayout { void setMinute(@IntRange(from = 0, to = 59) int minute); int getMinute(); - void setDate(long date); - long getDate(); + void setDate(@IntRange(from = 0, to = 23) int hour, + @IntRange(from = 0, to = 59) int minute); + + void autofill(AutofillValue value); + AutofillValue getAutofillValue(); void setIs24Hour(boolean is24Hour); boolean is24Hour(); @@ -422,6 +425,11 @@ public class TimePicker extends FrameLayout { protected OnTimeChangedListener mOnTimeChangedListener; protected OnTimeChangedListener mAutoFillChangeListener; + // The value that was passed to autofill() - it must be stored because it getAutofillValue() + // must return the exact same value that was autofilled, otherwise the widget will not be + // properly highlighted after autofill(). + private long mAutofilledValue; + public AbstractTimePickerDelegate(@NonNull TimePicker delegator, @NonNull Context context) { mDelegator = delegator; mContext = context; @@ -439,19 +447,41 @@ public class TimePicker extends FrameLayout { } @Override - public void setDate(long date) { - Calendar cal = Calendar.getInstance(mLocale); - cal.setTimeInMillis(date); - setHour(cal.get(Calendar.HOUR_OF_DAY)); - setMinute(cal.get(Calendar.MINUTE)); + public final void autofill(AutofillValue value) { + if (value == null || !value.isDate()) { + Log.w(LOG_TAG, value + " could not be autofilled into " + this); + return; + } + + final long time = value.getDateValue(); + + final Calendar cal = Calendar.getInstance(mLocale); + cal.setTimeInMillis(time); + setDate(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE)); + + // Must set mAutofilledValue *after* calling subclass method to make sure the value + // returned by getAutofillValue() matches it. + mAutofilledValue = time; } @Override - public long getDate() { - Calendar cal = Calendar.getInstance(mLocale); + public final AutofillValue getAutofillValue() { + if (mAutofilledValue != 0) { + return AutofillValue.forDate(mAutofilledValue); + } + + final Calendar cal = Calendar.getInstance(mLocale); cal.set(Calendar.HOUR_OF_DAY, getHour()); cal.set(Calendar.MINUTE, getMinute()); - return cal.getTimeInMillis(); + return AutofillValue.forDate(cal.getTimeInMillis()); + } + + /** + * This method must be called every time the value of the hour and/or minute is changed by + * a subclass method. + */ + protected void resetAutofilledValue() { + mAutofilledValue = 0; } protected static class SavedState extends View.BaseSavedState { @@ -532,12 +562,7 @@ public class TimePicker extends FrameLayout { public void autofill(AutofillValue value) { if (!isEnabled()) return; - if (!value.isDate()) { - Log.w(LOG_TAG, value + " could not be autofilled into " + this); - return; - } - - mDelegate.setDate(value.getDateValue()); + mDelegate.autofill(value); } @Override @@ -547,6 +572,6 @@ public class TimePicker extends FrameLayout { @Override public AutofillValue getAutofillValue() { - return isEnabled() ? AutofillValue.forDate(mDelegate.getDate()) : null; + return isEnabled() ? mDelegate.getAutofillValue() : null; } } diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java index 526246b28530..706b0ce225dc 100644 --- a/core/java/android/widget/TimePickerClockDelegate.java +++ b/core/java/android/widget/TimePickerClockDelegate.java @@ -506,19 +506,29 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { mAmPmLayout.setLayoutParams(params); } + @Override + public void setDate(int hour, int minute) { + setHourInternal(hour, FROM_EXTERNAL_API, true, false); + setMinuteInternal(minute, FROM_EXTERNAL_API, false); + + onTimeChanged(); + } + /** * Set the current hour. */ @Override public void setHour(int hour) { - setHourInternal(hour, FROM_EXTERNAL_API, true); + setHourInternal(hour, FROM_EXTERNAL_API, true, true); } - private void setHourInternal(int hour, @ChangeSource int source, boolean announce) { + private void setHourInternal(int hour, @ChangeSource int source, boolean announce, + boolean notify) { if (mCurrentHour == hour) { return; } + resetAutofilledValue(); mCurrentHour = hour; updateHeaderHour(hour, announce); updateHeaderAmPm(); @@ -532,7 +542,9 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { } mDelegator.invalidate(); - onTimeChanged(); + if (notify) { + onTimeChanged(); + } } /** @@ -557,14 +569,15 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { */ @Override public void setMinute(int minute) { - setMinuteInternal(minute, FROM_EXTERNAL_API); + setMinuteInternal(minute, FROM_EXTERNAL_API, true); } - private void setMinuteInternal(int minute, @ChangeSource int source) { + private void setMinuteInternal(int minute, @ChangeSource int source, boolean notify) { if (mCurrentMinute == minute) { return; } + resetAutofilledValue(); mCurrentMinute = minute; updateHeaderMinute(minute, true); @@ -576,7 +589,9 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { } mDelegator.invalidate(); - onTimeChanged(); + if (notify) { + onTimeChanged(); + } } /** @@ -870,7 +885,7 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { valueChanged = true; } final boolean isTransition = mAllowAutoAdvance && autoAdvance; - setHourInternal(newValue, FROM_RADIAL_PICKER, !isTransition); + setHourInternal(newValue, FROM_RADIAL_PICKER, !isTransition, true); if (isTransition) { setCurrentItemShowing(MINUTE_INDEX, true, false); @@ -882,7 +897,7 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { if (getMinute() != newValue) { valueChanged = true; } - setMinuteInternal(newValue, FROM_RADIAL_PICKER); + setMinuteInternal(newValue, FROM_RADIAL_PICKER, true); break; } @@ -897,10 +912,10 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { public void onValueChanged(int pickerType, int newValue) { switch (pickerType) { case TextInputTimePickerView.HOURS: - setHourInternal(newValue, FROM_INPUT_PICKER, false); + setHourInternal(newValue, FROM_INPUT_PICKER, false, true); break; case TextInputTimePickerView.MINUTES: - setMinuteInternal(newValue, FROM_INPUT_PICKER); + setMinuteInternal(newValue, FROM_INPUT_PICKER, true); break; case TextInputTimePickerView.AMPM: setAmOrPm(newValue); diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java index 7a7d9a948dcc..cc79b9c85784 100644 --- a/core/java/android/widget/TimePickerSpinnerDelegate.java +++ b/core/java/android/widget/TimePickerSpinnerDelegate.java @@ -284,6 +284,14 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate { } @Override + public void setDate(int hour, int minute) { + setCurrentHour(hour, false); + setCurrentMinute(minute, false); + + onTimeChanged(); + } + + @Override public void setHour(int hour) { setCurrentHour(hour, true); } @@ -293,6 +301,7 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate { if (currentHour == getHour()) { return; } + resetAutofilledValue(); if (!is24Hour()) { // convert [0,23] ordinal to wall clock display if (currentHour >= HOURS_IN_HALF_DAY) { @@ -328,11 +337,18 @@ class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate { @Override public void setMinute(int minute) { + setCurrentMinute(minute, true); + } + + private void setCurrentMinute(int minute, boolean notifyTimeChanged) { if (minute == getMinute()) { return; } + resetAutofilledValue(); mMinuteSpinner.setValue(minute); - onTimeChanged(); + if (notifyTimeChanged) { + onTimeChanged(); + } } @Override diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 5c1bafdbca3f..ceb06f511108 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -36,6 +36,7 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; +import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.net.Uri; @@ -50,6 +51,7 @@ import android.os.UserManager; import android.provider.MediaStore; import android.provider.Settings; import android.text.TextUtils; +import android.util.IconDrawableFactory; import android.util.Log; import android.util.Slog; import android.view.LayoutInflater; @@ -120,6 +122,8 @@ public class ResolverActivity extends Activity { /** See {@link #setRetainInOnStop}. */ private boolean mRetainInOnStop; + IconDrawableFactory mIconFactory; + private final PackageMonitor mPackageMonitor = new PackageMonitor() { @Override public void onSomePackagesChanged() { mAdapter.handlePackagesChanged(); @@ -330,6 +334,13 @@ public class ResolverActivity extends Activity { : MetricsProto.MetricsEvent.ACTION_SHOW_APP_DISAMBIG_NONE_FEATURED, intent.getAction() + ":" + intent.getType() + ":" + (categories != null ? Arrays.toString(categories.toArray()) : "")); + mIconFactory = IconDrawableFactory.newInstance(this, true); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + mAdapter.handlePackagesChanged(); } /** @@ -468,20 +479,20 @@ public class ResolverActivity extends Activity { if (ri.resolvePackageName != null && ri.icon != 0) { dr = getIcon(mPm.getResourcesForApplication(ri.resolvePackageName), ri.icon); if (dr != null) { - return dr; + return mIconFactory.getShadowedIcon(dr); } } final int iconRes = ri.getIconResource(); if (iconRes != 0) { dr = getIcon(mPm.getResourcesForApplication(ri.activityInfo.packageName), iconRes); if (dr != null) { - return dr; + return mIconFactory.getShadowedIcon(dr); } } } catch (NameNotFoundException e) { Log.e(TAG, "Couldn't find resources for package", e); } - return ri.loadIcon(mPm); + return mIconFactory.getBadgedIcon(ri.activityInfo.applicationInfo); } @Override @@ -1930,7 +1941,8 @@ public class ResolverActivity extends Activity { final int checkedPos = mAdapterView.getCheckedItemPosition(); final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION; if (!useLayoutWithDefault() - && (!hasValidSelection || mLastSelected != checkedPos)) { + && (!hasValidSelection || mLastSelected != checkedPos) + && mAlwaysButton != null) { setAlwaysButtonEnabled(hasValidSelection, checkedPos, true); mOnceButton.setEnabled(hasValidSelection); if (hasValidSelection) { diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java index 378826dc1deb..77cfc2fc5bd4 100644 --- a/core/java/com/android/internal/app/ResolverComparator.java +++ b/core/java/com/android/internal/app/ResolverComparator.java @@ -337,11 +337,13 @@ class ResolverComparator implements Comparator<ResolvedComponentInfo> { final ResolverTarget rhsTarget = mTargetsDict.get(new ComponentName( rhs.activityInfo.packageName, rhs.activityInfo.name)); - final int selectProbabilityDiff = Float.compare( + if (lhsTarget != null && rhsTarget != null) { + final int selectProbabilityDiff = Float.compare( rhsTarget.getSelectProbability(), lhsTarget.getSelectProbability()); - if (selectProbabilityDiff != 0) { - return selectProbabilityDiff > 0 ? 1 : -1; + if (selectProbabilityDiff != 0) { + return selectProbabilityDiff > 0 ? 1 : -1; + } } } } diff --git a/core/java/com/android/internal/colorextraction/ColorExtractor.java b/core/java/com/android/internal/colorextraction/ColorExtractor.java index ef98a5e9f787..c171fa6b25fd 100644 --- a/core/java/com/android/internal/colorextraction/ColorExtractor.java +++ b/core/java/com/android/internal/colorextraction/ColorExtractor.java @@ -80,7 +80,7 @@ public class ColorExtractor implements WallpaperManager.OnColorsChangedListener if (wallpaperManager == null) { Log.w(TAG, "Can't listen to color changes!"); } else { - wallpaperManager.addOnColorsChangedListener(this); + wallpaperManager.addOnColorsChangedListener(this, null /* handler */); // Initialize all gradients with the current colors Trace.beginSection("ColorExtractor#getWallpaperColors"); diff --git a/core/java/com/android/internal/colorextraction/types/Tonal.java b/core/java/com/android/internal/colorextraction/types/Tonal.java index dbc086c21304..e6ef10b3b7c6 100644 --- a/core/java/com/android/internal/colorextraction/types/Tonal.java +++ b/core/java/com/android/internal/colorextraction/types/Tonal.java @@ -111,18 +111,19 @@ public class Tonal implements ExtractionType { final List<Color> mainColors = inWallpaperColors.getMainColors(); final int mainColorsSize = mainColors.size(); - final boolean supportsDarkText = (inWallpaperColors.getColorHints() & - WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0; + final int hints = inWallpaperColors.getColorHints(); + final boolean supportsDarkText = (hints & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0; + final boolean generatedFromBitmap = (hints & WallpaperColors.HINT_FROM_BITMAP) != 0; if (mainColorsSize == 0) { return false; } - // Tonal is not really a sort, it takes a color from the extracted - // palette and finds a best fit amongst a collection of pre-defined - // palettes. The best fit is tweaked to be closer to the source color - // and replaces the original palette - // Get the most preeminent, non-blacklisted color. + // Decide what's the best color to use. + // We have 2 options: + // • Just pick the primary color + // • Filter out blacklisted colors. This is useful when palette is generated + // automatically from a bitmap. Color bestColor = null; final float[] hsl = new float[3]; for (int i = 0; i < mainColorsSize; i++) { @@ -132,7 +133,7 @@ public class Tonal implements ExtractionType { Color.blue(colorValue), hsl); // Stop when we find a color that meets our criteria - if (!isBlacklisted(hsl)) { + if (!generatedFromBitmap || !isBlacklisted(hsl)) { bestColor = color; break; } @@ -143,6 +144,10 @@ public class Tonal implements ExtractionType { return false; } + // Tonal is not really a sort, it takes a color from the extracted + // palette and finds a best fit amongst a collection of pre-defined + // palettes. The best fit is tweaked to be closer to the source color + // and replaces the original palette. int colorValue = bestColor.toArgb(); ColorUtils.RGBToHSL(Color.red(colorValue), Color.green(colorValue), Color.blue(colorValue), hsl); diff --git a/core/java/com/android/internal/net/OWNERS b/core/java/com/android/internal/net/OWNERS new file mode 100644 index 000000000000..7cb32ff793e7 --- /dev/null +++ b/core/java/com/android/internal/net/OWNERS @@ -0,0 +1,6 @@ +set noparent + +ek@google.com +hugobenichi@google.com +jsharkey@google.com +lorenzo@google.com diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java index d327180c6e9d..d64c9a1d813b 100644 --- a/core/java/com/android/internal/notification/SystemNotificationChannels.java +++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java @@ -132,10 +132,12 @@ public class SystemNotificationChannels { context.getString(R.string.notification_channel_usb), NotificationManager.IMPORTANCE_MIN)); - channelsList.add(new NotificationChannel( + NotificationChannel foregroundChannel = new NotificationChannel( FOREGROUND_SERVICE, context.getString(R.string.notification_channel_foreground_service), - NotificationManager.IMPORTANCE_LOW)); + NotificationManager.IMPORTANCE_LOW); + foregroundChannel.setBlockableSystem(true); + channelsList.add(foregroundChannel); nm.createNotificationChannels(channelsList); } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 75978cd25b78..c58ff0590dfa 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -1846,6 +1846,7 @@ public class BatteryStatsImpl extends BatteryStats { super(clocks, uid, type, timerPool, timeBase, in); mMaxDurationMs = in.readLong(); mTotalDurationMs = in.readLong(); + mCurrentDurationMs = in.readLong(); } public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, @@ -1857,7 +1858,8 @@ public class BatteryStatsImpl extends BatteryStats { public void writeToParcel(Parcel out, long elapsedRealtimeUs) { super.writeToParcel(out, elapsedRealtimeUs); out.writeLong(getMaxDurationMsLocked(elapsedRealtimeUs / 1000)); - out.writeLong(getTotalDurationMsLocked(elapsedRealtimeUs / 1000)); + out.writeLong(mTotalDurationMs); + out.writeLong(getCurrentDurationMsLocked(elapsedRealtimeUs / 1000)); } /** @@ -1988,6 +1990,10 @@ public class BatteryStatsImpl extends BatteryStats { * * Note that this time is NOT split between the timers in the timer group that * this timer is attached to. It is the TOTAL time. + * + * Note that if running timer is parceled and unparceled, this method will return + * current duration value at the time of parceling even though timer may not be + * currently running. */ @Override public long getCurrentDurationMsLocked(long elapsedRealtimeMs) { diff --git a/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java index 7cd4fd24fa0e..8884d24ff0ac 100644 --- a/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java +++ b/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java @@ -46,6 +46,7 @@ import java.io.IOException; * delta. */ public class KernelUidCpuFreqTimeReader { + private static final boolean DEBUG = false; private static final String TAG = "KernelUidCpuFreqTimeReader"; private static final String UID_TIMES_PROC_FILE = "/proc/uid_time_in_state"; @@ -165,14 +166,18 @@ public class KernelUidCpuFreqTimeReader { // If there is malformed data for any uid, then we just log about it and ignore // the data for that uid. if (deltaUidTimeMs[i] < 0 || totalTimeMs < 0) { - final StringBuilder sb = new StringBuilder("Malformed cpu freq data for UID=") - .append(uid).append("\n"); - sb.append("data=").append("(").append(uidTimeMs[i]).append(",") - .append(totalTimeMs).append(")").append("\n"); - sb.append("times=").append("("); - TimeUtils.formatDuration(mLastTimeReadMs, sb); sb.append(","); - TimeUtils.formatDuration(mNowTimeMs, sb); sb.append(")"); - Slog.wtf(TAG, sb.toString()); + if (DEBUG) { + final StringBuilder sb = new StringBuilder("Malformed cpu freq data for UID=") + .append(uid).append("\n"); + sb.append("data=").append("(").append(uidTimeMs[i]).append(",") + .append(totalTimeMs).append(")").append("\n"); + sb.append("times=").append("("); + TimeUtils.formatDuration(mLastTimeReadMs, sb); + sb.append(","); + TimeUtils.formatDuration(mNowTimeMs, sb); + sb.append(")"); + Slog.e(TAG, sb.toString()); + } return; } curUidTimeMs[i] = totalTimeMs; diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java index 51cf2eae851f..872b465a9ca5 100644 --- a/core/java/com/android/internal/os/PowerProfile.java +++ b/core/java/com/android/internal/os/PowerProfile.java @@ -205,13 +205,17 @@ public class PowerProfile { private static final String TAG_ARRAYITEM = "value"; private static final String ATTR_NAME = "name"; + private static final Object sLock = new Object(); + public PowerProfile(Context context) { // Read the XML file for the given profile (normally only one per // device) - if (sPowerMap.size() == 0) { - readPowerValuesFromXml(context); + synchronized (sLock) { + if (sPowerMap.size() == 0) { + readPowerValuesFromXml(context); + } + initCpuClusters(); } - initCpuClusters(); } private void readPowerValuesFromXml(Context context) { diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java index 89328b21ccf5..49010802c784 100644 --- a/core/java/com/android/internal/os/WrapperInit.java +++ b/core/java/com/android/internal/os/WrapperInit.java @@ -23,7 +23,7 @@ import android.system.Os; import android.system.OsConstants; import android.system.StructCapUserData; import android.system.StructCapUserHeader; -import android.util.BootTimingsTraceLog; +import android.util.TimingsTraceLog; import android.util.Slog; import dalvik.system.VMRuntime; import java.io.DataOutputStream; @@ -80,7 +80,7 @@ public class WrapperInit { } // Mimic system Zygote preloading. - ZygoteInit.preload(new BootTimingsTraceLog("WrapperInitTiming", + ZygoteInit.preload(new TimingsTraceLog("WrapperInitTiming", Trace.TRACE_TAG_DALVIK)); // Launch the application. diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 948f20311905..7058193e8ceb 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -42,8 +42,10 @@ import android.security.keystore.AndroidKeyStoreProvider; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; +import android.system.StructCapUserData; +import android.system.StructCapUserHeader; import android.text.Hyphenator; -import android.util.BootTimingsTraceLog; +import android.util.TimingsTraceLog; import android.util.EventLog; import android.util.Log; import android.util.Slog; @@ -54,7 +56,6 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.util.Preconditions; import dalvik.system.DexFile; -import dalvik.system.PathClassLoader; import dalvik.system.VMRuntime; import dalvik.system.ZygoteHooks; @@ -87,7 +88,6 @@ public class ZygoteInit { private static final String PROPERTY_DISABLE_OPENGL_PRELOADING = "ro.zygote.disable_gl_preload"; private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0"; - private static final String PROPERTY_RUNNING_IN_CONTAINER = "ro.boot.container"; private static final int LOG_BOOT_PROGRESS_PRELOAD_START = 3020; private static final int LOG_BOOT_PROGRESS_PRELOAD_END = 3030; @@ -120,7 +120,7 @@ public class ZygoteInit { private static boolean sPreloadComplete; - static void preload(BootTimingsTraceLog bootTimingsTraceLog) { + static void preload(TimingsTraceLog bootTimingsTraceLog) { Log.d(TAG, "begin preload"); bootTimingsTraceLog.traceBegin("BeginIcuCachePinning"); beginIcuCachePinning(); @@ -153,7 +153,7 @@ public class ZygoteInit { Preconditions.checkState(!sPreloadComplete); Log.i(TAG, "Lazily preloading resources."); - preload(new BootTimingsTraceLog("ZygoteInitTiming_lazy", Trace.TRACE_TAG_DALVIK)); + preload(new TimingsTraceLog("ZygoteInitTiming_lazy", Trace.TRACE_TAG_DALVIK)); } private static void beginIcuCachePinning() { @@ -632,12 +632,20 @@ public class ZygoteInit { OsConstants.CAP_SYS_PTRACE, OsConstants.CAP_SYS_TIME, OsConstants.CAP_SYS_TTY_CONFIG, - OsConstants.CAP_WAKE_ALARM + OsConstants.CAP_WAKE_ALARM, + OsConstants.CAP_BLOCK_SUSPEND ); - /* Containers run without this capability, so avoid setting it in that case */ - if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) { - capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND); + /* Containers run without some capabilities, so drop any caps that are not available. */ + StructCapUserHeader header = new StructCapUserHeader( + OsConstants._LINUX_CAPABILITY_VERSION_3, 0); + StructCapUserData[] data; + try { + data = Os.capget(header); + } catch (ErrnoException ex) { + throw new RuntimeException("Failed to capget()", ex); } + capabilities &= ((long) data[0].effective) | (((long) data[1].effective) << 32); + /* Hardcoded command line to start the system server */ String args[] = { "--setuid=1000", @@ -719,7 +727,7 @@ public class ZygoteInit { } String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing"; - BootTimingsTraceLog bootTimingsTraceLog = new BootTimingsTraceLog(bootTimeTag, + TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag, Trace.TRACE_TAG_DALVIK); bootTimingsTraceLog.traceBegin("ZygoteInit"); RuntimeInit.enableDdms(); diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index 60fbbe9778e7..8ea0242b3549 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -16,6 +16,7 @@ package com.android.internal.policy; +import android.app.WindowConfiguration; import android.graphics.Outline; import android.view.ViewOutlineProvider; import android.view.accessibility.AccessibilityNodeInfo; @@ -82,11 +83,8 @@ import android.view.animation.Interpolator; import android.widget.FrameLayout; import android.widget.PopupWindow; -import static android.app.ActivityManager.StackId; -import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; -import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; -import static android.app.ActivityManager.StackId.PINNED_STACK_ID; -import static android.app.ActivityManager.StackId.INVALID_STACK_ID; +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.os.Build.VERSION_CODES.M; import static android.os.Build.VERSION_CODES.N; @@ -234,10 +232,6 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind // If the window type does not require such a view, this member might be null. DecorCaptionView mDecorCaptionView; - // Stack window is currently in. Since querying and changing the stack is expensive, - // this is the stack value the window is currently set up for. - int mStackId; - private boolean mWindowResizeCallbacksAdded = false; private Drawable.Callback mLastBackgroundDrawableCb = null; private BackdropFrameRenderer mBackdropFrameRenderer = null; @@ -1470,7 +1464,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind invalidate(); int opacity = PixelFormat.OPAQUE; - if (StackId.hasWindowShadow(mStackId)) { + final WindowConfiguration winConfig = getResources().getConfiguration().windowConfiguration; + if (winConfig.hasWindowShadow()) { // If the window has a shadow, it must be translucent. opacity = PixelFormat.TRANSLUCENT; } else{ @@ -1812,7 +1807,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind mFloatingActionMode.finish(); } cleanupFloatingActionModeViews(); - mFloatingToolbar = new FloatingToolbar(mContext, mWindow); + mFloatingToolbar = new FloatingToolbar(mWindow); final FloatingActionMode mode = new FloatingActionMode(mContext, callback, originatingView, mFloatingToolbar); mFloatingActionModeOriginatingView = originatingView; @@ -1860,35 +1855,33 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - int workspaceId = getStackId(); - if (mStackId != workspaceId) { - mStackId = workspaceId; - if (mDecorCaptionView == null && StackId.hasWindowDecor(mStackId)) { - // Configuration now requires a caption. - final LayoutInflater inflater = mWindow.getLayoutInflater(); - mDecorCaptionView = createDecorCaptionView(inflater); - if (mDecorCaptionView != null) { - if (mDecorCaptionView.getParent() == null) { - addView(mDecorCaptionView, 0, - new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); - } - removeView(mContentRoot); - mDecorCaptionView.addView(mContentRoot, - new ViewGroup.MarginLayoutParams(MATCH_PARENT, MATCH_PARENT)); + + final boolean displayWindowDecor = + newConfig.windowConfiguration.hasWindowDecorCaption(); + if (mDecorCaptionView == null && displayWindowDecor) { + // Configuration now requires a caption. + final LayoutInflater inflater = mWindow.getLayoutInflater(); + mDecorCaptionView = createDecorCaptionView(inflater); + if (mDecorCaptionView != null) { + if (mDecorCaptionView.getParent() == null) { + addView(mDecorCaptionView, 0, + new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); } - } else if (mDecorCaptionView != null) { - // We might have to change the kind of surface before we do anything else. - mDecorCaptionView.onConfigurationChanged(StackId.hasWindowDecor(mStackId)); - enableCaption(StackId.hasWindowDecor(workspaceId)); + removeView(mContentRoot); + mDecorCaptionView.addView(mContentRoot, + new ViewGroup.MarginLayoutParams(MATCH_PARENT, MATCH_PARENT)); } + } else if (mDecorCaptionView != null) { + // We might have to change the kind of surface before we do anything else. + mDecorCaptionView.onConfigurationChanged(displayWindowDecor); + enableCaption(displayWindowDecor); } + updateAvailableWidth(); initializeElevation(); } void onResourcesLoaded(LayoutInflater inflater, int layoutResource) { - mStackId = getStackId(); - if (mBackdropFrameRenderer != null) { loadBackgroundDrawablesIfNeeded(); mBackdropFrameRenderer.onResourcesLoaded( @@ -1950,8 +1943,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind final WindowManager.LayoutParams attrs = mWindow.getAttributes(); final boolean isApplication = attrs.type == TYPE_BASE_APPLICATION || attrs.type == TYPE_APPLICATION || attrs.type == TYPE_DRAWN_APPLICATION; + final WindowConfiguration winConfig = getResources().getConfiguration().windowConfiguration; // Only a non floating application window on one of the allowed workspaces can get a caption - if (!mWindow.isFloating() && isApplication && StackId.hasWindowDecor(mStackId)) { + if (!mWindow.isFloating() && isApplication && winConfig.hasWindowDecorCaption()) { // Dependent on the brightness of the used title we either use the // dark or the light button frame. if (decorCaptionView == null) { @@ -2064,28 +2058,6 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind return drawable; } - /** - * Returns the Id of the stack which contains this window. - * Note that if no stack can be determined - which usually means that it was not - * created for an activity - the fullscreen stack ID will be returned. - * @return Returns the stack id which contains this window. - **/ - private int getStackId() { - int workspaceId = INVALID_STACK_ID; - final Window.WindowControllerCallback callback = mWindow.getWindowControllerCallback(); - if (callback != null) { - try { - workspaceId = callback.getWindowStackId(); - } catch (RemoteException ex) { - Log.e(mLogTag, "Failed to get the workspace ID of a PhoneWindow."); - } - } - if (workspaceId == INVALID_STACK_ID) { - return FULLSCREEN_WORKSPACE_STACK_ID; - } - return workspaceId; - } - void clearContentView() { if (mDecorCaptionView != null) { mDecorCaptionView.removeContentView(); @@ -2238,7 +2210,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind final boolean wasAdjustedForStack = mElevationAdjustedForStack; // Do not use a shadow when we are in resizing mode (mBackdropFrameRenderer not null) // since the shadow is bound to the content size and not the target size. - if ((mStackId == FREEFORM_WORKSPACE_STACK_ID) && !isResizing()) { + final int windowingMode = + getResources().getConfiguration().windowConfiguration.getWindowingMode(); + if ((windowingMode == WINDOWING_MODE_FREEFORM) && !isResizing()) { elevation = hasWindowFocus() ? DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP; // Add a maximum shadow height value to the top level view. @@ -2251,7 +2225,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind // Convert the DP elevation into physical pixels. elevation = dipToPx(elevation); mElevationAdjustedForStack = true; - } else if (mStackId == PINNED_STACK_ID) { + } else if (windowingMode == WINDOWING_MODE_PINNED) { elevation = dipToPx(DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP); mElevationAdjustedForStack = true; } else { diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index 544afd993b37..0d66376138c2 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -2453,6 +2453,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { decor.setSystemUiVisibility( decor.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); } + if (a.getBoolean(R.styleable.Window_windowLightNavigationBar, false)) { + decor.setSystemUiVisibility( + decor.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } if (mAlwaysReadCloseOnTouchAttr || getContext().getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) { diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index f978b579a10e..bab0306aaf9f 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -112,6 +112,13 @@ oneway interface IStatusBar */ void showGlobalActionsMenu(); + /** + * Set whether the top app currently hides the statusbar. + * + * @param hidesStatusBar whether it is being hidden + */ + void setTopAppHidesStatusBar(boolean hidesStatusBar); + void addQsTile(in ComponentName tile); void remQsTile(in ComponentName tile); void clickQsTile(in ComponentName tile); diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java index 2778d93a5388..933cc7af975a 100644 --- a/core/java/com/android/internal/util/NotificationColorUtil.java +++ b/core/java/com/android/internal/util/NotificationColorUtil.java @@ -33,6 +33,7 @@ import android.graphics.drawable.Icon; import android.graphics.drawable.VectorDrawable; import android.text.SpannableStringBuilder; import android.text.Spanned; +import android.text.style.BackgroundColorSpan; import android.text.style.CharacterStyle; import android.text.style.ForegroundColorSpan; import android.text.style.TextAppearanceSpan; @@ -240,6 +241,45 @@ public class NotificationColorUtil { return span; } + /** + * Clears all color spans of a text + * @param charSequence the input text + * @return the same text but without color spans + */ + public static CharSequence clearColorSpans(CharSequence charSequence) { + if (charSequence instanceof Spanned) { + Spanned ss = (Spanned) charSequence; + Object[] spans = ss.getSpans(0, ss.length(), Object.class); + SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString()); + for (Object span : spans) { + Object resultSpan = span; + if (resultSpan instanceof CharacterStyle) { + resultSpan = ((CharacterStyle) span).getUnderlying(); + } + if (resultSpan instanceof TextAppearanceSpan) { + TextAppearanceSpan originalSpan = (TextAppearanceSpan) resultSpan; + if (originalSpan.getTextColor() != null) { + resultSpan = new TextAppearanceSpan( + originalSpan.getFamily(), + originalSpan.getTextStyle(), + originalSpan.getTextSize(), + null, + originalSpan.getLinkTextColor()); + } + } else if (resultSpan instanceof ForegroundColorSpan + || (resultSpan instanceof BackgroundColorSpan)) { + continue; + } else { + resultSpan = span; + } + builder.setSpan(resultSpan, ss.getSpanStart(span), ss.getSpanEnd(span), + ss.getSpanFlags(span)); + } + return builder; + } + return charSequence; + } + private int processColor(int color) { return Color.argb(Color.alpha(color), 255 - Color.red(color), diff --git a/core/java/com/android/internal/view/TooltipPopup.java b/core/java/com/android/internal/view/TooltipPopup.java index 3930214ea286..d38ea2c19af4 100644 --- a/core/java/com/android/internal/view/TooltipPopup.java +++ b/core/java/com/android/internal/view/TooltipPopup.java @@ -93,7 +93,7 @@ public class TooltipPopup { private void computePosition(View anchorView, int anchorX, int anchorY, boolean fromTouch, WindowManager.LayoutParams outParams) { - outParams.token = anchorView.getWindowToken(); + outParams.token = anchorView.getApplicationWindowToken(); final int tooltipPreciseAnchorThreshold = mContext.getResources().getDimensionPixelOffset( com.android.internal.R.dimen.tooltip_precise_anchor_threshold); diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java index 83a2838be07e..f76c7247aba9 100644 --- a/core/java/com/android/internal/view/menu/ListMenuItemView.java +++ b/core/java/com/android/internal/view/menu/ListMenuItemView.java @@ -16,14 +16,18 @@ package com.android.internal.view.menu; +import com.android.internal.R; + import android.content.Context; import android.content.res.TypedArray; +import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityNodeInfo; +import android.widget.AbsListView; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.ImageView; @@ -34,25 +38,28 @@ import android.widget.TextView; /** * The item view for each item in the ListView-based MenuViews. */ -public class ListMenuItemView extends LinearLayout implements MenuView.ItemView { +public class ListMenuItemView extends LinearLayout + implements MenuView.ItemView, AbsListView.SelectionBoundsAdjuster { private static final String TAG = "ListMenuItemView"; - private MenuItemImpl mItemData; - + private MenuItemImpl mItemData; + private ImageView mIconView; private RadioButton mRadioButton; private TextView mTitleView; private CheckBox mCheckBox; private TextView mShortcutView; private ImageView mSubMenuArrowView; - + private ImageView mGroupDivider; + private Drawable mBackground; private int mTextAppearance; private Context mTextAppearanceContext; private boolean mPreserveIconSpacing; private Drawable mSubMenuArrow; - + private boolean mHasListDivider; + private int mMenuType; - + private LayoutInflater mInflater; private boolean mForceShowIcon; @@ -71,8 +78,14 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView com.android.internal.R.styleable.MenuView_preserveIconSpacing, false); mTextAppearanceContext = context; mSubMenuArrow = a.getDrawable(com.android.internal.R.styleable.MenuView_subMenuArrow); - + + final TypedArray b = context.getTheme() + .obtainStyledAttributes(null, new int[] { com.android.internal.R.attr.divider }, + com.android.internal.R.attr.dropDownListViewStyle, 0); + mHasListDivider = b.hasValue(0); + a.recycle(); + b.recycle(); } public ListMenuItemView(Context context, AttributeSet attrs, int defStyleAttr) { @@ -86,20 +99,21 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView @Override protected void onFinishInflate() { super.onFinishInflate(); - + setBackgroundDrawable(mBackground); - + mTitleView = findViewById(com.android.internal.R.id.title); if (mTextAppearance != -1) { mTitleView.setTextAppearance(mTextAppearanceContext, mTextAppearance); } - + mShortcutView = findViewById(com.android.internal.R.id.shortcut); mSubMenuArrowView = findViewById(com.android.internal.R.id.submenuarrow); if (mSubMenuArrowView != null) { mSubMenuArrowView.setImageDrawable(mSubMenuArrow); } + mGroupDivider = findViewById(com.android.internal.R.id.group_divider); } public void initialize(MenuItemImpl itemData, int menuType) { @@ -124,13 +138,13 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView public void setTitle(CharSequence title) { if (title != null) { mTitleView.setText(title); - + if (mTitleView.getVisibility() != VISIBLE) mTitleView.setVisibility(VISIBLE); } else { if (mTitleView.getVisibility() != GONE) mTitleView.setVisibility(GONE); } } - + public MenuItemImpl getItemData() { return mItemData; } @@ -139,11 +153,11 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView if (!checkable && mRadioButton == null && mCheckBox == null) { return; } - + // Depending on whether its exclusive check or not, the checkbox or // radio button will be the one in use (and the other will be otherCompoundButton) final CompoundButton compoundButton; - final CompoundButton otherCompoundButton; + final CompoundButton otherCompoundButton; if (mItemData.isExclusiveCheckable()) { if (mRadioButton == null) { @@ -158,15 +172,15 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView compoundButton = mCheckBox; otherCompoundButton = mRadioButton; } - + if (checkable) { compoundButton.setChecked(mItemData.isChecked()); - + final int newVisibility = checkable ? VISIBLE : GONE; if (compoundButton.getVisibility() != newVisibility) { compoundButton.setVisibility(newVisibility); } - + // Make sure the other compound button isn't visible if (otherCompoundButton != null && otherCompoundButton.getVisibility() != GONE) { otherCompoundButton.setVisibility(GONE); @@ -176,10 +190,10 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView if (mRadioButton != null) mRadioButton.setVisibility(GONE); } } - + public void setChecked(boolean checked) { CompoundButton compoundButton; - + if (mItemData.isExclusiveCheckable()) { if (mRadioButton == null) { insertRadioButton(); @@ -191,7 +205,7 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView } compoundButton = mCheckBox; } - + compoundButton.setChecked(checked); } @@ -213,21 +227,21 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView mShortcutView.setVisibility(newVisibility); } } - + public void setIcon(Drawable icon) { final boolean showIcon = mItemData.shouldShowIcon() || mForceShowIcon; if (!showIcon && !mPreserveIconSpacing) { return; } - + if (mIconView == null && icon == null && !mPreserveIconSpacing) { return; } - + if (mIconView == null) { insertIconView(); } - + if (icon != null || mPreserveIconSpacing) { mIconView.setImageDrawable(showIcon ? icon : null); @@ -238,7 +252,7 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView mIconView.setVisibility(GONE); } } - + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (mIconView != null && mPreserveIconSpacing) { @@ -258,7 +272,7 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView this, false); addView(mIconView, 0); } - + private void insertRadioButton() { LayoutInflater inflater = getInflater(); mRadioButton = @@ -266,7 +280,7 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView this, false); addView(mRadioButton); } - + private void insertCheckBox() { LayoutInflater inflater = getInflater(); mCheckBox = @@ -282,7 +296,7 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView public boolean showsIcon() { return mForceShowIcon; } - + private LayoutInflater getInflater() { if (mInflater == null) { mInflater = LayoutInflater.from(mContext); @@ -298,4 +312,26 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView info.setCanOpenPopup(true); } } + + /** + * Enable or disable group dividers for this view. + */ + public void setGroupDividerEnabled(boolean groupDividerEnabled) { + // If mHasListDivider is true, disabling the groupDivider. + // Otherwise, checking enbling it according to groupDividerEnabled flag. + mGroupDivider.setVisibility(!mHasListDivider + && groupDividerEnabled ? View.VISIBLE : View.GONE); + } + + @Override + public void adjustListItemSelectionBounds(Rect rect) { + if (mGroupDivider.getVisibility() == View.VISIBLE) { + // groupDivider is a part of MenuItemListView. + // If ListMenuItem with divider enabled is hovered/clicked, divider also gets selected. + // Clipping the selector bounds from the top divider portion when divider is enabled, + // so that divider does not get selected on hover or click. + final LayoutParams lp = (LayoutParams) mGroupDivider.getLayoutParams(); + rect.top += mGroupDivider.getHeight() + lp.topMargin + lp.bottomMargin; + } + } } diff --git a/core/java/com/android/internal/view/menu/MenuAdapter.java b/core/java/com/android/internal/view/menu/MenuAdapter.java index 673cfd12d878..2834d39a4f98 100644 --- a/core/java/com/android/internal/view/menu/MenuAdapter.java +++ b/core/java/com/android/internal/view/menu/MenuAdapter.java @@ -81,6 +81,14 @@ public class MenuAdapter extends BaseAdapter { convertView = mInflater.inflate(ITEM_LAYOUT, parent, false); } + final int currGroupId = getItem(position).getGroupId(); + final int prevGroupId = + position - 1 >= 0 ? getItem(position - 1).getGroupId() : currGroupId; + // Show a divider if adjacent items are in different groups. + ((ListMenuItemView) convertView) + .setGroupDividerEnabled(mAdapterMenu.isGroupDividerEnabled() + && (currGroupId != prevGroupId)); + MenuView.ItemView itemView = (MenuView.ItemView) convertView; if (mForceShowIcon) { ((ListMenuItemView) convertView).setForceShowIcon(true); diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java index 7eb0f4dbddc7..b53459e072d4 100644 --- a/core/java/com/android/internal/view/menu/MenuBuilder.java +++ b/core/java/com/android/internal/view/menu/MenuBuilder.java @@ -156,7 +156,12 @@ public class MenuBuilder implements Menu { * Currently expanded menu item; must be collapsed when we clear. */ private MenuItemImpl mExpandedItem; - + + /** + * Whether group dividers are enabled. + */ + private boolean mGroupDividerEnabled = false; + /** * Called by menu to notify of close and selection changes. */ @@ -462,6 +467,15 @@ public class MenuBuilder implements Menu { return addSubMenu(group, id, categoryOrder, mResources.getString(title)); } + @Override + public void setGroupDividerEnabled(boolean groupDividerEnabled) { + mGroupDividerEnabled = groupDividerEnabled; + } + + public boolean isGroupDividerEnabled() { + return mGroupDividerEnabled; + } + public int addIntentOptions(int group, int id, int categoryOrder, ComponentName caller, Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) { PackageManager pm = mContext.getPackageManager(); diff --git a/core/java/com/android/internal/view/menu/SubMenuBuilder.java b/core/java/com/android/internal/view/menu/SubMenuBuilder.java index cf741bf5bb02..897440ebf893 100644 --- a/core/java/com/android/internal/view/menu/SubMenuBuilder.java +++ b/core/java/com/android/internal/view/menu/SubMenuBuilder.java @@ -130,4 +130,14 @@ public class SubMenuBuilder extends MenuBuilder implements SubMenu { } return super.getActionViewStatesKey() + ":" + itemId; } + + @Override + public void setGroupDividerEnabled(boolean groupDividerEnabled) { + mParentMenu.setGroupDividerEnabled(groupDividerEnabled); + } + + @Override + public boolean isGroupDividerEnabled() { + return mParentMenu.isGroupDividerEnabled(); + } } diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java index 1d56e1ad3e03..f63b5a213528 100644 --- a/core/java/com/android/internal/widget/FloatingToolbar.java +++ b/core/java/com/android/internal/widget/FloatingToolbar.java @@ -120,8 +120,10 @@ public final class FloatingToolbar { /** * Initializes a floating toolbar. */ - public FloatingToolbar(Context context, Window window) { - mContext = applyDefaultTheme(Preconditions.checkNotNull(context)); + public FloatingToolbar(Window window) { + // TODO(b/65172902): Pass context in constructor when DecorView (and other callers) + // supports multi-display. + mContext = applyDefaultTheme(window.getContext()); mWindow = Preconditions.checkNotNull(window); mPopup = new FloatingToolbarPopup(mContext, window.getDecorView()); } diff --git a/core/java/com/android/internal/widget/ImageFloatingTextView.java b/core/java/com/android/internal/widget/ImageFloatingTextView.java index 31b167d43f66..7870333cd82d 100644 --- a/core/java/com/android/internal/widget/ImageFloatingTextView.java +++ b/core/java/com/android/internal/widget/ImageFloatingTextView.java @@ -81,6 +81,7 @@ public class ImageFloatingTextView extends TextView { .setTextDirection(getTextDirectionHeuristic()) .setLineSpacing(getLineSpacingExtra(), getLineSpacingMultiplier()) .setIncludePad(getIncludeFontPadding()) + .setUseLineSpacingFromFallbacks(true) .setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY) .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL); int maxLines; diff --git a/core/java/com/android/internal/widget/SubtitleView.java b/core/java/com/android/internal/widget/SubtitleView.java index 3230185dbda7..110782896d5a 100644 --- a/core/java/com/android/internal/widget/SubtitleView.java +++ b/core/java/com/android/internal/widget/SubtitleView.java @@ -256,8 +256,11 @@ public class SubtitleView extends View { // StaticLayout.getWidth(), so this is non-trivial. mHasMeasurements = true; mLastMeasuredWidth = maxWidth; - mLayout = new StaticLayout( - mText, mTextPaint, maxWidth, mAlignment, mSpacingMult, mSpacingAdd, true); + mLayout = StaticLayout.Builder.obtain(mText, 0, mText.length(), mTextPaint, maxWidth) + .setAlignment(mAlignment) + .setLineSpacing(mSpacingAdd, mSpacingMult) + .setUseLineSpacingFromFallbacks(true) + .build(); return true; } diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java index 18990cff1f83..43544862b5ec 100644 --- a/core/java/com/android/server/BootReceiver.java +++ b/core/java/com/android/server/BootReceiver.java @@ -31,13 +31,13 @@ import android.os.ServiceManager; import android.os.SystemProperties; import android.os.storage.StorageManager; import android.provider.Downloads; +import android.text.TextUtils; import android.util.AtomicFile; import android.util.Slog; import android.util.Xml; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; -import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.XmlUtils; @@ -106,6 +106,11 @@ public class BootReceiver extends BroadcastReceiver { "powerctl_shutdown_time_ms:([0-9]+):([0-9]+)"; private static final int UMOUNT_STATUS_NOT_AVAILABLE = 4; // should match with init/reboot.h + // Location of file with metrics recorded during shutdown + private static final String SHUTDOWN_METRICS_FILE = "/data/system/shutdown-metrics.txt"; + + private static final String SHUTDOWN_TRON_METRICS_PREFIX = "shutdown_"; + @Override public void onReceive(final Context context, Intent intent) { // Log boot events in the background to avoid blocking the main thread with I/O @@ -232,6 +237,7 @@ public class BootReceiver extends BroadcastReceiver { logFsShutdownTime(); logFsMountTime(); addFsckErrorsToDropBoxAndLogFsStat(db, timestamps, headers, -LOG_SIZE, "SYSTEM_FSCK"); + logSystemServerShutdownTimeMetrics(); // Scan existing tombstones (in case any new ones appeared) File[] tombstoneFiles = TOMBSTONE_DIR.listFiles(); @@ -380,6 +386,47 @@ public class BootReceiver extends BroadcastReceiver { } } + // TODO b/64815357 Move to bootstat.cpp and log AbsoluteRebootTime + private static void logSystemServerShutdownTimeMetrics() { + File metricsFile = new File(SHUTDOWN_METRICS_FILE); + String metricsStr = null; + if (metricsFile.exists()) { + try { + metricsStr = FileUtils.readTextFile(metricsFile, 0, null); + } catch (IOException e) { + Slog.e(TAG, "Problem reading " + metricsFile, e); + } + } + if (!TextUtils.isEmpty(metricsStr)) { + String[] array = metricsStr.split(","); + for (String keyValueStr : array) { + String[] keyValue = keyValueStr.split(":"); + if (keyValue.length != 2) { + Slog.e(TAG, "Wrong format of shutdown metrics - " + metricsStr); + continue; + } + // Ignore keys that are not indended for tron + if (keyValue[0].startsWith(SHUTDOWN_TRON_METRICS_PREFIX)) { + logTronShutdownMetric(keyValue[0], keyValue[1]); + } + } + } + metricsFile.delete(); + } + + private static void logTronShutdownMetric(String metricName, String valueStr) { + int value; + try { + value = Integer.parseInt(valueStr); + } catch (NumberFormatException e) { + Slog.e(TAG, "Cannot parse metric " + metricName + " int value - " + valueStr); + return; + } + if (value >= 0) { + MetricsLogger.histogram(null, metricName, value); + } + } + private static void logFsShutdownTime() { File f = null; for (String fileName : LAST_KMSG_FILES) { diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java index 81018fe4b357..77788921635f 100644 --- a/core/java/com/android/server/SystemConfig.java +++ b/core/java/com/android/server/SystemConfig.java @@ -141,6 +141,7 @@ public class SystemConfig { final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>(); + final ArrayMap<String, ArraySet<String>> mPrivAppDenyPermissions = new ArrayMap<>(); public static SystemConfig getInstance() { synchronized (SystemConfig.class) { @@ -219,6 +220,10 @@ public class SystemConfig { return mPrivAppPermissions.get(packageName); } + public ArraySet<String> getPrivAppDenyPermissions(String packageName) { + return mPrivAppDenyPermissions.get(packageName); + } + SystemConfig() { // Read configuration from system readPermissions(Environment.buildPath( @@ -660,6 +665,7 @@ public class SystemConfig { if (permissions == null) { permissions = new ArraySet<>(); } + ArraySet<String> denyPermissions = mPrivAppDenyPermissions.get(packageName); int depth = parser.getDepth(); while (XmlUtils.nextElementWithin(parser, depth)) { String name = parser.getName(); @@ -671,8 +677,22 @@ public class SystemConfig { continue; } permissions.add(permName); + } else if ("deny-permission".equals(name)) { + String permName = parser.getAttributeValue(null, "name"); + if (TextUtils.isEmpty(permName)) { + Slog.w(TAG, "name is required for <deny-permission> in " + + parser.getPositionDescription()); + continue; + } + if (denyPermissions == null) { + denyPermissions = new ArraySet<>(); + } + denyPermissions.add(permName); } } mPrivAppPermissions.put(packageName, permissions); + if (denyPermissions != null) { + mPrivAppDenyPermissions.put(packageName, denyPermissions); + } } } diff --git a/core/jni/Android.bp b/core/jni/Android.bp index c62934100540..d63e22c189f8 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -103,6 +103,7 @@ cc_library_shared { "android_nio_utils.cpp", "android_util_AssetManager.cpp", "android_util_Binder.cpp", + "android_util_StatsLog.cpp", "android_util_EventLog.cpp", "android_util_MemoryIntArray.cpp", "android_util_Log.cpp", diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 5afd06750601..02c9848ea149 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -111,6 +111,7 @@ namespace android { extern int register_android_app_admin_SecurityLog(JNIEnv* env); extern int register_android_content_AssetManager(JNIEnv* env); extern int register_android_util_EventLog(JNIEnv* env); +extern int register_android_util_StatsLog(JNIEnv* env); extern int register_android_util_Log(JNIEnv* env); extern int register_android_util_MemoryIntArray(JNIEnv* env); extern int register_android_util_PathParser(JNIEnv* env); @@ -1311,6 +1312,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit), REG_JNI(register_android_os_SystemClock), REG_JNI(register_android_util_EventLog), + REG_JNI(register_android_util_StatsLog), REG_JNI(register_android_util_Log), REG_JNI(register_android_util_MemoryIntArray), REG_JNI(register_android_util_PathParser), diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp index f99637d2ae30..42e9273c5ba2 100644 --- a/core/jni/android/graphics/BitmapFactory.cpp +++ b/core/jni/android/graphics/BitmapFactory.cpp @@ -76,6 +76,9 @@ jstring encodedFormatToString(JNIEnv* env, SkEncodedImageFormat format) { case SkEncodedImageFormat::kWEBP: mimeType = "image/webp"; break; + case SkEncodedImageFormat::kHEIF: + mimeType = "image/heif"; + break; case SkEncodedImageFormat::kWBMP: mimeType = "image/vnd.wap.wbmp"; break; diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp index 7c75ff426b24..5ea501e5fefd 100644 --- a/core/jni/android/graphics/Graphics.cpp +++ b/core/jni/android/graphics/Graphics.cpp @@ -62,11 +62,11 @@ bool GraphicsJNI::hasException(JNIEnv *env) { AutoJavaFloatArray::AutoJavaFloatArray(JNIEnv* env, jfloatArray array, int minLength, JNIAccess access) : fEnv(env), fArray(array), fPtr(NULL), fLen(0) { - SkASSERT(env); + ALOG_ASSERT(env); if (array) { fLen = env->GetArrayLength(array); if (fLen < minLength) { - sk_throw(); + LOG_ALWAYS_FATAL("bad length"); } fPtr = env->GetFloatArrayElements(array, NULL); } @@ -82,11 +82,11 @@ AutoJavaFloatArray::~AutoJavaFloatArray() { AutoJavaIntArray::AutoJavaIntArray(JNIEnv* env, jintArray array, int minLength) : fEnv(env), fArray(array), fPtr(NULL), fLen(0) { - SkASSERT(env); + ALOG_ASSERT(env); if (array) { fLen = env->GetArrayLength(array); if (fLen < minLength) { - sk_throw(); + LOG_ALWAYS_FATAL("bad length"); } fPtr = env->GetIntArrayElements(array, NULL); } @@ -101,11 +101,11 @@ AutoJavaIntArray::~AutoJavaIntArray() { AutoJavaShortArray::AutoJavaShortArray(JNIEnv* env, jshortArray array, int minLength, JNIAccess access) : fEnv(env), fArray(array), fPtr(NULL), fLen(0) { - SkASSERT(env); + ALOG_ASSERT(env); if (array) { fLen = env->GetArrayLength(array); if (fLen < minLength) { - sk_throw(); + LOG_ALWAYS_FATAL("bad length"); } fPtr = env->GetShortArrayElements(array, NULL); } @@ -121,11 +121,11 @@ AutoJavaShortArray::~AutoJavaShortArray() { AutoJavaByteArray::AutoJavaByteArray(JNIEnv* env, jbyteArray array, int minLength) : fEnv(env), fArray(array), fPtr(NULL), fLen(0) { - SkASSERT(env); + ALOG_ASSERT(env); if (array) { fLen = env->GetArrayLength(array); if (fLen < minLength) { - sk_throw(); + LOG_ALWAYS_FATAL("bad length"); } fPtr = env->GetByteArrayElements(array, NULL); } @@ -211,7 +211,7 @@ static jmethodID gTransferParameters_constructorMethodID; void GraphicsJNI::get_jrect(JNIEnv* env, jobject obj, int* L, int* T, int* R, int* B) { - SkASSERT(env->IsInstanceOf(obj, gRect_class)); + ALOG_ASSERT(env->IsInstanceOf(obj, gRect_class)); *L = env->GetIntField(obj, gRect_leftFieldID); *T = env->GetIntField(obj, gRect_topFieldID); @@ -221,7 +221,7 @@ void GraphicsJNI::get_jrect(JNIEnv* env, jobject obj, int* L, int* T, int* R, in void GraphicsJNI::set_jrect(JNIEnv* env, jobject obj, int L, int T, int R, int B) { - SkASSERT(env->IsInstanceOf(obj, gRect_class)); + ALOG_ASSERT(env->IsInstanceOf(obj, gRect_class)); env->SetIntField(obj, gRect_leftFieldID, L); env->SetIntField(obj, gRect_topFieldID, T); @@ -231,7 +231,7 @@ void GraphicsJNI::set_jrect(JNIEnv* env, jobject obj, int L, int T, int R, int B SkIRect* GraphicsJNI::jrect_to_irect(JNIEnv* env, jobject obj, SkIRect* ir) { - SkASSERT(env->IsInstanceOf(obj, gRect_class)); + ALOG_ASSERT(env->IsInstanceOf(obj, gRect_class)); ir->set(env->GetIntField(obj, gRect_leftFieldID), env->GetIntField(obj, gRect_topFieldID), @@ -242,7 +242,7 @@ SkIRect* GraphicsJNI::jrect_to_irect(JNIEnv* env, jobject obj, SkIRect* ir) void GraphicsJNI::irect_to_jrect(const SkIRect& ir, JNIEnv* env, jobject obj) { - SkASSERT(env->IsInstanceOf(obj, gRect_class)); + ALOG_ASSERT(env->IsInstanceOf(obj, gRect_class)); env->SetIntField(obj, gRect_leftFieldID, ir.fLeft); env->SetIntField(obj, gRect_topFieldID, ir.fTop); @@ -252,7 +252,7 @@ void GraphicsJNI::irect_to_jrect(const SkIRect& ir, JNIEnv* env, jobject obj) SkRect* GraphicsJNI::jrectf_to_rect(JNIEnv* env, jobject obj, SkRect* r) { - SkASSERT(env->IsInstanceOf(obj, gRectF_class)); + ALOG_ASSERT(env->IsInstanceOf(obj, gRectF_class)); r->set(env->GetFloatField(obj, gRectF_leftFieldID), env->GetFloatField(obj, gRectF_topFieldID), @@ -263,7 +263,7 @@ SkRect* GraphicsJNI::jrectf_to_rect(JNIEnv* env, jobject obj, SkRect* r) SkRect* GraphicsJNI::jrect_to_rect(JNIEnv* env, jobject obj, SkRect* r) { - SkASSERT(env->IsInstanceOf(obj, gRect_class)); + ALOG_ASSERT(env->IsInstanceOf(obj, gRect_class)); r->set(SkIntToScalar(env->GetIntField(obj, gRect_leftFieldID)), SkIntToScalar(env->GetIntField(obj, gRect_topFieldID)), @@ -274,7 +274,7 @@ SkRect* GraphicsJNI::jrect_to_rect(JNIEnv* env, jobject obj, SkRect* r) void GraphicsJNI::rect_to_jrectf(const SkRect& r, JNIEnv* env, jobject obj) { - SkASSERT(env->IsInstanceOf(obj, gRectF_class)); + ALOG_ASSERT(env->IsInstanceOf(obj, gRectF_class)); env->SetFloatField(obj, gRectF_leftFieldID, SkScalarToFloat(r.fLeft)); env->SetFloatField(obj, gRectF_topFieldID, SkScalarToFloat(r.fTop)); @@ -284,7 +284,7 @@ void GraphicsJNI::rect_to_jrectf(const SkRect& r, JNIEnv* env, jobject obj) SkIPoint* GraphicsJNI::jpoint_to_ipoint(JNIEnv* env, jobject obj, SkIPoint* point) { - SkASSERT(env->IsInstanceOf(obj, gPoint_class)); + ALOG_ASSERT(env->IsInstanceOf(obj, gPoint_class)); point->set(env->GetIntField(obj, gPoint_xFieldID), env->GetIntField(obj, gPoint_yFieldID)); @@ -293,7 +293,7 @@ SkIPoint* GraphicsJNI::jpoint_to_ipoint(JNIEnv* env, jobject obj, SkIPoint* poin void GraphicsJNI::ipoint_to_jpoint(const SkIPoint& ir, JNIEnv* env, jobject obj) { - SkASSERT(env->IsInstanceOf(obj, gPoint_class)); + ALOG_ASSERT(env->IsInstanceOf(obj, gPoint_class)); env->SetIntField(obj, gPoint_xFieldID, ir.fX); env->SetIntField(obj, gPoint_yFieldID, ir.fY); @@ -301,7 +301,7 @@ void GraphicsJNI::ipoint_to_jpoint(const SkIPoint& ir, JNIEnv* env, jobject obj) SkPoint* GraphicsJNI::jpointf_to_point(JNIEnv* env, jobject obj, SkPoint* point) { - SkASSERT(env->IsInstanceOf(obj, gPointF_class)); + ALOG_ASSERT(env->IsInstanceOf(obj, gPointF_class)); point->set(env->GetIntField(obj, gPointF_xFieldID), env->GetIntField(obj, gPointF_yFieldID)); @@ -310,7 +310,7 @@ SkPoint* GraphicsJNI::jpointf_to_point(JNIEnv* env, jobject obj, SkPoint* point) void GraphicsJNI::point_to_jpointf(const SkPoint& r, JNIEnv* env, jobject obj) { - SkASSERT(env->IsInstanceOf(obj, gPointF_class)); + ALOG_ASSERT(env->IsInstanceOf(obj, gPointF_class)); env->SetFloatField(obj, gPointF_xFieldID, SkScalarToFloat(r.fX)); env->SetFloatField(obj, gPointF_yFieldID, SkScalarToFloat(r.fY)); @@ -364,17 +364,17 @@ SkPixelRef* GraphicsJNI::refSkPixelRef(JNIEnv* env, jobject jbitmap) { return &bitmap; } SkColorType GraphicsJNI::getNativeBitmapColorType(JNIEnv* env, jobject jconfig) { - SkASSERT(env); + ALOG_ASSERT(env); if (NULL == jconfig) { return kUnknown_SkColorType; } - SkASSERT(env->IsInstanceOf(jconfig, gBitmapConfig_class)); + ALOG_ASSERT(env->IsInstanceOf(jconfig, gBitmapConfig_class)); int c = env->GetIntField(jconfig, gBitmapConfig_nativeInstanceID); return legacyBitmapConfigToColorType(c); } bool GraphicsJNI::isHardwareConfig(JNIEnv* env, jobject jconfig) { - SkASSERT(env); + ALOG_ASSERT(env); if (NULL == jconfig) { return false; } @@ -387,9 +387,9 @@ jint GraphicsJNI::hardwareLegacyBitmapConfig() { } android::Canvas* GraphicsJNI::getNativeCanvas(JNIEnv* env, jobject canvas) { - SkASSERT(env); - SkASSERT(canvas); - SkASSERT(env->IsInstanceOf(canvas, gCanvas_class)); + ALOG_ASSERT(env); + ALOG_ASSERT(canvas); + ALOG_ASSERT(env->IsInstanceOf(canvas, gCanvas_class)); jlong canvasHandle = env->GetLongField(canvas, gCanvas_nativeInstanceID); if (!canvasHandle) { return NULL; @@ -399,12 +399,12 @@ android::Canvas* GraphicsJNI::getNativeCanvas(JNIEnv* env, jobject canvas) { SkRegion* GraphicsJNI::getNativeRegion(JNIEnv* env, jobject region) { - SkASSERT(env); - SkASSERT(region); - SkASSERT(env->IsInstanceOf(region, gRegion_class)); + ALOG_ASSERT(env); + ALOG_ASSERT(region); + ALOG_ASSERT(env->IsInstanceOf(region, gRegion_class)); jlong regionHandle = env->GetLongField(region, gRegion_nativeInstanceID); SkRegion* r = reinterpret_cast<SkRegion*>(regionHandle); - SkASSERT(r); + ALOG_ASSERT(r); return r; } @@ -412,7 +412,7 @@ SkRegion* GraphicsJNI::getNativeRegion(JNIEnv* env, jobject region) jobject GraphicsJNI::createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap) { - SkASSERT(bitmap != NULL); + ALOG_ASSERT(bitmap != NULL); jobject obj = env->NewObject(gBitmapRegionDecoder_class, gBitmapRegionDecoder_constructorMethodID, @@ -423,7 +423,7 @@ jobject GraphicsJNI::createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecode jobject GraphicsJNI::createRegion(JNIEnv* env, SkRegion* region) { - SkASSERT(region != NULL); + ALOG_ASSERT(region != NULL); jobject obj = env->NewObject(gRegion_class, gRegion_constructorMethodID, reinterpret_cast<jlong>(region), 0); hasException(env); // For the side effect of logging. diff --git a/core/jni/android/graphics/pdf/PdfEditor.cpp b/core/jni/android/graphics/pdf/PdfEditor.cpp index e75712c49fd3..10c30260d7e3 100644 --- a/core/jni/android/graphics/pdf/PdfEditor.cpp +++ b/core/jni/android/graphics/pdf/PdfEditor.cpp @@ -60,12 +60,7 @@ static jint nativeRemovePage(JNIEnv* env, jclass thiz, jlong documentPtr, jint p FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); FPDFPage_Delete(document, pageIndex); - HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, -1) - - int pageCount = FPDF_GetPageCount(document); - HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, -1) - - return pageCount; + return FPDF_GetPageCount(document); } struct PdfToFdWriter : FPDF_FILEWRITE { @@ -110,7 +105,6 @@ static void nativeWrite(JNIEnv* env, jclass thiz, jlong documentPtr, jint fd) { jniThrowExceptionFmt(env, "java/io/IOException", "cannot write to fd. Error: %d", errno); } - HANDLE_PDFIUM_ERROR_STATE(env) } static void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, @@ -123,7 +117,6 @@ static void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPt "cannot open page"); return; } - HANDLE_PDFIUM_ERROR_STATE(env); double width = 0; double height = 0; @@ -134,11 +127,6 @@ static void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPt "cannot get page size"); return; } - bool isExceptionPending = forwardPdfiumError(env); - if (isExceptionPending) { - FPDF_ClosePage(page); - return; - } // PDF's coordinate system origin is left-bottom while in graphics it // is the top-left. So, translate the PDF coordinates to ours. @@ -170,14 +158,8 @@ static void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPt FS_RECTF clip = {(float) clipLeft, (float) clipTop, (float) clipRight, (float) clipBottom}; FPDFPage_TransFormWithClip(page, &transform, &clip); - isExceptionPending = forwardPdfiumError(env); - if (isExceptionPending) { - FPDF_ClosePage(page); - return; - } FPDF_ClosePage(page); - HANDLE_PDFIUM_ERROR_STATE(env); } static void nativeGetPageSize(JNIEnv* env, jclass thiz, jlong documentPtr, @@ -190,7 +172,6 @@ static void nativeGetPageSize(JNIEnv* env, jclass thiz, jlong documentPtr, "cannot open page"); return; } - HANDLE_PDFIUM_ERROR_STATE(env); double width = 0; double height = 0; @@ -201,17 +182,11 @@ static void nativeGetPageSize(JNIEnv* env, jclass thiz, jlong documentPtr, "cannot get page size"); return; } - bool isExceptionPending = forwardPdfiumError(env); - if (isExceptionPending) { - FPDF_ClosePage(page); - return; - } env->SetIntField(outSize, gPointClassInfo.x, width); env->SetIntField(outSize, gPointClassInfo.y, height); FPDF_ClosePage(page); - HANDLE_PDFIUM_ERROR_STATE(env); } static bool nativeGetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, @@ -224,7 +199,6 @@ static bool nativeGetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint p "cannot open page"); return false; } - HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, false); float left; float top; @@ -234,14 +208,8 @@ static bool nativeGetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint p const FPDF_BOOL success = (pageBox == PAGE_BOX_MEDIA) ? FPDFPage_GetMediaBox(page, &left, &top, &right, &bottom) : FPDFPage_GetCropBox(page, &left, &top, &right, &bottom); - bool isExceptionPending = forwardPdfiumError(env); - if (isExceptionPending) { - FPDF_ClosePage(page); - return false; - } FPDF_ClosePage(page); - HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, false); if (!success) { return false; @@ -279,7 +247,6 @@ static void nativeSetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint p "cannot open page"); return; } - HANDLE_PDFIUM_ERROR_STATE(env); const int left = env->GetIntField(box, gRectClassInfo.left); const int top = env->GetIntField(box, gRectClassInfo.top); @@ -291,14 +258,8 @@ static void nativeSetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint p } else { FPDFPage_SetCropBox(page, left, top, right, bottom); } - bool isExceptionPending = forwardPdfiumError(env); - if (isExceptionPending) { - FPDF_ClosePage(page); - return; - } FPDF_ClosePage(page); - HANDLE_PDFIUM_ERROR_STATE(env); } static void nativeSetPageMediaBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, diff --git a/core/jni/android/graphics/pdf/PdfRenderer.cpp b/core/jni/android/graphics/pdf/PdfRenderer.cpp index 95cdbb5cba25..d20c7ef2ec76 100644 --- a/core/jni/android/graphics/pdf/PdfRenderer.cpp +++ b/core/jni/android/graphics/pdf/PdfRenderer.cpp @@ -50,7 +50,6 @@ static jlong nativeOpenPageAndGetSize(JNIEnv* env, jclass thiz, jlong documentPt "cannot load page"); return -1; } - HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, -1) double width = 0; double height = 0; @@ -61,7 +60,6 @@ static jlong nativeOpenPageAndGetSize(JNIEnv* env, jclass thiz, jlong documentPt "cannot get page size"); return -1; } - HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, -1) env->SetIntField(outSize, gPointClassInfo.x, width); env->SetIntField(outSize, gPointClassInfo.y, height); @@ -72,7 +70,6 @@ static jlong nativeOpenPageAndGetSize(JNIEnv* env, jclass thiz, jlong documentPt static void nativeClosePage(JNIEnv* env, jclass thiz, jlong pagePtr) { FPDF_PAGE page = reinterpret_cast<FPDF_PAGE>(pagePtr); FPDF_ClosePage(page); - HANDLE_PDFIUM_ERROR_STATE(env) } static void nativeRenderPage(JNIEnv* env, jclass thiz, jlong documentPtr, jlong pagePtr, @@ -87,11 +84,6 @@ static void nativeRenderPage(JNIEnv* env, jclass thiz, jlong documentPtr, jlong FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(skBitmap.width(), skBitmap.height(), FPDFBitmap_BGRA, skBitmap.getPixels(), stride); - bool isExceptionPending = forwardPdfiumError(env); - if (isExceptionPending || bitmap == NULL) { - ALOGE("Error creating bitmap"); - return; - } int renderFlags = FPDF_REVERSE_BYTE_ORDER; if (renderMode == RENDER_MODE_FOR_DISPLAY) { @@ -129,7 +121,6 @@ static void nativeRenderPage(JNIEnv* env, jclass thiz, jlong documentPtr, jlong FS_RECTF clip = {(float) clipLeft, (float) clipTop, (float) clipRight, (float) clipBottom}; FPDF_RenderPageBitmapWithMatrix(bitmap, page, &transform, &clip, renderFlags); - HANDLE_PDFIUM_ERROR_STATE(env); skBitmap.notifyPixelsChanged(); } diff --git a/core/jni/android/graphics/pdf/PdfUtils.cpp b/core/jni/android/graphics/pdf/PdfUtils.cpp index 905a2aa49b1c..dacca78c650a 100644 --- a/core/jni/android/graphics/pdf/PdfUtils.cpp +++ b/core/jni/android/graphics/pdf/PdfUtils.cpp @@ -78,34 +78,24 @@ bool forwardPdfiumError(JNIEnv* env) { return true; } -static bool initializeLibraryIfNeeded(JNIEnv* env) { +static void initializeLibraryIfNeeded(JNIEnv* env) { if (sUnmatchedPdfiumInitRequestCount == 0) { FPDF_InitLibrary(); - - HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, false); } sUnmatchedPdfiumInitRequestCount++; - return true; } static void destroyLibraryIfNeeded(JNIEnv* env, bool handleError) { if (sUnmatchedPdfiumInitRequestCount == 1) { - FPDF_DestroyLibrary(); - - if (handleError) { - HANDLE_PDFIUM_ERROR_STATE(env); - } + FPDF_DestroyLibrary(); } sUnmatchedPdfiumInitRequestCount--; } jlong nativeOpen(JNIEnv* env, jclass thiz, jint fd, jlong size) { - bool isInitialized = initializeLibraryIfNeeded(env); - if (!isInitialized) { - return -1; - } + initializeLibraryIfNeeded(env); FPDF_FILEACCESS loader; loader.m_FileLen = size; @@ -125,7 +115,6 @@ jlong nativeOpen(JNIEnv* env, jclass thiz, jint fd, jlong size) { void nativeClose(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); FPDF_CloseDocument(document); - HANDLE_PDFIUM_ERROR_STATE(env) destroyLibraryIfNeeded(env, true); } @@ -133,17 +122,12 @@ void nativeClose(JNIEnv* env, jclass thiz, jlong documentPtr) { jint nativeGetPageCount(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); - int pageCount = FPDF_GetPageCount(document); - HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, -1); - - return pageCount; + return FPDF_GetPageCount(document); } jboolean nativeScaleForPrinting(JNIEnv* env, jclass thiz, jlong documentPtr) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); - FPDF_BOOL printScaling = FPDF_VIEWERREF_GetPrintScaling(document); - HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, false); return printScaling ? JNI_TRUE : JNI_FALSE; } diff --git a/core/jni/android/graphics/pdf/PdfUtils.h b/core/jni/android/graphics/pdf/PdfUtils.h index 6e3cebd6414d..65327382e899 100644 --- a/core/jni/android/graphics/pdf/PdfUtils.h +++ b/core/jni/android/graphics/pdf/PdfUtils.h @@ -24,24 +24,6 @@ namespace android { int getBlock(void* param, unsigned long position, unsigned char* outBuffer, unsigned long size); -bool forwardPdfiumError(JNIEnv* env); - -#define HANDLE_PDFIUM_ERROR_STATE(env) \ - { \ - bool isExceptionPending = forwardPdfiumError(env); \ - if (isExceptionPending) { \ - return; \ - } \ - } - -#define HANDLE_PDFIUM_ERROR_STATE_WITH_RET_CODE(env, retCode) \ - { \ - bool isExceptionPending = forwardPdfiumError(env); \ - if (isExceptionPending) { \ - return retCode; \ - } \ - } - jlong nativeOpen(JNIEnv* env, jclass thiz, jint fd, jlong size); void nativeClose(JNIEnv* env, jclass thiz, jlong documentPtr); diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp index c3d5af8a8c59..fba0721d9119 100644 --- a/core/jni/android_graphics_Canvas.cpp +++ b/core/jni/android_graphics_Canvas.cpp @@ -77,11 +77,6 @@ static jint getHeight(jlong canvasHandle) { return static_cast<jint>(get_canvas(canvasHandle)->height()); } -static void setHighContrastText(jlong canvasHandle, jboolean highContrastText) { - Canvas* canvas = get_canvas(canvasHandle); - canvas->setHighContrastText(highContrastText); -} - static jint save(jlong canvasHandle, jint flagsHandle) { SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle); return static_cast<jint>(get_canvas(canvasHandle)->save(flags)); @@ -588,7 +583,6 @@ static const JNINativeMethod gMethods[] = { {"nIsOpaque","(J)Z", (void*) CanvasJNI::isOpaque}, {"nGetWidth","(J)I", (void*) CanvasJNI::getWidth}, {"nGetHeight","(J)I", (void*) CanvasJNI::getHeight}, - {"nSetHighContrastText","(JZ)V", (void*) CanvasJNI::setHighContrastText}, {"nSave","(JI)I", (void*) CanvasJNI::save}, {"nSaveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer}, {"nSaveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha}, diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp index 2702d1d29e4c..a140b57268d1 100644 --- a/core/jni/android_os_Debug.cpp +++ b/core/jni/android_os_Debug.cpp @@ -29,6 +29,7 @@ #include <time.h> #include <unistd.h> +#include <atomic> #include <iomanip> #include <string> @@ -44,16 +45,11 @@ #include "jni.h" #include <memtrack/memtrack.h> #include <memunreachable/memunreachable.h> +#include "android_os_Debug.h" namespace android { -static void safeFclose(FILE* fp) { - if (fp) fclose(fp); -} - -using UniqueFile = std::unique_ptr<FILE, decltype(&safeFclose)>; - static inline UniqueFile MakeUniqueFile(const char* path, const char* mode) { return UniqueFile(fopen(path, mode), safeFclose); } @@ -155,6 +151,14 @@ struct stats_t { int swappedOutPss; }; +enum pss_rollup_support { + PSS_ROLLUP_UNTRIED, + PSS_ROLLUP_SUPPORTED, + PSS_ROLLUP_UNSUPPORTED +}; + +static std::atomic<pss_rollup_support> g_pss_rollup_support; + #define BINDER_STATS "/proc/binder/stats" static jlong android_os_Debug_getNativeHeapSize(JNIEnv *env, jobject clazz) @@ -548,6 +552,33 @@ static void android_os_Debug_getDirtyPages(JNIEnv *env, jobject clazz, jobject o android_os_Debug_getDirtyPagesPid(env, clazz, getpid(), object); } +UniqueFile OpenSmapsOrRollup(int pid) +{ + enum pss_rollup_support rollup_support = + g_pss_rollup_support.load(std::memory_order_relaxed); + if (rollup_support != PSS_ROLLUP_UNSUPPORTED) { + std::string smaps_rollup_path = + base::StringPrintf("/proc/%d/smaps_rollup", pid); + UniqueFile fp_rollup = MakeUniqueFile(smaps_rollup_path.c_str(), "re"); + if (fp_rollup == nullptr && errno != ENOENT) { + return fp_rollup; // Actual error, not just old kernel. + } + if (fp_rollup != nullptr) { + if (rollup_support == PSS_ROLLUP_UNTRIED) { + ALOGI("using rollup pss collection"); + g_pss_rollup_support.store(PSS_ROLLUP_SUPPORTED, + std::memory_order_relaxed); + } + return fp_rollup; + } + g_pss_rollup_support.store(PSS_ROLLUP_UNSUPPORTED, + std::memory_order_relaxed); + } + + std::string smaps_path = base::StringPrintf("/proc/%d/smaps", pid); + return MakeUniqueFile(smaps_path.c_str(), "re"); +} + static jlong android_os_Debug_getPssPid(JNIEnv *env, jobject clazz, jint pid, jlongArray outUssSwapPss, jlongArray outMemtrack) { @@ -563,12 +594,11 @@ static jlong android_os_Debug_getPssPid(JNIEnv *env, jobject clazz, jint pid, } { - std::string smaps_path = base::StringPrintf("/proc/%d/smaps", pid); - UniqueFile fp = MakeUniqueFile(smaps_path.c_str(), "re"); + UniqueFile fp = OpenSmapsOrRollup(pid); if (fp != nullptr) { while (true) { - if (fgets(line, 1024, fp.get()) == NULL) { + if (fgets(line, sizeof (line), fp.get()) == NULL) { break; } diff --git a/cmds/incidentd/src/section_list.cpp b/core/jni/android_os_Debug.h index 80ddb86da509..81270ca994bb 100644 --- a/cmds/incidentd/src/section_list.cpp +++ b/core/jni/android_os_Debug.h @@ -14,17 +14,21 @@ * limitations under the License. */ -#include "section_list.h" +#ifndef ANDROID_OS_DEBUG_H +#define ANDROID_OS_DEBUG_H -/** - * This is the mapping of section IDs to the commands that are run to get those commands. - */ -const Section* SECTION_LIST[] = { - // Linux Services - new CommandSection(2000, "/system/xbin/procrank", NULL), - new FileSection(2002, "/d/wakeup_sources"), +#include <memory> +#include <stdio.h> + +namespace android { + +inline void safeFclose(FILE* fp) { + if (fp) fclose(fp); +} + +using UniqueFile = std::unique_ptr<FILE, decltype(&safeFclose)>; +UniqueFile OpenSmapsOrRollup(int pid); + +} // namespace android - // System Services - new DumpsysSection(3000, "fingerprint", "--proto", "--incident", NULL), - NULL -}; +#endif // ANDROID_OS_HW_BLOB_H diff --git a/core/jni/android_os_HwBlob.cpp b/core/jni/android_os_HwBlob.cpp index 0c23797b627b..40d49b7662d9 100644 --- a/core/jni/android_os_HwBlob.cpp +++ b/core/jni/android_os_HwBlob.cpp @@ -83,12 +83,6 @@ JHwBlob::JHwBlob(JNIEnv *env, jobject thiz, size_t size) mSize(size), mOwnsBuffer(true), mHandle(0) { - jclass clazz = env->GetObjectClass(thiz); - CHECK(clazz != NULL); - - mClass = (jclass)env->NewGlobalRef(clazz); - mObject = env->NewWeakGlobalRef(thiz); - if (size > 0) { mBuffer = malloc(size); } @@ -99,14 +93,6 @@ JHwBlob::~JHwBlob() { free(mBuffer); mBuffer = nullptr; } - - JNIEnv *env = AndroidRuntime::getJNIEnv(); - - env->DeleteWeakGlobalRef(mObject); - mObject = NULL; - - env->DeleteGlobalRef(mClass); - mClass = NULL; } void JHwBlob::setTo(const void *ptr, size_t handle) { diff --git a/core/jni/android_os_HwBlob.h b/core/jni/android_os_HwBlob.h index 09204880881b..39393cb76c23 100644 --- a/core/jni/android_os_HwBlob.h +++ b/core/jni/android_os_HwBlob.h @@ -70,9 +70,6 @@ private: sp<JHwBlob> mBlob; }; - jclass mClass; - jobject mObject; - void *mBuffer; size_t mSize; bool mOwnsBuffer; diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp index b412b6a016b6..9494fb8e7eef 100644 --- a/core/jni/android_os_HwParcel.cpp +++ b/core/jni/android_os_HwParcel.cpp @@ -166,10 +166,6 @@ JHwParcel::JHwParcel(JNIEnv *env, jobject thiz) mOwnsParcel(false), mTransactCallback(nullptr), mWasSent(false) { - jclass clazz = env->GetObjectClass(thiz); - CHECK(clazz != NULL); - - mObject = env->NewWeakGlobalRef(thiz); } JHwParcel::~JHwParcel() { @@ -178,9 +174,6 @@ JHwParcel::~JHwParcel() { mStorage.release(env); setParcel(NULL, false /* assumeOwnership */); - - env->DeleteWeakGlobalRef(mObject); - mObject = NULL; } hardware::Parcel *JHwParcel::getParcel() { diff --git a/core/jni/android_os_HwParcel.h b/core/jni/android_os_HwParcel.h index f6e61004b0e3..2c26993a0439 100644 --- a/core/jni/android_os_HwParcel.h +++ b/core/jni/android_os_HwParcel.h @@ -53,8 +53,6 @@ protected: virtual ~JHwParcel(); private: - jobject mObject; - hardware::Parcel *mParcel; bool mOwnsParcel; diff --git a/core/jni/android_os_SystemProperties.cpp b/core/jni/android_os_SystemProperties.cpp index 8844fb0a261f..a94cac0f18f5 100644 --- a/core/jni/android_os_SystemProperties.cpp +++ b/core/jni/android_os_SystemProperties.cpp @@ -17,188 +17,109 @@ #define LOG_TAG "SysPropJNI" +#include "android-base/logging.h" +#include "android-base/properties.h" #include "cutils/properties.h" #include "utils/misc.h" #include <utils/Log.h> #include "jni.h" #include "core_jni_helpers.h" #include <nativehelper/JNIHelp.h> +#include <nativehelper/ScopedPrimitiveArray.h> +#include <nativehelper/ScopedUtfChars.h> namespace android { -static jstring SystemProperties_getSS(JNIEnv *env, jobject clazz, - jstring keyJ, jstring defJ) -{ - int len; - const char* key; - char buf[PROPERTY_VALUE_MAX]; - jstring rvJ = NULL; - - if (keyJ == NULL) { - jniThrowNullPointerException(env, "key must not be null."); - goto error; - } - - key = env->GetStringUTFChars(keyJ, NULL); - - len = property_get(key, buf, ""); - if ((len <= 0) && (defJ != NULL)) { - rvJ = defJ; - } else if (len >= 0) { - rvJ = env->NewStringUTF(buf); - } else { - rvJ = env->NewStringUTF(""); +namespace { + +template <typename T, typename Handler> +T ConvertKeyAndForward(JNIEnv *env, jstring keyJ, T defJ, Handler handler) { + std::string key; + { + // Scope the String access. If the handler can throw an exception, + // releasing the string characters late would trigger an abort. + ScopedUtfChars key_utf(env, keyJ); + if (key_utf.c_str() == nullptr) { + return defJ; + } + key = key_utf.c_str(); // This will make a copy, but we can't avoid + // with the existing interface in + // android::base. } - - env->ReleaseStringUTFChars(keyJ, key); - -error: - return rvJ; + return handler(key, defJ); } -static jstring SystemProperties_getS(JNIEnv *env, jobject clazz, - jstring keyJ) +jstring SystemProperties_getSS(JNIEnv *env, jclass clazz, jstring keyJ, + jstring defJ) { - return SystemProperties_getSS(env, clazz, keyJ, NULL); + // Using ConvertKeyAndForward is sub-optimal for copying the key string, + // but improves reuse and reasoning over code. + auto handler = [&](const std::string& key, jstring defJ) { + std::string prop_val = android::base::GetProperty(key, ""); + if (!prop_val.empty()) { + return env->NewStringUTF(prop_val.c_str()); + }; + if (defJ != nullptr) { + return defJ; + } + // This function is specified to never return null (or have an + // exception pending). + return env->NewStringUTF(""); + }; + return ConvertKeyAndForward(env, keyJ, defJ, handler); } -static jint SystemProperties_get_int(JNIEnv *env, jobject clazz, - jstring keyJ, jint defJ) +jstring SystemProperties_getS(JNIEnv *env, jclass clazz, jstring keyJ) { - int len; - const char* key; - char buf[PROPERTY_VALUE_MAX]; - char* end; - jint result = defJ; - - if (keyJ == NULL) { - jniThrowNullPointerException(env, "key must not be null."); - goto error; - } - - key = env->GetStringUTFChars(keyJ, NULL); - - len = property_get(key, buf, ""); - if (len > 0) { - result = strtol(buf, &end, 0); - if (end == buf) { - result = defJ; - } - } - - env->ReleaseStringUTFChars(keyJ, key); - -error: - return result; + return SystemProperties_getSS(env, clazz, keyJ, nullptr); } -static jlong SystemProperties_get_long(JNIEnv *env, jobject clazz, - jstring keyJ, jlong defJ) +template <typename T> +T SystemProperties_get_integral(JNIEnv *env, jclass, jstring keyJ, + T defJ) { - int len; - const char* key; - char buf[PROPERTY_VALUE_MAX]; - char* end; - jlong result = defJ; - - if (keyJ == NULL) { - jniThrowNullPointerException(env, "key must not be null."); - goto error; - } - - key = env->GetStringUTFChars(keyJ, NULL); - - len = property_get(key, buf, ""); - if (len > 0) { - result = strtoll(buf, &end, 0); - if (end == buf) { - result = defJ; - } - } - - env->ReleaseStringUTFChars(keyJ, key); - -error: - return result; + auto handler = [](const std::string& key, T defV) { + return android::base::GetIntProperty<T>(key, defV); + }; + return ConvertKeyAndForward(env, keyJ, defJ, handler); } -static jboolean SystemProperties_get_boolean(JNIEnv *env, jobject clazz, - jstring keyJ, jboolean defJ) +jboolean SystemProperties_get_boolean(JNIEnv *env, jclass, jstring keyJ, + jboolean defJ) { - int len; - const char* key; - char buf[PROPERTY_VALUE_MAX]; - jboolean result = defJ; - - if (keyJ == NULL) { - jniThrowNullPointerException(env, "key must not be null."); - goto error; - } - - key = env->GetStringUTFChars(keyJ, NULL); - - len = property_get(key, buf, ""); - if (len == 1) { - char ch = buf[0]; - if (ch == '0' || ch == 'n') - result = false; - else if (ch == '1' || ch == 'y') - result = true; - } else if (len > 1) { - if (!strcmp(buf, "no") || !strcmp(buf, "false") || !strcmp(buf, "off")) { - result = false; - } else if (!strcmp(buf, "yes") || !strcmp(buf, "true") || !strcmp(buf, "on")) { - result = true; - } - } - - env->ReleaseStringUTFChars(keyJ, key); - -error: - return result; + auto handler = [](const std::string& key, jboolean defV) -> jboolean { + bool result = android::base::GetBoolProperty(key, defV); + return result ? JNI_TRUE : JNI_FALSE; + }; + return ConvertKeyAndForward(env, keyJ, defJ, handler); } -static void SystemProperties_set(JNIEnv *env, jobject clazz, - jstring keyJ, jstring valJ) +void SystemProperties_set(JNIEnv *env, jobject clazz, jstring keyJ, + jstring valJ) { - int err; - const char* key; - const char* val; - - if (keyJ == NULL) { - jniThrowNullPointerException(env, "key must not be null."); - return ; - } - key = env->GetStringUTFChars(keyJ, NULL); - - if (valJ == NULL) { - val = ""; /* NULL pointer not allowed here */ - } else { - val = env->GetStringUTFChars(valJ, NULL); - } - - err = property_set(key, val); - - env->ReleaseStringUTFChars(keyJ, key); - - if (valJ != NULL) { - env->ReleaseStringUTFChars(valJ, val); - } - - if (err < 0) { + auto handler = [&](const std::string& key, bool) { + std::string val; + if (valJ != nullptr) { + ScopedUtfChars key_utf(env, valJ); + val = key_utf.c_str(); + } + return android::base::SetProperty(key, val); + }; + if (!ConvertKeyAndForward(env, keyJ, true, handler)) { + // Must have been a failure in SetProperty. jniThrowException(env, "java/lang/RuntimeException", "failed to set system property"); } } -static JavaVM* sVM = NULL; -static jclass sClazz = NULL; -static jmethodID sCallChangeCallbacks; +JavaVM* sVM = nullptr; +jclass sClazz = nullptr; +jmethodID sCallChangeCallbacks; -static void do_report_sysprop_change() { +void do_report_sysprop_change() { //ALOGI("Java SystemProperties: VM=%p, Clazz=%p", sVM, sClazz); - if (sVM != NULL && sClazz != NULL) { + if (sVM != nullptr && sClazz != nullptr) { JNIEnv* env; if (sVM->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0) { //ALOGI("Java SystemProperties: calling %p", sCallChangeCallbacks); @@ -207,47 +128,49 @@ static void do_report_sysprop_change() { } } -static void SystemProperties_add_change_callback(JNIEnv *env, jobject clazz) +void SystemProperties_add_change_callback(JNIEnv *env, jobject clazz) { // This is called with the Java lock held. - if (sVM == NULL) { + if (sVM == nullptr) { env->GetJavaVM(&sVM); } - if (sClazz == NULL) { + if (sClazz == nullptr) { sClazz = (jclass) env->NewGlobalRef(clazz); sCallChangeCallbacks = env->GetStaticMethodID(sClazz, "callChangeCallbacks", "()V"); add_sysprop_change_callback(do_report_sysprop_change, -10000); } } -static void SystemProperties_report_sysprop_change(JNIEnv /**env*/, jobject /*clazz*/) +void SystemProperties_report_sysprop_change(JNIEnv /**env*/, jobject /*clazz*/) { report_sysprop_change(); } -static const JNINativeMethod method_table[] = { - { "native_get", "(Ljava/lang/String;)Ljava/lang/String;", - (void*) SystemProperties_getS }, - { "native_get", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", - (void*) SystemProperties_getSS }, - { "native_get_int", "(Ljava/lang/String;I)I", - (void*) SystemProperties_get_int }, - { "native_get_long", "(Ljava/lang/String;J)J", - (void*) SystemProperties_get_long }, - { "native_get_boolean", "(Ljava/lang/String;Z)Z", - (void*) SystemProperties_get_boolean }, - { "native_set", "(Ljava/lang/String;Ljava/lang/String;)V", - (void*) SystemProperties_set }, - { "native_add_change_callback", "()V", - (void*) SystemProperties_add_change_callback }, - { "native_report_sysprop_change", "()V", - (void*) SystemProperties_report_sysprop_change }, -}; +} // namespace int register_android_os_SystemProperties(JNIEnv *env) { - return RegisterMethodsOrDie(env, "android/os/SystemProperties", method_table, - NELEM(method_table)); + const JNINativeMethod method_table[] = { + { "native_get", "(Ljava/lang/String;)Ljava/lang/String;", + (void*) SystemProperties_getS }, + { "native_get", + "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", + (void*) SystemProperties_getSS }, + { "native_get_int", "(Ljava/lang/String;I)I", + (void*) SystemProperties_get_integral<jint> }, + { "native_get_long", "(Ljava/lang/String;J)J", + (void*) SystemProperties_get_integral<jlong> }, + { "native_get_boolean", "(Ljava/lang/String;Z)Z", + (void*) SystemProperties_get_boolean }, + { "native_set", "(Ljava/lang/String;Ljava/lang/String;)V", + (void*) SystemProperties_set }, + { "native_add_change_callback", "()V", + (void*) SystemProperties_add_change_callback }, + { "native_report_sysprop_change", "()V", + (void*) SystemProperties_report_sysprop_change }, + }; + return RegisterMethodsOrDie(env, "android/os/SystemProperties", + method_table, NELEM(method_table)); } }; diff --git a/core/jni/android_text_StaticLayout.cpp b/core/jni/android_text_StaticLayout.cpp index 82a6411826c9..7442fa2d62dc 100644 --- a/core/jni/android_text_StaticLayout.cpp +++ b/core/jni/android_text_StaticLayout.cpp @@ -44,23 +44,54 @@ namespace android { struct JLineBreaksID { jfieldID breaks; jfieldID widths; + jfieldID ascents; + jfieldID descents; jfieldID flags; }; static jclass gLineBreaks_class; static JLineBreaksID gLineBreaks_fieldID; +class JNILineBreakerLineWidth : public minikin::LineBreaker::LineWidthDelegate { + public: + JNILineBreakerLineWidth(float firstWidth, int32_t firstLineCount, float restWidth, + std::vector<float>&& indents, int32_t indentsOffset) + : mFirstWidth(firstWidth), mFirstLineCount(firstLineCount), mRestWidth(restWidth), + mIndents(std::move(indents)), mIndentsOffset(indentsOffset) {} + + float getLineWidth(size_t lineNo) override { + const float width = ((ssize_t)lineNo < (ssize_t)mFirstLineCount) + ? mFirstWidth : mRestWidth; + if (mIndents.empty()) { + return width; + } + + const size_t indentIndex = lineNo + mIndentsOffset; + if (indentIndex < mIndents.size()) { + return width - mIndents[indentIndex]; + } else { + return width - mIndents.back(); + } + } + + private: + const float mFirstWidth; + const int32_t mFirstLineCount; + const float mRestWidth; + const std::vector<float> mIndents; + const int32_t mIndentsOffset; +}; + // set text and set a number of parameters for creating a layout (width, tabstops, strategy, // hyphenFrequency) static void nSetupParagraph(JNIEnv* env, jclass, jlong nativePtr, jcharArray text, jint length, jfloat firstWidth, jint firstWidthLineLimit, jfloat restWidth, jintArray variableTabStops, jint defaultTabStop, jint strategy, jint hyphenFrequency, - jboolean isJustified) { + jboolean isJustified, jintArray indents, jint indentsOffset) { minikin::LineBreaker* b = reinterpret_cast<minikin::LineBreaker*>(nativePtr); b->resize(length); env->GetCharArrayRegion(text, 0, length, b->buffer()); b->setText(); - b->setLineWidths(firstWidth, firstWidthLineLimit, restWidth); if (variableTabStops == nullptr) { b->setTabStops(nullptr, 0, defaultTabStop); } else { @@ -70,38 +101,57 @@ static void nSetupParagraph(JNIEnv* env, jclass, jlong nativePtr, jcharArray tex b->setStrategy(static_cast<minikin::BreakStrategy>(strategy)); b->setHyphenationFrequency(static_cast<minikin::HyphenationFrequency>(hyphenFrequency)); b->setJustified(isJustified); + + std::vector<float> indentVec; + // TODO: copy indents only once when LineBreaker is started to be used. + if (indents != nullptr) { + ScopedIntArrayRO indentArr(env, indents); + indentVec.assign(indentArr.get(), indentArr.get() + indentArr.size()); + } + b->setLineWidthDelegate(std::make_unique<JNILineBreakerLineWidth>( + firstWidth, firstWidthLineLimit, restWidth, std::move(indentVec), indentsOffset)); } static void recycleCopy(JNIEnv* env, jobject recycle, jintArray recycleBreaks, - jfloatArray recycleWidths, jintArray recycleFlags, + jfloatArray recycleWidths, jfloatArray recycleAscents, + jfloatArray recycleDescents, jintArray recycleFlags, jint recycleLength, size_t nBreaks, const jint* breaks, - const jfloat* widths, const jint* flags) { + const jfloat* widths, const jfloat* ascents, const jfloat* descents, + const jint* flags) { if ((size_t)recycleLength < nBreaks) { // have to reallocate buffers recycleBreaks = env->NewIntArray(nBreaks); recycleWidths = env->NewFloatArray(nBreaks); + recycleAscents = env->NewFloatArray(nBreaks); + recycleDescents = env->NewFloatArray(nBreaks); recycleFlags = env->NewIntArray(nBreaks); env->SetObjectField(recycle, gLineBreaks_fieldID.breaks, recycleBreaks); env->SetObjectField(recycle, gLineBreaks_fieldID.widths, recycleWidths); + env->SetObjectField(recycle, gLineBreaks_fieldID.ascents, recycleAscents); + env->SetObjectField(recycle, gLineBreaks_fieldID.descents, recycleDescents); env->SetObjectField(recycle, gLineBreaks_fieldID.flags, recycleFlags); } // copy data env->SetIntArrayRegion(recycleBreaks, 0, nBreaks, breaks); env->SetFloatArrayRegion(recycleWidths, 0, nBreaks, widths); + env->SetFloatArrayRegion(recycleAscents, 0, nBreaks, ascents); + env->SetFloatArrayRegion(recycleDescents, 0, nBreaks, descents); env->SetIntArrayRegion(recycleFlags, 0, nBreaks, flags); } static jint nComputeLineBreaks(JNIEnv* env, jclass, jlong nativePtr, jobject recycle, jintArray recycleBreaks, - jfloatArray recycleWidths, jintArray recycleFlags, + jfloatArray recycleWidths, jfloatArray recycleAscents, + jfloatArray recycleDescents, jintArray recycleFlags, jint recycleLength) { minikin::LineBreaker* b = reinterpret_cast<minikin::LineBreaker*>(nativePtr); size_t nBreaks = b->computeBreaks(); - recycleCopy(env, recycle, recycleBreaks, recycleWidths, recycleFlags, recycleLength, - nBreaks, b->getBreaks(), b->getWidths(), b->getFlags()); + recycleCopy(env, recycle, recycleBreaks, recycleWidths, recycleAscents, recycleDescents, + recycleFlags, recycleLength, nBreaks, b->getBreaks(), b->getWidths(), b->getAscents(), + b->getDescents(), b->getFlags()); b->finish(); @@ -152,13 +202,6 @@ static void nSetLocales(JNIEnv* env, jclass, jlong nativePtr, jstring javaLocale b->setLocales(localeNames.c_str(), hyphVec); } -static void nSetIndents(JNIEnv* env, jclass, jlong nativePtr, jintArray indents) { - ScopedIntArrayRO indentArr(env, indents); - std::vector<float> indentVec(indentArr.get(), indentArr.get() + indentArr.size()); - minikin::LineBreaker* b = reinterpret_cast<minikin::LineBreaker*>(nativePtr); - b->setIndents(indentVec); -} - // Basically similar to Paint.getTextRunAdvances but with C++ interface static jfloat nAddStyleRun(JNIEnv* env, jclass, jlong nativePtr, jlong nativePaint, jint start, jint end, jboolean isRtl) { @@ -199,13 +242,12 @@ static const JNINativeMethod gMethods[] = { {"nFinishBuilder", "(J)V", (void*) nFinishBuilder}, {"nLoadHyphenator", "(Ljava/nio/ByteBuffer;III)J", (void*) nLoadHyphenator}, {"nSetLocales", "(JLjava/lang/String;[J)V", (void*) nSetLocales}, - {"nSetupParagraph", "(J[CIFIF[IIIIZ)V", (void*) nSetupParagraph}, - {"nSetIndents", "(J[I)V", (void*) nSetIndents}, + {"nSetupParagraph", "(J[CIFIF[IIIIZ[II)V", (void*) nSetupParagraph}, {"nAddStyleRun", "(JJIIZ)F", (void*) nAddStyleRun}, {"nAddMeasuredRun", "(JII[F)V", (void*) nAddMeasuredRun}, {"nAddReplacementRun", "(JIIF)V", (void*) nAddReplacementRun}, {"nGetWidths", "(J[F)V", (void*) nGetWidths}, - {"nComputeLineBreaks", "(JLandroid/text/StaticLayout$LineBreaks;[I[F[II)I", + {"nComputeLineBreaks", "(JLandroid/text/StaticLayout$LineBreaks;[I[F[F[F[II)I", (void*) nComputeLineBreaks} }; @@ -216,6 +258,8 @@ int register_android_text_StaticLayout(JNIEnv* env) gLineBreaks_fieldID.breaks = GetFieldIDOrDie(env, gLineBreaks_class, "breaks", "[I"); gLineBreaks_fieldID.widths = GetFieldIDOrDie(env, gLineBreaks_class, "widths", "[F"); + gLineBreaks_fieldID.ascents = GetFieldIDOrDie(env, gLineBreaks_class, "ascents", "[F"); + gLineBreaks_fieldID.descents = GetFieldIDOrDie(env, gLineBreaks_class, "descents", "[F"); gLineBreaks_fieldID.flags = GetFieldIDOrDie(env, gLineBreaks_class, "flags", "[I"); return RegisterMethodsOrDie(env, "android/text/StaticLayout", gMethods, NELEM(gMethods)); diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index 44f15cd637ed..33c8304f2547 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -31,6 +31,7 @@ #include "android_util_Binder.h" #include <nativehelper/JNIHelp.h> +#include "android_os_Debug.h" #include <dirent.h> #include <fcntl.h> @@ -1092,27 +1093,21 @@ static jlong android_os_Process_getElapsedCpuTime(JNIEnv* env, jobject clazz) static jlong android_os_Process_getPss(JNIEnv* env, jobject clazz, jint pid) { - char filename[64]; - - snprintf(filename, sizeof(filename), "/proc/%" PRId32 "/smaps", pid); - - FILE * file = fopen(filename, "r"); - if (!file) { + UniqueFile file = OpenSmapsOrRollup(pid); + if (file == nullptr) { return (jlong) -1; } // Tally up all of the Pss from the various maps char line[256]; jlong pss = 0; - while (fgets(line, sizeof(line), file)) { + while (fgets(line, sizeof(line), file.get())) { jlong v; if (sscanf(line, "Pss: %" SCNd64 " kB", &v) == 1) { pss += v; } } - fclose(file); - // Return the Pss value in bytes, not kilobytes return pss * 1024; } diff --git a/core/jni/android_util_StatsLog.cpp b/core/jni/android_util_StatsLog.cpp new file mode 100644 index 000000000000..c992365094f7 --- /dev/null +++ b/core/jni/android_util_StatsLog.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2007-2014 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. + */ + +#include <fcntl.h> +#include <log/log_event_list.h> + +#include <log/log.h> + +#include <nativehelper/JNIHelp.h> +#include "core_jni_helpers.h" +#include "jni.h" + +#define UNUSED __attribute__((__unused__)) + +namespace android { + +static jclass gCollectionClass; +static jmethodID gCollectionAddID; + +static jclass gIntegerClass; +static jfieldID gIntegerValueID; + +static jclass gLongClass; +static jfieldID gLongValueID; + +static jclass gFloatClass; +static jfieldID gFloatValueID; + +static jclass gStringClass; + +/* + * In class android.util.StatsLog: + * static native int writeInt(int tag, int value) + */ +static jint android_util_StatsLog_write_Integer(JNIEnv* env UNUSED, + jobject clazz UNUSED, + jint tag, jint value) +{ + android_log_event_list ctx(tag); + ctx << (int32_t)value; + return ctx.write(LOG_ID_STATS); +} + +/* + * In class android.util.StatsLog: + * static native int writeLong(long tag, long value) + */ +static jint android_util_StatsLog_write_Long(JNIEnv* env UNUSED, + jobject clazz UNUSED, + jint tag, jlong value) +{ + android_log_event_list ctx(tag); + ctx << (int64_t)value; + return ctx.write(LOG_ID_STATS); +} + +/* + * In class android.util.StatsLog: + * static native int writeFloat(long tag, float value) + */ +static jint android_util_StatsLog_write_Float(JNIEnv* env UNUSED, + jobject clazz UNUSED, + jint tag, jfloat value) +{ + android_log_event_list ctx(tag); + ctx << (float)value; + return ctx.write(LOG_ID_STATS); +} + +/* + * In class android.util.StatsLog: + * static native int writeString(int tag, String value) + */ +static jint android_util_StatsLog_write_String(JNIEnv* env, + jobject clazz UNUSED, + jint tag, jstring value) { + android_log_event_list ctx(tag); + // Don't throw NPE -- I feel like it's sort of mean for a logging function + // to be all crashy if you pass in NULL -- but make the NULL value explicit. + if (value != NULL) { + const char *str = env->GetStringUTFChars(value, NULL); + ctx << str; + env->ReleaseStringUTFChars(value, str); + } else { + ctx << "NULL"; + } + return ctx.write(LOG_ID_STATS); +} + +/* + * In class android.util.StatsLog: + * static native int writeArray(long tag, Object... value) + */ +static jint android_util_StatsLog_write_Array(JNIEnv* env, jobject clazz, + jint tag, jobjectArray value) { + android_log_event_list ctx(tag); + + if (value == NULL) { + ctx << "[NULL]"; + return ctx.write(LOG_ID_STATS); + } + + jsize copied = 0, num = env->GetArrayLength(value); + for (; copied < num && copied < 255; ++copied) { + if (ctx.status()) break; + jobject item = env->GetObjectArrayElement(value, copied); + if (item == NULL) { + ctx << "NULL"; + } else if (env->IsInstanceOf(item, gStringClass)) { + const char *str = env->GetStringUTFChars((jstring) item, NULL); + ctx << str; + env->ReleaseStringUTFChars((jstring) item, str); + } else if (env->IsInstanceOf(item, gIntegerClass)) { + ctx << (int32_t)env->GetIntField(item, gIntegerValueID); + } else if (env->IsInstanceOf(item, gLongClass)) { + ctx << (int64_t)env->GetLongField(item, gLongValueID); + } else if (env->IsInstanceOf(item, gFloatClass)) { + ctx << (float)env->GetFloatField(item, gFloatValueID); + } else { + jniThrowException(env, + "java/lang/IllegalArgumentException", + "Invalid payload item type"); + return -1; + } + env->DeleteLocalRef(item); + } + return ctx.write(LOG_ID_STATS); +} + +/* + * JNI registration. + */ +static const JNINativeMethod gRegisterMethods[] = { + /* name, signature, funcPtr */ + { "writeInt", "(II)I", (void*) android_util_StatsLog_write_Integer }, + { "writeLong", "(IJ)I", (void*) android_util_StatsLog_write_Long }, + { "writeFloat", "(IF)I", (void*) android_util_StatsLog_write_Float }, + { "writeString", + "(ILjava/lang/String;)I", + (void*) android_util_StatsLog_write_String + }, + { "writeArray", + "(I[Ljava/lang/Object;)I", + (void*) android_util_StatsLog_write_Array + }, +}; + +static struct { const char *name; jclass *clazz; } gClasses[] = { + { "java/lang/Integer", &gIntegerClass }, + { "java/lang/Long", &gLongClass }, + { "java/lang/Float", &gFloatClass }, + { "java/lang/String", &gStringClass }, + { "java/util/Collection", &gCollectionClass }, +}; + +static struct { jclass *c; const char *name, *ft; jfieldID *id; } gFields[] = { + { &gIntegerClass, "value", "I", &gIntegerValueID }, + { &gLongClass, "value", "J", &gLongValueID }, + { &gFloatClass, "value", "F", &gFloatValueID }, +}; + +static struct { jclass *c; const char *name, *mt; jmethodID *id; } gMethods[] = { + { &gCollectionClass, "add", "(Ljava/lang/Object;)Z", &gCollectionAddID }, +}; + +int register_android_util_StatsLog(JNIEnv* env) { + for (int i = 0; i < NELEM(gClasses); ++i) { + jclass clazz = FindClassOrDie(env, gClasses[i].name); + *gClasses[i].clazz = MakeGlobalRefOrDie(env, clazz); + } + + for (int i = 0; i < NELEM(gFields); ++i) { + *gFields[i].id = GetFieldIDOrDie(env, + *gFields[i].c, gFields[i].name, gFields[i].ft); + } + + for (int i = 0; i < NELEM(gMethods); ++i) { + *gMethods[i].id = GetMethodIDOrDie(env, + *gMethods[i].c, gMethods[i].name, gMethods[i].mt); + } + + return RegisterMethodsOrDie( + env, + "android/util/StatsLog", + gRegisterMethods, NELEM(gRegisterMethods)); +} + +}; // namespace android diff --git a/core/jni/android_view_DisplayListCanvas.cpp b/core/jni/android_view_DisplayListCanvas.cpp index 2c4771c18d0f..98f47330829b 100644 --- a/core/jni/android_view_DisplayListCanvas.cpp +++ b/core/jni/android_view_DisplayListCanvas.cpp @@ -33,6 +33,7 @@ #include <CanvasProperty.h> #include <hwui/Canvas.h> #include <hwui/Paint.h> +#include <minikin/Layout.h> #include <renderthread/RenderProxy.h> #include "core_jni_helpers.h" @@ -94,6 +95,7 @@ static void android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) { int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor); android::uirenderer::renderthread::RenderProxy::dumpGraphicsMemory(fd); + minikin::Layout::dumpMinikinStats(fd); } diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index db9b52e4fdbd..33f1c7d393af 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -736,6 +736,15 @@ static void nativeReparentChildren(JNIEnv* env, jclass clazz, jlong nativeObject ctrl->reparentChildren(handle); } +static void nativeReparentChild(JNIEnv* env, jclass clazz, jlong nativeObject, + jobject newParentObject, jobject childObject) { + auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + sp<IBinder> parentHandle = ibinderForJavaObject(env, newParentObject); + sp<IBinder> childHandle = ibinderForJavaObject(env, childObject); + + ctrl->reparentChild(parentHandle, childHandle); +} + static void nativeSeverChildren(JNIEnv* env, jclass clazz, jlong nativeObject) { auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); ctrl->detachChildren(); @@ -859,6 +868,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeDeferTransactionUntilSurface }, {"nativeReparentChildren", "(JLandroid/os/IBinder;)V", (void*)nativeReparentChildren } , + {"nativeReparentChild", "(JLandroid/os/IBinder;Landroid/os/IBinder;)V", + (void*)nativeReparentChild }, {"nativeSeverChildren", "(J)V", (void*)nativeSeverChildren } , {"nativeSetOverrideScalingMode", "(JI)V", diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp index 46b0a79d9f6f..2f5b2e2b7edd 100644 --- a/core/jni/android_view_ThreadedRenderer.cpp +++ b/core/jni/android_view_ThreadedRenderer.cpp @@ -47,6 +47,7 @@ #include <FrameInfo.h> #include <FrameMetricsObserver.h> #include <IContextFactory.h> +#include <Properties.h> #include <PropertyValuesAnimatorSet.h> #include <RenderNode.h> #include <renderthread/CanvasContext.h> @@ -923,13 +924,18 @@ static jobject android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode( // Continue I guess? } sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer); - return createBitmap(env, bitmap.release(), android::bitmap::kBitmapCreateFlag_Mutable); + return bitmap::createBitmap(env, bitmap.release(), + android::bitmap::kBitmapCreateFlag_Premultiplied); } static void android_view_ThreadedRenderer_disableVsync(JNIEnv*, jclass) { RenderProxy::disableVsync(); } +static void android_view_ThreadedRenderer_setHighContrastText(JNIEnv*, jclass, jboolean enable) { + Properties::enableHighContrastText = enable; +} + // ---------------------------------------------------------------------------- // FrameMetricsObserver // ---------------------------------------------------------------------------- @@ -1029,6 +1035,7 @@ static const JNINativeMethod gMethods[] = { { "nCreateHardwareBitmap", "(JII)Landroid/graphics/Bitmap;", (void*)android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode }, { "disableVsync", "()V", (void*)android_view_ThreadedRenderer_disableVsync }, + { "nSetHighContrastText", "(Z)V", (void*)android_view_ThreadedRenderer_setHighContrastText }, }; int register_android_view_ThreadedRenderer(JNIEnv* env) { diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index dba819480805..fffdda13d11f 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -45,6 +45,8 @@ #include <unistd.h> #include "android-base/logging.h" +#include <android-base/file.h> +#include <android-base/stringprintf.h> #include <cutils/fs.h> #include <cutils/multiuser.h> #include <cutils/sched_policy.h> @@ -65,6 +67,8 @@ namespace { using android::String8; +using android::base::StringPrintf; +using android::base::WriteStringToFile; static pid_t gSystemServerPid = 0; @@ -674,6 +678,22 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra } return pid; } + +static uint64_t GetEffectiveCapabilityMask(JNIEnv* env) { + __user_cap_header_struct capheader; + memset(&capheader, 0, sizeof(capheader)); + capheader.version = _LINUX_CAPABILITY_VERSION_3; + capheader.pid = 0; + + __user_cap_data_struct capdata[2]; + if (capget(&capheader, &capdata[0]) == -1) { + ALOGE("capget failed: %s", strerror(errno)); + RuntimeAbort(env, __LINE__, "capget failed"); + } + + return capdata[0].effective | + (static_cast<uint64_t>(capdata[1].effective) << 32); +} } // anonymous namespace namespace android { @@ -724,6 +744,10 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( capabilities |= (1LL << CAP_BLOCK_SUSPEND); } + // Containers run without some capabilities, so drop any caps that are not + // available. + capabilities &= GetEffectiveCapabilityMask(env); + return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags, rlimits, capabilities, capabilities, mount_external, se_info, se_name, false, fdsToClose, fdsToIgnore, instructionSet, appDataDir); @@ -750,6 +774,11 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer( ALOGE("System server process %d has died. Restarting Zygote!", pid); RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!"); } + + // Assign system_server to the correct memory cgroup. + if (!WriteStringToFile(StringPrintf("%d", pid), "/dev/memcg/system/tasks")) { + ALOGE("couldn't write %d to /dev/memcg/system/tasks", pid); + } } return pid; } diff --git a/core/proto/android/graphics/rect.proto b/core/proto/android/graphics/rect.proto new file mode 100644 index 000000000000..a65d33185e34 --- /dev/null +++ b/core/proto/android/graphics/rect.proto @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; + +package android.graphics; + +option java_multiple_files = true; + +message RectProto { + int32 left = 1; + int32 top = 2; + int32 right = 3; + int32 bottom = 4; +} + diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto index 76e683f51b4e..5dfcd2a63b18 100644 --- a/core/proto/android/os/incident.proto +++ b/core/proto/android/os/incident.proto @@ -20,6 +20,7 @@ option java_multiple_files = true; option java_outer_classname = "IncidentProtoMetadata"; import "frameworks/base/libs/incident/proto/android/privacy.proto"; +import "frameworks/base/libs/incident/proto/android/section.proto"; import "frameworks/base/core/proto/android/service/appwidget.proto"; import "frameworks/base/core/proto/android/service/battery.proto"; import "frameworks/base/core/proto/android/service/fingerprint.proto"; @@ -46,6 +47,9 @@ message IncidentHeaderProto { Cause cause = 1; } +// privacy field options must not be set at this level because all +// the sections are able to be controlled and configured by section ids. +// Instead privacy field options need to be configured in each section proto message. message IncidentProto { // Incident header repeated IncidentHeaderProto header = 1; @@ -54,12 +58,21 @@ message IncidentProto { //SystemProperties system_properties = 1000; // Linux services - Procrank procrank = 2000; + Procrank procrank = 2000 [ + (section).type = SECTION_COMMAND, + (section).args = "/system/xbin/procrank" + ]; //PageTypeInfo page_type_info = 2001; - KernelWakeSources kernel_wake_sources = 2002; + KernelWakeSources kernel_wake_sources = 2002 [ + (section).type = SECTION_FILE, + (section).args = "/d/wakeup_sources" + ]; // System Services - android.service.fingerprint.FingerprintServiceDumpProto fingerprint = 3000; + android.service.fingerprint.FingerprintServiceDumpProto fingerprint = 3000 [ + (section).type = SECTION_DUMPSYS, + (section).args = "fingerprint --proto --incident" + ]; android.service.NetworkStatsServiceDumpProto netstats = 3001; android.providers.settings.SettingsServiceDumpProto settings = 3002; android.service.appwidget.AppWidgetServiceDumpProto appwidget = 3003; diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto new file mode 100644 index 000000000000..ee8a6dc452b7 --- /dev/null +++ b/core/proto/android/server/windowmanagerservice.proto @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; + +import "frameworks/base/core/proto/android/graphics/rect.proto"; +import "frameworks/base/core/proto/android/view/displayinfo.proto"; +import "frameworks/base/core/proto/android/view/windowlayoutparams.proto"; + +package com.android.server.wm.proto; + +option java_multiple_files = true; + +message WindowManagerServiceProto { + WindowManagerPolicyProto policy = 1; + /* window manager hierarchy structure */ + repeated DisplayProto displays = 2; + /* window references in top down z order */ + repeated IdentifierProto windows = 3; + IdentifierProto focused_window = 4; + string focused_app = 5; + IdentifierProto input_method_window = 6; + bool display_frozen = 7; + int32 rotation = 8; + int32 last_orientation = 9; + AppTransitionProto app_transition = 10; +} + +/* represents PhoneWindowManager */ +message WindowManagerPolicyProto { + .android.graphics.RectProto stable_bounds = 1; +} + +/* represents AppTransition */ +message AppTransitionProto { + enum AppState { + APP_STATE_IDLE = 0; + APP_STATE_READY = 1; + APP_STATE_RUNNING = 2; + APP_STATE_TIMEOUT = 3; + } + AppState app_transition_state = 1; + /* definitions for constants found in {@link com.android.server.wm.AppTransition} */ + enum TransitionType { + TRANSIT_NONE = 0; + TRANSIT_UNSET = -1; + TRANSIT_ACTIVITY_OPEN = 6; + TRANSIT_ACTIVITY_CLOSE = 7; + TRANSIT_TASK_OPEN = 8; + TRANSIT_TASK_CLOSE = 9; + TRANSIT_TASK_TO_FRONT = 10; + TRANSIT_TASK_TO_BACK = 11; + TRANSIT_WALLPAPER_CLOSE = 12; + TRANSIT_WALLPAPER_OPEN = 13; + TRANSIT_WALLPAPER_INTRA_OPEN = 14; + TRANSIT_WALLPAPER_INTRA_CLOSE = 15; + TRANSIT_TASK_OPEN_BEHIND = 16; + TRANSIT_TASK_IN_PLACE = 17; + TRANSIT_ACTIVITY_RELAUNCH = 18; + TRANSIT_DOCK_TASK_FROM_RECENTS = 19; + TRANSIT_KEYGUARD_GOING_AWAY = 20; + TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER = 21; + TRANSIT_KEYGUARD_OCCLUDE = 22; + TRANSIT_KEYGUARD_UNOCCLUDE = 23; + } + TransitionType last_used_app_transition = 2; +} + +/* represents DisplayContent */ +message DisplayProto { + int32 id = 1; + repeated StackProto stacks = 2; + DockedStackDividerControllerProto docked_stack_divider_controller = 3; + PinnedStackControllerProto pinned_stack_controller = 4; + /* non app windows */ + repeated WindowTokenProto above_app_windows = 5; + repeated WindowTokenProto below_app_windows = 6; + repeated WindowTokenProto ime_windows = 7; + int32 dpi = 8; + .android.view.DisplayInfoProto display_info = 9; + int32 rotation = 10; + ScreenRotationAnimationProto screen_rotation_animation = 11; +} + + +/* represents DockedStackDividerController */ +message DockedStackDividerControllerProto { + bool minimized_dock = 1; +} + +/* represents PinnedStackController */ +message PinnedStackControllerProto { + .android.graphics.RectProto default_bounds = 1; + .android.graphics.RectProto movement_bounds = 2; +} + +/* represents TaskStack */ +message StackProto { + int32 id = 1; + repeated TaskProto tasks = 2; + bool fills_parent = 3; + .android.graphics.RectProto bounds = 4; + bool animation_background_surface_is_dimming = 5; +} + +/* represents Task */ +message TaskProto { + int32 id = 1; + repeated AppWindowTokenProto app_window_tokens = 2; + bool fills_parent = 3; + .android.graphics.RectProto bounds = 4; + .android.graphics.RectProto temp_inset_bounds = 5; +} + +/* represents AppWindowToken */ +message AppWindowTokenProto { + /* obtained from ActivityRecord */ + string name = 1; + WindowTokenProto window_token = 2; +} + +/* represents WindowToken */ +message WindowTokenProto { + int32 hash_code = 1; + repeated WindowStateProto windows = 2; +} + +/* represents WindowState */ +message WindowStateProto { + IdentifierProto identifier = 1; + int32 display_id = 2; + int32 stack_id = 3; + .android.view.WindowLayoutParamsProto attributes = 4; + .android.graphics.RectProto given_content_insets = 5; + .android.graphics.RectProto frame = 6; + .android.graphics.RectProto containing_frame = 7; + .android.graphics.RectProto parent_frame = 8; + .android.graphics.RectProto content_frame = 9; + .android.graphics.RectProto content_insets = 10; + .android.graphics.RectProto surface_insets = 11; + WindowStateAnimatorProto animator = 12; + bool animating_exit = 13; + repeated WindowStateProto child_windows = 14; +} + +message IdentifierProto { + int32 hash_code = 1; + int32 user_id = 2; + string title = 3; +} + +/* represents WindowStateAnimator */ +message WindowStateAnimatorProto { + .android.graphics.RectProto last_clip_rect = 1; + WindowSurfaceControllerProto surface = 2; +} + +/* represents WindowSurfaceController */ +message WindowSurfaceControllerProto { + bool shown = 1; + int32 layer = 2; +} + +/* represents ScreenRotationAnimation */ +message ScreenRotationAnimationProto { + bool started = 1; + bool animation_running = 2; +}
\ No newline at end of file diff --git a/core/proto/android/view/displayinfo.proto b/core/proto/android/view/displayinfo.proto new file mode 100644 index 000000000000..858386852f59 --- /dev/null +++ b/core/proto/android/view/displayinfo.proto @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; + +package android.view; + +option java_multiple_files = true; + +/* represents DisplayInfo */ +message DisplayInfoProto { + int32 logical_width = 1; + int32 logical_height = 2; + int32 app_width = 3; + int32 app_height = 4; +} diff --git a/core/proto/android/view/windowlayoutparams.proto b/core/proto/android/view/windowlayoutparams.proto new file mode 100644 index 000000000000..5bb84dceade8 --- /dev/null +++ b/core/proto/android/view/windowlayoutparams.proto @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; + +package android.view; + +option java_multiple_files = true; + +/* represents WindowManager.LayoutParams */ +message WindowLayoutParamsProto { + int32 type = 1; +} diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 400c9e8587c6..4f435af38c96 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -775,7 +775,7 @@ android:permissionGroup="android.permission-group.LOCATION" android:label="@string/permlab_accessFineLocation" android:description="@string/permdesc_accessFineLocation" - android:protectionLevel="dangerous|ephemeral" /> + android:protectionLevel="dangerous|instant" /> <!-- Allows an app to access approximate location. Alternatively, you might want {@link #ACCESS_FINE_LOCATION}. @@ -785,7 +785,7 @@ android:permissionGroup="android.permission-group.LOCATION" android:label="@string/permlab_accessCoarseLocation" android:description="@string/permdesc_accessCoarseLocation" - android:protectionLevel="dangerous|ephemeral" /> + android:protectionLevel="dangerous|instant" /> <!-- ====================================================================== --> <!-- Permissions for accessing the device telephony --> @@ -820,13 +820,13 @@ android:protectionLevel="dangerous" /> <!-- Allows read access to the device's phone number(s). This is a subset of the capabilities - granted by {@link #READ_PHONE_STATE} but is exposed to ephemeral applications. + granted by {@link #READ_PHONE_STATE} but is exposed to instant applications. <p>Protection level: dangerous--> <permission android:name="android.permission.READ_PHONE_NUMBERS" android:permissionGroup="android.permission-group.PHONE" android:label="@string/permlab_readPhoneNumbers" android:description="@string/permdesc_readPhoneNumbers" - android:protectionLevel="dangerous|ephemeral" /> + android:protectionLevel="dangerous|instant" /> <!-- Allows an application to initiate a phone call without going through the Dialer user interface for the user to confirm the call. @@ -1008,7 +1008,7 @@ android:permissionGroup="android.permission-group.CAMERA" android:label="@string/permlab_camera" android:description="@string/permdesc_camera" - android:protectionLevel="dangerous|ephemeral" /> + android:protectionLevel="dangerous|instant" /> <!-- ====================================================================== --> @@ -1251,7 +1251,7 @@ <permission android:name="android.permission.INTERNET" android:description="@string/permdesc_createNetworkSockets" android:label="@string/permlab_createNetworkSockets" - android:protectionLevel="normal|ephemeral" /> + android:protectionLevel="normal|instant" /> <!-- Allows applications to access information about networks. <p>Protection level: normal @@ -1259,7 +1259,7 @@ <permission android:name="android.permission.ACCESS_NETWORK_STATE" android:description="@string/permdesc_accessNetworkState" android:label="@string/permlab_accessNetworkState" - android:protectionLevel="normal|ephemeral" /> + android:protectionLevel="normal|instant" /> <!-- Allows applications to access information about Wi-Fi networks. <p>Protection level: normal @@ -1482,7 +1482,7 @@ <permission android:name="android.permission.VIBRATE" android:label="@string/permlab_vibrate" android:description="@string/permdesc_vibrate" - android:protectionLevel="normal|ephemeral" /> + android:protectionLevel="normal|instant" /> <!-- Allows using PowerManager WakeLocks to keep processor from sleeping or screen from dimming. @@ -1491,7 +1491,7 @@ <permission android:name="android.permission.WAKE_LOCK" android:label="@string/permlab_wakeLock" android:description="@string/permdesc_wakeLock" - android:protectionLevel="normal|ephemeral" /> + android:protectionLevel="normal|instant" /> <!-- Allows using the device's IR transmitter, if available. <p>Protection level: normal @@ -1993,6 +1993,15 @@ android:description="@string/permdesc_setWallpaperHints" android:protectionLevel="normal" /> + <!-- Allow the app to read the system wallpaper image without + holding the READ_EXTERNAL_STORAGE permission. + <p>Not for use by third-party applications. + @hide + @SystemApi + --> + <permission android:name="android.permission.READ_WALLPAPER_INTERNAL" + android:protectionLevel="signature|privileged" /> + <!-- ============================================ --> <!-- Permissions for changing the system clock --> <!-- ============================================ --> @@ -2390,7 +2399,8 @@ <permission android:name="android.permission.UPDATE_DEVICE_STATS" android:protectionLevel="signature|privileged" /> - <!-- @SystemApi @hide Allows an application to collect battery statistics --> + <!-- @SystemApi @hide Allows an application to collect application operation statistics. + Not for use by third party apps. --> <permission android:name="android.permission.GET_APP_OPS_STATS" android:protectionLevel="signature|privileged|development" /> @@ -2766,6 +2776,14 @@ <!-- @SystemApi Allows an application to install packages. <p>Not for use by third-party applications. --> <permission android:name="android.permission.INSTALL_PACKAGES" + android:protectionLevel="signature|privileged" /> + + <!-- @SystemApi Allows an application to install self updates. This is a limited version + of {@link android.Manifest.permission#INSTALL_PACKAGES}. + <p>Not for use by third-party applications. + @hide + --> + <permission android:name="android.permission.INSTALL_SELF_UPDATES" android:protectionLevel="signature|privileged" /> <!-- @SystemApi Allows an application to clear user data. @@ -3512,6 +3530,11 @@ <permission android:name="android.permission.ACCESS_VR_MANAGER" android:protectionLevel="signature" /> + <!-- Required to access VR-Mode state and state change events via {android.app.VrStateCallback} + @hide --> + <permission android:name="android.permission.ACCESS_VR_STATE" + android:protectionLevel="signature|preinstalled" /> + <!-- Allows an application to whitelist tasks during lock task mode @hide <p>Not for use by third-party applications.</p> --> <permission android:name="android.permission.UPDATE_LOCK_TASK_PACKAGES" @@ -3541,7 +3564,7 @@ <!-- Allows an instant app to create foreground services. --> <permission android:name="android.permission.INSTANT_APP_FOREGROUND_SERVICE" - android:protectionLevel="signature|development|ephemeral|appop" /> + android:protectionLevel="signature|development|instant|appop" /> <application android:process="system" android:persistent="true" diff --git a/core/res/res/drawable/ic_corp_icon.xml b/core/res/res/drawable/ic_corp_icon.xml index a6b68f17409d..48531dd8c539 100644 --- a/core/res/res/drawable/ic_corp_icon.xml +++ b/core/res/res/drawable/ic_corp_icon.xml @@ -1,12 +1,9 @@ <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="48dp" android:height="48dp" - android:viewportWidth="48.0" - android:viewportHeight="48.0"> + android:viewportWidth="24.0" + android:viewportHeight="24.0"> <path - android:pathData="M24,24m-24,0a24,24 0,1 1,48 0a24,24 0,1 1,-48 0" - android:fillColor="#FF6D00"/> - <path - android:pathData="M35.2,15.6h-5.6v-2.8c0,-1.55 -1.25,-2.8 -2.8,-2.8h-5.6c-1.55,0 -2.8,1.25 -2.8,2.8v2.8h-5.6c-1.55,0 -2.79,1.25 -2.79,2.8L10,33.8c0,1.55 1.25,2.8 2.8,2.8h22.4c1.55,0 2.8,-1.25 2.8,-2.8V18.4C38,16.85 36.75,15.6 35.2,15.6zM24,28.2c-1.54,0 -2.8,-1.26 -2.8,-2.8s1.26,-2.8 2.8,-2.8c1.54,0 2.8,1.26 2.8,2.8S25.54,28.2 24,28.2zM26.8,15.6h-5.6v-2.8h5.6V15.6z" - android:fillColor="#FFFFFF"/> + android:pathData="M20,6h-4L16,4c0,-1.11 -0.89,-2 -2,-2h-4c-1.11,0 -2,0.89 -2,2v2L4,6c-1.11,0 -1.99,0.89 -1.99,2L2,19c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2L22,8c0,-1.11 -0.89,-2 -2,-2zM12,15c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM14,6h-4L10,4h4v2z" + android:fillColor="#000000"/> </vector>
\ No newline at end of file diff --git a/core/res/res/layout/autofill_save.xml b/core/res/res/layout/autofill_save.xml index 77fa62a5ecc9..50ff50f19564 100644 --- a/core/res/res/layout/autofill_save.xml +++ b/core/res/res/layout/autofill_save.xml @@ -14,94 +14,91 @@ limitations under the License. --> +<!-- NOTE: outer layout is required to provide proper shadow. --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/autofill_save" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:layout_marginTop="32dp" - android:paddingTop="16dp" - android:elevation="32dp" - android:background="?android:attr/colorBackground" android:orientation="vertical"> <LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/autofill_save" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:paddingLeft="16dp" - android:paddingRight="16dp" + android:layout_marginTop="32dp" + android:paddingTop="16dp" + android:elevation="32dp" + android:background="?android:attr/colorBackground" android:orientation="vertical"> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" - android:orientation="horizontal"> + android:paddingLeft="16dp" + android:paddingRight="16dp" + android:orientation="vertical"> - <TextView - android:id="@+id/autofill_save_title" - android:layout_width="0dp" + <LinearLayout + android:layout_width="fill_parent" android:layout_height="wrap_content" - android:text="@string/autofill_save_title" - android:textSize="16sp" - android:textColor="?android:attr/textColorPrimary" - android:layout_weight="1"> - </TextView> - - <ImageView - android:id="@+id/autofill_save_close" - android:layout_width="wrap_content" + android:orientation="horizontal"> + + <TextView + android:id="@+id/autofill_save_title" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:text="@string/autofill_save_title" + android:textSize="16sp" + android:textColor="?android:attr/textColorPrimary" + android:layout_weight="1"> + </TextView> + + </LinearLayout> + + <com.android.server.autofill.ui.CustomScrollView + android:id="@+id/autofill_save_custom_subtitle" + android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginLeft="16dp" - android:src="@android:drawable/ic_close" - android:alpha="0.54" - android:background="?android:attr/selectableItemBackgroundBorderless" - android:contentDescription="@android:string/close_button_text"> - </ImageView> + android:layout_marginTop="4dp" + android:visibility="gone"/> </LinearLayout> - <com.android.server.autofill.ui.CustomScrollView - android:id="@+id/autofill_save_custom_subtitle" - android:layout_width="match_parent" + <com.android.internal.widget.ButtonBarLayout + android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="4dp" - android:visibility="gone"/> + android:layout_gravity="end" + android:padding="16dp" + android:clipToPadding="false" + android:layout_weight="1" + android:orientation="horizontal"> - </LinearLayout> + <Space + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_weight="1" + android:visibility="invisible"> + </Space> - <com.android.internal.widget.ButtonBarLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="end" - android:padding="16dp" - android:clipToPadding="false" - android:layout_weight="1" - android:orientation="horizontal"> - - <Space - android:layout_width="0dp" - android:layout_height="0dp" - android:layout_weight="1" - android:visibility="invisible"> - </Space> + <Button + android:id="@+id/autofill_save_no" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + style="?android:attr/buttonBarButtonStyle" + android:text="@string/autofill_save_no"> + </Button> - <Button - android:id="@+id/autofill_save_no" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - style="?android:attr/buttonBarButtonStyle" - android:text="@string/autofill_save_no"> - </Button> + <Button + android:id="@+id/autofill_save_yes" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + style="@style/Widget.Material.Button.Colored" + android:text="@string/autofill_save_yes"> + </Button> - <Button - android:id="@+id/autofill_save_yes" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - style="@style/Widget.Material.Button.Colored" - android:text="@string/autofill_save_yes"> - <requestFocus /> - </Button> + </com.android.internal.widget.ButtonBarLayout> - </com.android.internal.widget.ButtonBarLayout> + </LinearLayout> </LinearLayout> diff --git a/core/res/res/layout/notification_template_material_big_picture.xml b/core/res/res/layout/notification_template_material_big_picture.xml index 83c0fec004b6..e94e646fa581 100644 --- a/core/res/res/layout/notification_template_material_big_picture.xml +++ b/core/res/res/layout/notification_template_material_big_picture.xml @@ -40,7 +40,10 @@ android:layout_marginEnd="@dimen/notification_content_margin_end" android:orientation="vertical"> <include layout="@layout/notification_template_part_line1"/> - <include layout="@layout/notification_template_progress"/> + <include layout="@layout/notification_template_progress" + android:layout_width="match_parent" + android:layout_height="@dimen/notification_progress_bar_height" + android:layout_marginTop="@dimen/notification_progress_margin_top"/> <include layout="@layout/notification_template_text"/> </LinearLayout> <ImageView diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml index 0cfe6898f111..3c87f92639bb 100644 --- a/core/res/res/layout/notification_template_material_big_text.xml +++ b/core/res/res/layout/notification_template_material_big_text.xml @@ -45,7 +45,11 @@ android:orientation="vertical" > <include layout="@layout/notification_template_part_line1" /> - <include layout="@layout/notification_template_progress" /> + <include layout="@layout/notification_template_progress" + android:layout_width="match_parent" + android:layout_height="@dimen/notification_progress_bar_height" + android:layout_marginTop="@dimen/notification_progress_margin_top" + android:layout_marginBottom="6dp"/> <com.android.internal.widget.ImageFloatingTextView android:id="@+id/big_text" android:layout_width="match_parent" android:layout_height="wrap_content" diff --git a/core/res/res/layout/notification_template_material_inbox.xml b/core/res/res/layout/notification_template_material_inbox.xml index 7820e39e777c..e4c91a458220 100644 --- a/core/res/res/layout/notification_template_material_inbox.xml +++ b/core/res/res/layout/notification_template_material_inbox.xml @@ -48,8 +48,9 @@ android:layout_height="wrap_content" /> <include layout="@layout/notification_template_progress" android:layout_width="match_parent" - android:layout_height="15dp" - android:layout_marginTop="4dp"/> + android:layout_height="@dimen/notification_progress_bar_height" + android:layout_marginTop="@dimen/notification_progress_margin_top" + android:layout_marginBottom="2dp"/> <TextView android:id="@+id/inbox_text0" android:textAppearance="@style/TextAppearance.Material.Notification" android:layout_width="match_parent" diff --git a/core/res/res/layout/popup_menu_item_layout.xml b/core/res/res/layout/popup_menu_item_layout.xml index 8b8c93afffbd..3eecb36f0ea6 100644 --- a/core/res/res/layout/popup_menu_item_layout.xml +++ b/core/res/res/layout/popup_menu_item_layout.xml @@ -16,56 +16,72 @@ <com.android.internal.view.menu.ListMenuItemView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="?attr/dropdownListPreferredItemHeight" + android:layout_height="wrap_content" android:minWidth="196dip" - android:paddingEnd="16dip"> - + android:orientation="vertical" > + + <ImageView + android:id="@+id/group_divider" + android:layout_width="match_parent" + android:layout_height="1dip" + android:layout_marginTop="4dip" + android:layout_marginBottom="4dip" + android:background="@drawable/list_divider_material" /> + <!-- Icon will be inserted here. --> - - <!-- The title and summary have some gap between them, and this 'group' should be centered vertically. --> - <RelativeLayout - android:layout_width="0dip" - android:layout_weight="1" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:layout_marginStart="16dip" - android:duplicateParentState="true"> - - <TextView - android:id="@+id/title" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_alignParentTop="true" - android:layout_alignParentStart="true" - android:textAppearance="?attr/textAppearanceLargePopupMenu" - android:singleLine="true" - android:duplicateParentState="true" - android:ellipsize="marquee" - android:fadingEdge="horizontal" - android:textAlignment="viewStart" /> - <TextView - android:id="@+id/shortcut" - android:layout_width="wrap_content" + <!-- The title and summary have some gap between them, + and this 'group' should be centered vertically. --> + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="?attr/dropdownListPreferredItemHeight" + android:paddingEnd="16dip" + android:duplicateParentState="true" > + + <LinearLayout + android:layout_width="0dip" + android:layout_weight="1" android:layout_height="wrap_content" - android:layout_below="@id/title" - android:layout_alignParentStart="true" - android:textAppearance="?attr/textAppearanceSmallPopupMenu" - android:singleLine="true" - android:duplicateParentState="true" - android:textAlignment="viewStart" /> + android:layout_gravity="center_vertical" + android:layout_marginStart="16dip" + android:duplicateParentState="true"> - </RelativeLayout> + <TextView + android:id="@+id/title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_alignParentTop="true" + android:layout_alignParentStart="true" + android:textAppearance="?attr/textAppearanceLargePopupMenu" + android:singleLine="true" + android:duplicateParentState="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + android:textAlignment="viewStart" /> - <ImageView - android:id="@+id/submenuarrow" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:layout_marginStart="8dp" - android:scaleType="center" - android:visibility="gone" /> + <TextView + android:id="@+id/shortcut" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@id/title" + android:layout_alignParentStart="true" + android:textAppearance="?attr/textAppearanceSmallPopupMenu" + android:singleLine="true" + android:duplicateParentState="true" + android:textAlignment="viewStart" /> + + </LinearLayout> + + <ImageView + android:id="@+id/submenuarrow" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginStart="8dp" + android:scaleType="center" + android:visibility="gone" /> + </LinearLayout> <!-- Checkbox, and/or radio button will be inserted here. --> - + </com.android.internal.view.menu.ListMenuItemView> diff --git a/core/res/res/layout/time_picker_text_input_material.xml b/core/res/res/layout/time_picker_text_input_material.xml index 2bef027583bc..4988842cb99c 100644 --- a/core/res/res/layout/time_picker_text_input_material.xml +++ b/core/res/res/layout/time_picker_text_input_material.xml @@ -80,6 +80,7 @@ android:layout_height="wrap_content" android:layout_below="@id/input_hour" android:layout_alignStart="@id/input_hour" + android:accessibilityLiveRegion="assertive" android:textColor="?attr/colorError" android:text="@string/time_picker_input_error" /> </RelativeLayout> diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index a1ce62e8f708..a6dcc1958fd0 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Opletberigte"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Kleinhandeldemonstrasie"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB-verbinding"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Programme wat op die agtergrond loop"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> loop tans op die agtergrond"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> programme loop tans op die agtergrond"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Programme wat batterykrag gebruik"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> gebruik tans batterykrag"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> programme gebruik tans batterykrag"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Tik vir besonderhede oor battery- en datagebruik"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Veiligmodus"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Gekoppel aan <xliff:g id="SESSION">%s</xliff:g>. Tik om die netwerk te bestuur."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Altydaan-VPN koppel tans..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Altydaan-VPN gekoppel"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Altydaan-VPN is ontkoppel"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Ontkoppel van altyd-aan-VPN"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Altydaan-VPN-fout"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tik om op te stel"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Verander netwerk- of VPN-instellings"</string> <string name="upload_file" msgid="2897957172366730416">"Kies lêer"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Geen lêer gekies nie"</string> <string name="reset" msgid="2448168080964209908">"Stel terug"</string> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index 0143b3a76619..56191b530d99 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"ማንቂያዎች"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"የችርቻሮ ማሳያ"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"የዩኤስቢ ግንኙነት"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"በጀርባ ውስጥ የሚያሄዱ መተግበሪያዎች"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> በጀርባ ውስጥ እያሄደ ነው"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> መተግበሪያዎች በጀርባ ውስጥ እያሄዱ ነው"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"ባትሪ በመፍጀት ላይ ያሉ መተግበሪያዎች"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> ባትሪ እየተጠቀመ ነው"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> መተግበሪያዎች ባትሪ እየተጠቀሙ ነው"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"በባትሪ እና ውሂብ አጠቃቀም ላይ ዝርዝሮችን ለማግኘት መታ ያድርጉ"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>፣ <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"የሚያስተማምን ሁነታ"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"ለ<xliff:g id="SESSION">%s</xliff:g> የተገናኘ። አውታረመረቡን ለማደራጀት ሁለቴ ንካ።"</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"ሁልጊዜ የበራ VPN በመገናኘት ላይ…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"ሁልጊዜ የበራ VPN ተገናኝቷል"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"ሁልጊዜ የበራ የVPN ግንኙነት ተቋርጧል"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"ሁልጊዜ ከበራ ቪፒኤን ጋር ግንኙነት ተቋርጧል"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"ሁልጊዜ የበራ VPN ስህተት"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"ለማዋቀር መታ ያድርጉ"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"የአውታረ መረብ ወይም የቪፒኤን ቅንብሮችን ይቀይሩ"</string> <string name="upload_file" msgid="2897957172366730416">"ፋይል ምረጥ"</string> <string name="no_file_chosen" msgid="6363648562170759465">"ምንም ፋይል አልተመረጠም"</string> <string name="reset" msgid="2448168080964209908">"ዳግም አስጀምር"</string> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index 92446f3249b2..0d63fbee456b 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -141,7 +141,7 @@ <string name="cfTemplateRegisteredTime" msgid="6781621964320635172">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: لم تتم إعادة التوجيه"</string> <string name="fcComplete" msgid="3118848230966886575">"اكتمل كود الميزة."</string> <string name="fcError" msgid="3327560126588500777">"حدثت مشكلة بالاتصال أو أن كود الميزة غير صحيح."</string> - <string name="httpErrorOk" msgid="1191919378083472204">"موافق"</string> + <string name="httpErrorOk" msgid="1191919378083472204">"حسنًا"</string> <string name="httpError" msgid="7956392511146698522">"حدث خطأ في الشبكة."</string> <string name="httpErrorLookup" msgid="4711687456111963163">"تعذر العثور على عنوان URL."</string> <string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"نظام مصادقة الموقع غير معتمد."</string> @@ -260,9 +260,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"التنبيهات"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"عرض توضيحي لبائع التجزئة"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"اتصال USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"التطبيقات التي تعمل في الخلفية"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"جارٍ تشغيل <xliff:g id="APP_NAME">%1$s</xliff:g> في الخلفية"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"جارٍ تشغيل <xliff:g id="NUMBER">%1$d</xliff:g> تطبيق في الخلفية"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"التطبيقات التي تستهلك البطارية"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"يستخدم تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> البطارية"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"تستخدم <xliff:g id="NUMBER">%1$d</xliff:g> من التطبيقات البطارية"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"انقر للحصول على تفاصيل حول البطارية واستخدام البيانات"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>، <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"الوضع الآمن"</string> @@ -1030,7 +1030,7 @@ <string name="VideoView_error_title" msgid="3534509135438353077">"مشكلة في الفيديو"</string> <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"عذرًا، هذا الفيديو غير صالح للبث على هذا الجهاز."</string> <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"لا يمكنك تشغيل هذا الفيديو."</string> - <string name="VideoView_error_button" msgid="2822238215100679592">"موافق"</string> + <string name="VideoView_error_button" msgid="2822238215100679592">"حسنًا"</string> <string name="relative_time" msgid="1818557177829411417">"<xliff:g id="DATE">%1$s</xliff:g>، <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="noon" msgid="7245353528818587908">"الظهر"</string> <string name="Noon" msgid="3342127745230013127">"الظهر"</string> @@ -1065,9 +1065,9 @@ <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"ليست هناك سعة تخزينية كافية للنظام. تأكد من أنه لديك مساحة خالية تبلغ ٢٥٠ ميغابايت وأعد التشغيل."</string> <string name="app_running_notification_title" msgid="8718335121060787914">"<xliff:g id="APP_NAME">%1$s</xliff:g> قيد التشغيل"</string> <string name="app_running_notification_text" msgid="1197581823314971177">"انقر للحصول على مزيد من المعلومات أو لإيقاف التطبيق."</string> - <string name="ok" msgid="5970060430562524910">"موافق"</string> + <string name="ok" msgid="5970060430562524910">"حسنًا"</string> <string name="cancel" msgid="6442560571259935130">"إلغاء"</string> - <string name="yes" msgid="5362982303337969312">"موافق"</string> + <string name="yes" msgid="5362982303337969312">"حسنًا"</string> <string name="no" msgid="5141531044935541497">"إلغاء"</string> <string name="dialog_alert_title" msgid="2049658708609043103">"تنبيه"</string> <string name="loading" msgid="7933681260296021180">"جارٍ التحميل…"</string> @@ -1267,7 +1267,7 @@ <string name="perms_description_app" msgid="5139836143293299417">"يقدمه <xliff:g id="APP_NAME">%1$s</xliff:g>."</string> <string name="no_permissions" msgid="7283357728219338112">"لا أذونات مطلوبة"</string> <string name="perm_costs_money" msgid="4902470324142151116">"قد يكلفك هذا مالاً."</string> - <string name="dlg_ok" msgid="7376953167039865701">"موافق"</string> + <string name="dlg_ok" msgid="7376953167039865701">"حسنًا"</string> <string name="usb_charging_notification_title" msgid="6895185153353640787">"يتم استخدام الاتصال عبر USB لشحن هذا الجهاز"</string> <string name="usb_supplying_notification_title" msgid="5310642257296510271">"يتم استخدام الاتصال عبر USB لإمداد الجهاز المتصل بالطاقة"</string> <string name="usb_mtp_notification_title" msgid="8396264943589760855">"USB لنقل الملفات"</string> @@ -1382,9 +1382,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"تم الاتصال بـ <xliff:g id="SESSION">%s</xliff:g>. انقر لإدارة الشبكة."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"جارٍ الاتصال بشبكة افتراضية خاصة (VPN) دائمة التشغيل..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"تم الاتصال بشبكة افتراضية خاصة (VPN) دائمة التشغيل"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"تم فصل الشبكة الافتراضية الخاصة (VPN) دائمة التشغيل"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"تم قطع الاتصال بالشبكة الافتراضية الخاصة (VPN) التي يتم تشغيلها دائمًا"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"خطأ بشبكة افتراضية خاصة (VPN) دائمة التشغيل"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"انقر للإعداد."</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"تغيير إعدادات الشبكة أو الشبكة الافتراضية الخاصة (VPN)"</string> <string name="upload_file" msgid="2897957172366730416">"اختيار ملف"</string> <string name="no_file_chosen" msgid="6363648562170759465">"لم يتم اختيار أي ملف"</string> <string name="reset" msgid="2448168080964209908">"إعادة تعيين"</string> diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml index beae9de97982..a14bf5a38f63 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Siqnallar"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Pərakəndə demo"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB əlaqə"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Arxa fonda işləyən tətbiqlər"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> arxa fonda işləyir"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> tətbiq arxa fonda işləyir"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Batareyadan istifadə edən tətbiqlər"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> batareyadan istifadə edir"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> tətbiq batareyadan istifadə edir"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Batareya və data istifadəsi haqqında ətraflı məlumat üçün klikləyin"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Təhlükəsiz rejim"</string> @@ -261,7 +261,7 @@ <string name="permgroupdesc_contacts" msgid="6951499528303668046">"kontaktlarınıza daxil olun"</string> <string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> tətbiqinə kontaktlara daxil olmaq icazəsi verin"</string> <string name="permgrouplab_location" msgid="7275582855722310164">"Yer"</string> - <string name="permgroupdesc_location" msgid="1346617465127855033">"bu cihazın məkanını əldə edin"</string> + <string name="permgroupdesc_location" msgid="1346617465127855033">"cihazın yerini bilmək"</string> <string name="permgrouprequest_location" msgid="8903573681261610809">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> tətbiqinə bu cihazın məkanına daxil olmaq icazəsi verin"</string> <string name="permgrouplab_calendar" msgid="5863508437783683902">"Təqvim"</string> <string name="permgroupdesc_calendar" msgid="3889615280211184106">"təqvimə daxil olun"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> sessiyaya qoşulun. Şəbəkəni idarə etmək üçün tıklayın."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Həmişə aktiv VPN bağlanır..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN bağlantısı həmişə aktiv"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Həmişə aktiv VPN bağlantısı kəsildi"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Həmişə aktiv VPN bağlantısı kəsildi"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Həmişə aktiv VPN xətası"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Quraşdırmaq üçün tıklayın"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Şəbəkə və ya VPN ayarlarını dəyişin"</string> <string name="upload_file" msgid="2897957172366730416">"Fayl seçin"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Heç bir fayl seçilməyib"</string> <string name="reset" msgid="2448168080964209908">"Sıfırlayın"</string> diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml index 8bf9aa14e3c6..c9b2096176db 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -251,9 +251,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Obaveštenja"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Režim demonstracije za maloprodajne objekte"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB veza"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Aplikacije pokrenute u pozadini"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> radi u pozadini"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"Aplikacije (<xliff:g id="NUMBER">%1$d</xliff:g>) su pokrenute u pozadini"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Aplikacije koje troše bateriju"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> koristi bateriju"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"Aplikacije (<xliff:g id="NUMBER">%1$d</xliff:g>) koriste bateriju"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Dodirnite za detalje o bateriji i potrošnji podataka"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Bezbedni režim"</string> @@ -1316,9 +1316,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Povezano sa sesijom <xliff:g id="SESSION">%s</xliff:g>. Dodirnite da biste upravljali mrežom."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Povezivanje stalno uključenog VPN-a..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Stalno uključeni VPN je povezan"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Veza sa stalno uključenim VPN-om je prekinuta"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Veza sa uvek uključenim VPN-om je prekinuta"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Greška stalno uključenog VPN-a"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Dodirnite da biste podesili"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Promenite podešavanja VPN-a"</string> <string name="upload_file" msgid="2897957172366730416">"Odaberi datoteku"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Nije izabrana nijedna datoteka"</string> <string name="reset" msgid="2448168080964209908">"Resetuj"</string> diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index fe89e5fb7084..78e0cece2afb 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -254,9 +254,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Абвесткi"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Дэманстрацыйны рэжым для пунктаў продажу"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Падключэнне USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Праграмы, якія працуюць у фонавым рэжыме"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> працуе ў фонавым рэжыме"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"Праграмы (<xliff:g id="NUMBER">%1$d</xliff:g>) працуюць у фонавым рэжыме"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Праграмы, якія выкарыстоўваюць акумулятар"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> выкарыстоўвае акумулятар"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"Наступная колькасць праграм выкарыстоўваюць акумулятар: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Дакраніцеся, каб даведацца пра выкарыстанне трафіка і акумулятара"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Бяспечны рэжым"</string> @@ -268,7 +268,7 @@ <string name="permgrouprequest_contacts" msgid="1601591667800538208">"Дазволіць <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> атрымліваць доступ да вашых кантактаў"</string> <string name="permgrouplab_location" msgid="7275582855722310164">"Месцазнаходжанне"</string> <string name="permgroupdesc_location" msgid="1346617465127855033">"атрымліваць доступ да месцазнаходжання гэтай прылады"</string> - <string name="permgrouprequest_location" msgid="8903573681261610809">"Дазволіць <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> атрымліваць доступ да звестак аб месцазнаходжанні гэтай прылады"</string> + <string name="permgrouprequest_location" msgid="8903573681261610809">"Дазволіць праграме <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> атрымліваць доступ да звестак аб месцазнаходжанні гэтай прылады"</string> <string name="permgrouplab_calendar" msgid="5863508437783683902">"Каляндар"</string> <string name="permgroupdesc_calendar" msgid="3889615280211184106">"атрымліваць доступ да вашага календара"</string> <string name="permgrouprequest_calendar" msgid="6704529828699071445">"Дазволіць <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> атрымліваць доступ да вашага календара"</string> @@ -1338,9 +1338,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Падлучаны да <xliff:g id="SESSION">%s</xliff:g>. Націсніце, каб кiраваць сеткай."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Падключэнне заўсёды ўключанага VPN..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Заўсёды ўключаны i падключаны VPN"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Заўсёды ўключаны VPN адключаны"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Адключана ад заўсёды ўключанай VPN"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Памылка заўсёды ўключанага VPN"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Дакраніцеся, каб наладзіць"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Змяніць налады сеткі ці VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Выберыце файл"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Файл не выбраны"</string> <string name="reset" msgid="2448168080964209908">"Скінуць"</string> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index 9992c44e7d7d..cd7fe1a7358a 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Сигнали"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Демонстрационен режим за магазини"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB връзка"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Приложения, работещи на заден план"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> се изпълнява на заден план"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> приложения работят на заден план"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Приложения, използващи батерията"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> използва батерията"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> приложения използват батерията"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Докоснете за информация относно използването на батерията и преноса на данни"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Безопасен режим"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Свързана с/ъс <xliff:g id="SESSION">%s</xliff:g>. Докоснете, за да управлявате мрежата."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Установява се връзка с винаги включената виртуална частна мрежа (VPN)…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Установена е връзка с винаги включената виртуална частна мрежа (VPN)"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Няма връзка с винаги включената виртуална частна мрежа (VPN)"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Връзката с винаги включената VPN е прекратена"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Грешка във винаги включената виртуална частна мрежа (VPN)"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Докоснете, за да настроите"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Промяна на настройките за мрежата или VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Избор на файл"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Няма избран файл"</string> <string name="reset" msgid="2448168080964209908">"Повторно задаване"</string> diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index c0ef6ded81cb..4b7d20f425c7 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -29,7 +29,7 @@ <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"ভয়েসমেল"</string> <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string> <string name="mmiError" msgid="5154499457739052907">"সংযোগ সমস্যা বা অবৈধ MMI কোড৷"</string> - <string name="mmiFdnError" msgid="5224398216385316471">"নির্দিষ্ট নম্বরে ডায়ালযোগ্য হিসাবে প্রক্রিয়াটি সীমিত করা হয়েছে৷"</string> + <string name="mmiFdnError" msgid="5224398216385316471">"নির্দিষ্ট নম্বরে ডায়ালযোগ্য হিসেবে প্রক্রিয়াটি সীমিত করা হয়েছে৷"</string> <string name="mmiErrorWhileRoaming" msgid="762488890299284230">"আপনি রোমিংয়ে থাকাকালীন আপনার ফোন থেকে \'কল ফরওয়ার্ড করার সেটিংস\' পরিবর্তন করা যাবে না৷"</string> <string name="serviceEnabled" msgid="8147278346414714315">"পরিষেবা সক্ষম করা ছিল৷"</string> <string name="serviceEnabledFor" msgid="6856228140453471041">"এর জন্য পরিষেবার সক্ষম করা ছিল:"</string> @@ -140,8 +140,8 @@ <string name="httpErrorOk" msgid="1191919378083472204">"ঠিক আছে"</string> <string name="httpError" msgid="7956392511146698522">"একটি নেটওয়ার্ক ত্রুটি ঘটেছে৷"</string> <string name="httpErrorLookup" msgid="4711687456111963163">"URL খুঁজে পাওয়া যায়নি৷"</string> - <string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"এই সাইট প্রমাণীকরণ স্কীমটি সমর্থিত নয়৷"</string> - <string name="httpErrorAuth" msgid="1435065629438044534">"প্রমাণীকরণ করা যায়নি৷"</string> + <string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"এই সাইট যাচাইকরণ স্কীমটি সমর্থিত নয়৷"</string> + <string name="httpErrorAuth" msgid="1435065629438044534">"যাচাইকরণ করা যায়নি৷"</string> <string name="httpErrorProxyAuth" msgid="1788207010559081331">"প্রক্সী সার্ভারের মাধ্যমে প্রমাণীকরণ ব্যর্থ হয়েছে৷"</string> <string name="httpErrorConnect" msgid="8714273236364640549">"সার্ভারের সাথে সংযোগ স্থাপন করা যায়নি৷"</string> <string name="httpErrorIO" msgid="2340558197489302188">"সার্ভারের সাথে যোগাযোগ করা যায়নি৷ পরে আবার চেষ্টা করুন৷"</string> @@ -175,7 +175,7 @@ <string name="network_logging_notification_title" msgid="6399790108123704477">"ডিভাইসটি পরিচালনা করা হচ্ছে"</string> <string name="network_logging_notification_text" msgid="7930089249949354026">"আপনার প্রতিষ্ঠান এই ডিভাইসটি পরিচালনা করে এবং এটির নেটওয়ার্ক ট্রাফিকের উপরে নজর রাখতে পারে। বিশদ বিবরণের জন্য ট্যাপ করুন।,"</string> <string name="factory_reset_warning" msgid="5423253125642394387">"আপনার ডিভাইসটি মুছে ফেলা হবে"</string> - <string name="factory_reset_message" msgid="7972496262232832457">"প্রশাসক অ্যাপটি ব্যবহার করা যাবে না। আপনার ডিভাইসে থাকা সবকিছু এখন মুছে ফেলা হবে।\n\nকোনো প্রশ্ন থাকলে আপনার প্রতিষ্ঠানের প্রশাসকের সাথে যোগাযোগ করুন।"</string> + <string name="factory_reset_message" msgid="7972496262232832457">"প্রশাসক অ্যাপটি ব্যবহার করা যাবে না। আপনার ডিভাইসে থাকা সবকিছু এখন মুছে ফেলা হবে।\n\nকোনও প্রশ্ন থাকলে আপনার প্রতিষ্ঠানের প্রশাসকের সাথে যোগাযোগ করুন।"</string> <string name="me" msgid="6545696007631404292">"আমাকে"</string> <string name="power_dialog" product="tablet" msgid="8545351420865202853">"ট্যাবলেট বিকল্পগুলি"</string> <string name="power_dialog" product="tv" msgid="6153888706430556356">"টিভি বিকল্পগুলি"</string> @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"সতর্কতাগুলি"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"খুচরা বিক্রয়ের ডেমো"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB সংযোগ"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"পটভূমিতে অ্যাপ চালু আছে"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"পটভূমিতে <xliff:g id="APP_NAME">%1$s</xliff:g> অ্যাপ চালু আছে"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"পটভূমিতে <xliff:g id="NUMBER">%1$d</xliff:g>টি অ্যাপ চালু আছে"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"কিছু অ্যাপ ব্যাটারি ব্যবহার করছে"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> অ্যাপটি ব্যাটারি ব্যবহার করছে"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g>টি অ্যাপ ব্যাটারি ব্যবহার করছে"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"ব্যাটারি এবং ডেটার ব্যবহারের বিশদ বিবরণের জন্য ট্যাপ করুন"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"নিরাপদ মোড"</string> @@ -307,24 +307,24 @@ <string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"শর্টকাটগুলি আনইনস্টল করে"</string> <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"অ্যাপ্লিকেশানটিকে ব্যবহারকারীর হস্তক্ষেপ ছাড়াই হোমস্ক্রীণের শর্টকাটগুলি সরানোর অনুমতি দেয়৷"</string> <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"আউটগোয়িং কলগুলি পুনঃচালিত করুন"</string> - <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"অ্যাপ্লিকেশানকে কল চলাকালীন অন্য একটি নম্বরে কল পুনঃনির্দেশ বা কলটি একসথে বন্ধ করার সাথে ডায়াল করা নম্বরটি দেখতে দেয়৷"</string> + <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"অ্যাপ্লিকেশনকে কল চলাকালীন অন্য একটি নম্বরে কল পুনঃনির্দেশ বা কলটি একসথে বন্ধ করার সাথে ডায়াল করা নম্বরটি দেখতে দেয়৷"</string> <string name="permlab_answerPhoneCalls" msgid="4077162841226223337">"ফোন কলের উত্তর দিতে দিন"</string> <string name="permdesc_answerPhoneCalls" msgid="2901889867993572266">"অ্যাপটিকে ইনকামিং ফোন কলের উত্তর দিতে দেয়।"</string> - <string name="permlab_receiveSms" msgid="8673471768947895082">"পাঠ্য বার্তা পান (SMS)"</string> + <string name="permlab_receiveSms" msgid="8673471768947895082">"টেক্সট মেসেজ পান (SMS)"</string> <string name="permdesc_receiveSms" msgid="6424387754228766939">"অ্যাপ্লিকেশানটিকে এসএমএস প্রাপ্ত করার এবং প্রক্রিয়া করার অনুমতি দেয়৷ এর মানে হল অ্যাপ্লিকেশানটি আপনার ডিভাইস থেকে পাঠানো বার্তাগুলিকে পর্যবেক্ষণ করতে পারে এবং মুছতে পারে সেগুলিকে আপনাকে না দেখিয়ে৷"</string> - <string name="permlab_receiveMms" msgid="1821317344668257098">"পাঠ্য বার্তা পান (MMS)"</string> + <string name="permlab_receiveMms" msgid="1821317344668257098">"টেক্সট মেসেজ পান (MMS)"</string> <string name="permdesc_receiveMms" msgid="533019437263212260">"অ্যাপ্লিকেশানটিকে MMS বার্তা প্রাপ্ত করার এবং প্রক্রিয়া করার অনুমতি দেয়৷ এর মানে হল অ্যাপ্লিকেশানটি আপনার ডিভাইস থেকে পাঠানো বার্তাগুলিকে পর্যবেক্ষণ করতে পারে এবং মুছতে পারে সেগুলিকে আপনাকে না দেখিয়ে৷"</string> <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"সেল সম্প্রচার বার্তা পড়ুন"</string> <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"আপনার ডিভাইস দ্বারা প্রাপ্ত সেল সম্প্রচার পড়তে অ্যাপ্লিকেশানটিকে অনুমতি দেয়৷ কয়েকটি স্থানে আপনাকে জরুরি অবস্থার জন্য সতর্ক করতে জরুরি সতর্কতাগুলি বিতরণ করা হয়৷ যখন একটি জরুরি সেল সম্প্রচার প্রাপ্ত হয় তখন ক্ষতিকারক অ্যাপ্লিকেশানগুলি আপনার ডিভাইসের কার্য সম্পাদনা বা কার্যকলাপে প্রতিবন্ধকতার সৃষ্টি করতে পারে৷"</string> - <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"গ্রাহক হিসাবে নেওয়া ফিডগুলি পড়ে"</string> + <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"গ্রাহক হিসেবে নেওয়া ফিডগুলি পড়ে"</string> <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"অ্যাপ্লিকেশানকে বর্তমানে সিঙ্ক করা ফিডগুলির সম্পর্কে বিবরণ পেতে দেয়৷"</string> <string name="permlab_sendSms" msgid="7544599214260982981">"SMS পাঠানো ও দেখা,আপনি কি পরিচিতি কে এগুলি করার অনুমতি দেবেন?"</string> <string name="permdesc_sendSms" msgid="7094729298204937667">"অ্যাপ্লিকেশানটিকে এসএমএসগুলি পাঠাতে অনুমতি দেয়৷ এর জন্য অপ্রত্যাশিত চার্জ কাটা হতে পারে৷ ক্ষতিকারক অ্যাপ্লিকেশানগুলি আপনার নিশ্চিতকরণ ছাড়া বার্তা পাঠানোর মাধ্যমে আপনাকে অর্থ চার্জ করতে পারে৷"</string> - <string name="permlab_readSms" msgid="8745086572213270480">"আপনার পাঠ্য বার্তা পড়ুন (SMS বা MMS)"</string> - <string name="permdesc_readSms" product="tablet" msgid="4741697454888074891">"এই অ্যাপটি আপনার ট্যাবলেটে সংরক্ষিত সমস্ত SMS (পাঠ্য) বার্তা পড়তে পারে৷"</string> - <string name="permdesc_readSms" product="tv" msgid="5796670395641116592">"এই অ্যাপটি আপনার টিভিতে সংরক্ষিত সমস্ত SMS (পাঠ্য) বার্তা পড়তে পারে৷"</string> - <string name="permdesc_readSms" product="default" msgid="6826832415656437652">"এই অ্যাপটি আপনার ফোনে সংরক্ষিত সমস্ত SMS (পাঠ্য) বার্তা পড়তে পারে৷"</string> - <string name="permlab_receiveWapPush" msgid="5991398711936590410">"পাঠ্য বার্তা পান (WAP)"</string> + <string name="permlab_readSms" msgid="8745086572213270480">"আপনার টেক্সট মেসেজ পড়ুন (SMS বা MMS)"</string> + <string name="permdesc_readSms" product="tablet" msgid="4741697454888074891">"এই অ্যাপটি আপনার ট্যাবলেটে স্টোর করা সমস্ত SMS (টেক্সট) মেসেজ পড়তে পারে৷"</string> + <string name="permdesc_readSms" product="tv" msgid="5796670395641116592">"এই অ্যাপটি আপনার টিভিতে স্টোর করা সমস্ত SMS (টেক্সট) মেসেজ পড়তে পারে৷"</string> + <string name="permdesc_readSms" product="default" msgid="6826832415656437652">"এই অ্যাপটি আপনার ফোনে স্টোর করা সমস্ত SMS (টেক্সট) মেসেজ পড়তে পারে৷"</string> + <string name="permlab_receiveWapPush" msgid="5991398711936590410">"টেক্সট মেসেজ পান (WAP)"</string> <string name="permdesc_receiveWapPush" msgid="748232190220583385">"অ্যাপ্লিকেশানটিকে WAP বার্তা প্রাপ্ত করার এবং প্রক্রিয়া করার অনুমতি দেয়৷ এর মানে হল অ্যাপ্লিকেশানটি আপনার ডিভাইস থেকে পাঠানো বার্তাগুলিকে পর্যবেক্ষণ করতে পারে এবং মুছতে পারে সেগুলিকে আপনাকে না দেখিয়ে৷"</string> <string name="permlab_getTasks" msgid="6466095396623933906">"চলমান অ্যাপ্লিকেশান উদ্ধার করে"</string> <string name="permdesc_getTasks" msgid="7454215995847658102">"বর্তমানে ও সাম্প্রতিককালের সক্রিয় ক্রিয়াগুলি সম্বন্ধে তথ্য পুনরুদ্ধার করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷ এছাড়া এটি ডিভাইসটিতে কোন অ্যাপ্লিকেশানগুলি ব্যবহৃত হচ্ছে তার বিষয়ে তথ্য খুঁজে বের করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করতে পারে৷"</string> @@ -391,7 +391,7 @@ <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"মোবাইল টাওয়ার এবং ওয়াই-ফাই নেটওয়ার্কগুলির মত নেটওয়ার্কের উৎসগুলির উপর ভিত্তি করে এই অ্যাপটি আপনার অবস্থান সনাক্ত করতে পারে৷ এই অবস্থান পরিষেবাগুলি অবশ্যই চালু রাখতে হবে এবং অ্যাপটি যাতে সেগুলি ব্যবহার করতে পারে সেজন্য সেগুলিকে আপনার টিভিতে উপলব্ধ করে রাখতে হবে৷"</string> <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"মোবাইল টাওয়ার এবং ওয়াই-ফাই নেটওয়ার্কগুলির মত নেটওয়ার্ক উৎসগুলির উপর ভিত্তি করে এই অ্যাপটি আপনার অবস্থান সনাক্ত করতে পারে৷ এই অবস্থান পরিষেবাগুলি অবশ্যই চালু রাখতে হবে এবং অ্যাপটি যাতে সেগুলি ব্যবহার করতে পারে সেজন্য সেগুলিকে আপনার ফোনে উপলব্ধ করে রাখতে হবে৷"</string> <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"আপনার অডিও সেটিংস পরিবর্তন করে"</string> - <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ভলিউম এবং যেখানে স্পিকার আউটপুট সামগ্রী হিসাবে ব্যবহৃত হয় সেই সব ক্ষেত্রে গ্লোবাল অডিও সেটিংসের সংশোধন করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷"</string> + <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ভলিউম এবং যেখানে স্পিকার আউটপুট সামগ্রী হিসেবে ব্যবহৃত হয় সেই সব ক্ষেত্রে গ্লোবাল অডিও সেটিংসের সংশোধন করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷"</string> <string name="permlab_recordAudio" msgid="3876049771427466323">"অডিও রেকর্ড"</string> <string name="permdesc_recordAudio" msgid="4245930455135321433">"এই অ্যাপটি মাইক্রোফোন ব্যবহার করে যে কোনো সময় অডিও রেকর্ড করতে পারে৷"</string> <string name="permlab_sim_communication" msgid="2935852302216852065">"সিম এ আদেশগুলি পাঠান"</string> @@ -570,7 +570,7 @@ <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"সতর্কীকরণ ছাড়াই এই টিভিতে থাকা ব্যাবহারকার্রী ডেটা মুছে ফেলে৷"</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="6787904546711590238">"সতর্কীকরণ ছাড়াই এই ফোনে থাকা ব্যাবহারকার্রী ডেটা মুছে ফেলে৷"</string> <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"ডিভাইসের বৈশ্বিক প্রক্সী সেট করে"</string> - <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"নীতিযখন নীতি সক্ষম করা হয় তখন ডিভাইসের বৈশ্বিক প্রক্সী ব্যবহার করা হবে সেই হিসাবে সেট করে৷ শুধুমাত্র ডিভাইসের মালিক বৈশ্বিক প্রক্সী সেট করতে পারেন৷"</string> + <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"নীতিযখন নীতি সক্ষম করা হয় তখন ডিভাইসের বৈশ্বিক প্রক্সী ব্যবহার করা হবে সেই হিসেবে সেট করে৷ শুধুমাত্র ডিভাইসের মালিক বৈশ্বিক প্রক্সী সেট করতে পারেন৷"</string> <string name="policylab_expirePassword" msgid="5610055012328825874">"স্ক্রিন লক করার জন্য পাসওয়ার্ডের মেয়াদ শেষ হওয়ার সময় সেট করে"</string> <string name="policydesc_expirePassword" msgid="5367525762204416046">"স্ক্রিন লক করার পাসওয়ার্ড কত ঘন ঘন পরিবর্তন করা আবশ্যক তা পরিবর্তন করুন৷"</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"সঞ্চয়স্থানের এনক্রিপশান সেট করে"</string> @@ -755,7 +755,7 @@ <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"আনলক করতে আপনার Google অ্যাকাউন্টের মাধ্যমে প্রবেশ করুন৷"</string> <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"ব্যবহারকারীনাম (ইমেল)"</string> <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"পাসওয়ার্ড"</string> - <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"প্রবেশ করুন"</string> + <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"সাইন-ইন করুন"</string> <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"অবৈধ ব্যবহারকারী নাম অথবা পাসওয়ার্ড৷"</string> <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"আপনার ব্যবহারকারী নাম অথবা পাসওয়ার্ড ভুলে গেছেন?\n"<b>"google.com/accounts/recovery"</b>" এ যান৷"</string> <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"পরীক্ষা করা হচ্ছে..."</string> @@ -799,7 +799,7 @@ <string name="factorytest_failed" msgid="5410270329114212041">"ফ্যাক্টরী পরীক্ষা ব্যর্থ হয়েছে"</string> <string name="factorytest_not_system" msgid="4435201656767276723">"FACTORY_TEST ক্রিয়াটি শুধুমাত্র /system/app এ ইনস্টল থাকা প্যাকেজগুলি সমর্থন করে৷"</string> <string name="factorytest_no_action" msgid="872991874799998561">"এমন কোনো প্যাকেজ খুঁজে পাওয়া যায়নি যা FACTORY_TEST ক্রিয়া প্রদান করে৷"</string> - <string name="factorytest_reboot" msgid="6320168203050791643">"পুনরায় চালু করুন"</string> + <string name="factorytest_reboot" msgid="6320168203050791643">"রিবুট করুন"</string> <string name="js_dialog_title" msgid="1987483977834603872">"\"<xliff:g id="TITLE">%s</xliff:g>\" পৃষ্ঠা অনুসারে:"</string> <string name="js_dialog_title_default" msgid="6961903213729667573">"জাভাস্ক্রিপ্ট"</string> <string name="js_dialog_before_unload_title" msgid="2619376555525116593">"বেরিয়ে যাওয়া নিশ্চিত করুন"</string> @@ -963,7 +963,7 @@ <string name="copy" msgid="2681946229533511987">"অনুলিপি"</string> <string name="failed_to_copy_to_clipboard" msgid="1833662432489814471">"ক্লিপবোর্ডে কপি করা যায়নি"</string> <string name="paste" msgid="5629880836805036433">"আটকান"</string> - <string name="paste_as_plain_text" msgid="5427792741908010675">"প্লেইন টেক্সট হিসাবে আটকান"</string> + <string name="paste_as_plain_text" msgid="5427792741908010675">"প্লেইন টেক্সট হিসেবে আটকান"</string> <string name="replace" msgid="5781686059063148930">"প্রতিস্থাপন করুন..."</string> <string name="delete" msgid="6098684844021697789">"মুছুন"</string> <string name="copyUrl" msgid="2538211579596067402">"URL কপি করুন"</string> @@ -1009,7 +1009,7 @@ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"%1$s ব্যবহার করে পাঠান"</string> <string name="whichSendToApplicationLabel" msgid="8878962419005813500">"পাঠান"</string> <string name="whichHomeApplication" msgid="4307587691506919691">"একটি হোম অ্যাপ্লিকেশন নির্বাচন করুন"</string> - <string name="whichHomeApplicationNamed" msgid="4493438593214760979">"হোম হিসাবে %1$s ব্যবহার করুন"</string> + <string name="whichHomeApplicationNamed" msgid="4493438593214760979">"হোম হিসেবে %1$s ব্যবহার করুন"</string> <string name="whichHomeApplicationLabel" msgid="809529747002918649">"ছবি তুলুন"</string> <string name="whichImageCaptureApplication" msgid="3680261417470652882">"এই দিয়ে ছবি তুলুন"</string> <string name="whichImageCaptureApplicationNamed" msgid="8619384150737825003">"%1$s দিয়ে ছবি তুলুন"</string> @@ -1108,8 +1108,8 @@ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"সমস্ত নেটওয়ার্ক দেখতে ট্যাপ করুন"</string> <string name="wifi_available_action_connect" msgid="2635699628459488788">"সংযুক্ত করুন"</string> <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"সমস্ত নেটওয়ার্ক"</string> - <string name="wifi_available_sign_in" msgid="9157196203958866662">"ওয়াই-ফাই নেটওয়ার্কে প্রবেশ করুন"</string> - <string name="network_available_sign_in" msgid="1848877297365446605">"নেটওয়ার্কে প্রবেশ করুন"</string> + <string name="wifi_available_sign_in" msgid="9157196203958866662">"ওয়াই-ফাই নেটওয়ার্কে সাইন-ইন করুন"</string> + <string name="network_available_sign_in" msgid="1848877297365446605">"নেটওয়ার্কে সাইন-ইন করুন"</string> <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) --> <skip /> <string name="wifi_no_internet" msgid="8451173622563841546">"ওয়াই-ফাই -তে কোনো ইন্টারনেট অ্যাক্সেস নেই"</string> @@ -1259,7 +1259,7 @@ <string name="permdesc_requestDeletePackages" msgid="3406172963097595270">"একটি অ্যাপ্লিকেশানকে প্যাকেজগুলি মুছে দেওয়ার অনুরোধ জানাতে দেয়৷"</string> <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"ব্যাটারি অপ্টিমাইজেশন উপেক্ষা করার জন্য অনুমতি চাওয়া"</string> <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"কোনো অ্যাপের জন্য ব্যাটারি অপ্টিমাইজেশন উপেক্ষা করতে সেটিকে অনুমতির চাওয়ার মঞ্জুরি দেয়৷"</string> - <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"জুম নিয়ন্ত্রণের জন্য দুবার আলতো চাপুন"</string> + <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"জুম নিয়ন্ত্রণের জন্য দুবার ট্যাপ করুন"</string> <string name="gadget_host_error_inflating" msgid="4882004314906466162">"উইজেট যোগ করা যায়নি৷"</string> <string name="ime_action_go" msgid="8320845651737369027">"যান"</string> <string name="ime_action_search" msgid="658110271822807811">"অনুসন্ধান করুন"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> তে সংযুক্ত হয়েছে৷ নেটওয়ার্ক পরিচালনা করতে আলতো চাপুন৷"</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"সর্বদা-চালু VPN সংযুক্ত হচ্ছে..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"সর্বদা-চালু VPN সংযুক্ত হয়েছে"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"সর্বদা-চালু VPN এর সংযোগ বিচ্ছিন্ন হয়েছে"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"সবসময়-চালু VPN এর সংযোগ বিচ্ছিন্ন আছে"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"সর্বদা-চালু VPN ত্রুটি"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"সেট আপ করতে আলতো চাপুন"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"নেটওয়ার্ক অথবা VPN সেটিংস পরিবর্তন করুন"</string> <string name="upload_file" msgid="2897957172366730416">"ফাইল বেছে নিন"</string> <string name="no_file_chosen" msgid="6363648562170759465">"কোনো ফাইল নির্বাচন করা হয়নি"</string> <string name="reset" msgid="2448168080964209908">"আবার সেট করুন"</string> @@ -1464,7 +1464,7 @@ <string name="kg_login_instructions" msgid="1100551261265506448">"আনলক করতে আপনার Google অ্যাকাউন্টের মাধ্যমে প্রবেশ করুন৷"</string> <string name="kg_login_username_hint" msgid="5718534272070920364">"ব্যবহারকারী নাম (ইমেল)"</string> <string name="kg_login_password_hint" msgid="9057289103827298549">"পাসওয়ার্ড"</string> - <string name="kg_login_submit_button" msgid="5355904582674054702">"প্রবেশ করুন"</string> + <string name="kg_login_submit_button" msgid="5355904582674054702">"সাইন-ইন করুন"</string> <string name="kg_login_invalid_input" msgid="5754664119319872197">"অবৈধ ব্যবহারকারী নাম অথবা পাসওয়ার্ড৷"</string> <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"আপনার ব্যবহারকারী নাম অথবা পাসওয়ার্ড ভুলে গেছেন?\n"<b>"google.com/accounts/recovery"</b>" এ যান৷"</string> <string name="kg_login_checking_password" msgid="1052685197710252395">"অ্যাকাউন্ট পরীক্ষা করা হচ্ছে..."</string> @@ -1581,7 +1581,7 @@ <string name="mediasize_japanese_kahu" msgid="6872696027560065173">"Kahu"</string> <string name="mediasize_japanese_kaku2" msgid="2359077233775455405">"Kaku2"</string> <string name="mediasize_japanese_you4" msgid="2091777168747058008">"You4"</string> - <string name="mediasize_unknown_portrait" msgid="3088043641616409762">"অজানা প্রতিকৃতি"</string> + <string name="mediasize_unknown_portrait" msgid="3088043641616409762">"অজানা পোর্ট্রেট"</string> <string name="mediasize_unknown_landscape" msgid="4876995327029361552">"অজানা ভূদৃশ্য"</string> <string name="write_fail_reason_cancelled" msgid="7091258378121627624">"বাতিল করা হয়েছে"</string> <string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"সামগ্রী লেখায় ত্রুটি হয়েছে"</string> @@ -1684,7 +1684,7 @@ <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS অনুরোধটিকে নতুন USSD অনুরোধে রুপান্তরিত করা হয়েছে৷"</string> <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS অনুরোধটিকে নতুন SS অনুরোধে রুপান্তরিত করা হয়েছে৷"</string> <string name="notification_work_profile_content_description" msgid="4600554564103770764">"কর্মস্থলের প্রোফাইল"</string> - <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"প্রসারিত করুন"</string> + <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"বড় করুন"</string> <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"সঙ্কুচিত করুন"</string> <string name="expand_action_accessibility" msgid="5307730695723718254">"টগল সম্প্রসারণ"</string> <string name="usb_midi_peripheral_name" msgid="7221113987741003817">"Android USB পেরিফেরাল পোর্ট"</string> diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index 25f170b1a2ca..96b9e7685762 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -251,9 +251,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozorenja"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Promotivna demonstracija u maloprodaji"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB veza"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Aplikacije koje rade u pozadini"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je pokrenuta u pozadini"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"Broj aplikacija koje rade u pozadini: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Aplikacije koje troše bateriju"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> troši bateriju"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"Broj aplikacija koje troše bateriju: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Dodirnite za detalje o potrošnji baterije i prijenosa podataka"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Siguran način rada"</string> @@ -481,7 +481,7 @@ <string-array name="fingerprint_acquired_vendor"> </string-array> <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"Hardver za otisak prsta nije dostupan."</string> - <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Otisak prsta se ne može sačuvati. Uklonite postojeći otisak prsta."</string> + <string name="fingerprint_error_no_space" msgid="1055819001126053318">"Otisak prsta se ne može pohraniti. Uklonite postojeći otisak prsta."</string> <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vremensko ograničenje za otisak prsta je isteklo. Pokušajte ponovo."</string> <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Radnja sa otiskom prsta je otkazana."</string> <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Previše pokušaja. Pokušajte ponovo kasnije."</string> @@ -1185,12 +1185,10 @@ <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Uvijek dozvoli"</string> <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nikada ne dozvoli"</string> <string name="sim_removed_title" msgid="6227712319223226185">"SIM kartica uklonjena"</string> - <!-- no translation found for sim_removed_message (2333164559970958645) --> - <skip /> + <string name="sim_removed_message" msgid="2333164559970958645">"Mobilna mreža bit će nedostupna do ponovnog pokretanja s umetnutom važećom SIM karticom."</string> <string name="sim_done_button" msgid="827949989369963775">"Gotovo"</string> <string name="sim_added_title" msgid="3719670512889674693">"SIM kartica dodana"</string> - <!-- no translation found for sim_added_message (6599945301141050216) --> - <skip /> + <string name="sim_added_message" msgid="6599945301141050216">"Za pristup mobilnoj mreži ponovo pokrenite uređaj."</string> <string name="sim_restart_button" msgid="4722407842815232347">"Ponovo pokreni"</string> <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Da bi nova SIM kartica ispravno radila, morate instalirati i otvoriti aplikaciju svog operatera."</string> <string name="carrier_app_dialog_button" msgid="7900235513678617329">"PREUZMI APLIKACIJU"</string> @@ -1320,9 +1318,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Povezano sa sesijom <xliff:g id="SESSION">%s</xliff:g>. Dodirnite da upravljate mrežom."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Povezivanje na uvijek aktivni VPN…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Povezan na uvijek aktivni VPN"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Uvijek aktivni VPN nije povezan"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Prekinuta je veza s uvijek uključenim VPN-om"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Greška u povezivanju na uvijek aktivni VPN"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Dodirnite za postavke"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Promijenite postavke mreže ili VPN-a"</string> <string name="upload_file" msgid="2897957172366730416">"Odabir fajla"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Nije izabran nijedan fajl"</string> <string name="reset" msgid="2448168080964209908">"Vraćanje na zadano"</string> @@ -1416,8 +1414,7 @@ <string name="data_usage_limit_body" msgid="291731708279614081">"Podaci pauz. za ostatak ciklusa"</string> <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"Premašeni 2G-3G podaci"</string> <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"Premašeni 4G podaci"</string> - <!-- no translation found for data_usage_mobile_limit_snoozed_title (279240572165412168) --> - <skip /> + <string name="data_usage_mobile_limit_snoozed_title" msgid="279240572165412168">"Prekoračeno je ograničenje za podatke na mobilnom uređaju"</string> <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Premašeno Wi-Fi ograničenje"</string> <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> preko navedenog ograničenja."</string> <string name="data_usage_restricted_title" msgid="5965157361036321914">"Pozadinski podaci su ograničeni"</string> @@ -1742,7 +1739,7 @@ <string name="importance_from_person" msgid="9160133597262938296">"Ovo je značajno zbog osoba koje su uključene."</string> <string name="user_creation_account_exists" msgid="1942606193570143289">"Da li dozvoljavate aplikaciji <xliff:g id="APP">%1$s</xliff:g> da kreira novog korisnika s računom <xliff:g id="ACCOUNT">%2$s</xliff:g>?"</string> <string name="user_creation_adding" msgid="4482658054622099197">"Da li dozvoljavate da <xliff:g id="APP">%1$s</xliff:g> kreira novog korisnika za <xliff:g id="ACCOUNT">%2$s</xliff:g> (Korisnik sa ovim nalogom već postoji)?"</string> - <string name="language_selection_title" msgid="2680677278159281088">"Dodaj jezik"</string> + <string name="language_selection_title" msgid="2680677278159281088">"Dodajte jezik"</string> <string name="country_selection_title" msgid="2954859441620215513">"Izbor regije"</string> <string name="search_language_hint" msgid="7042102592055108574">"Upišite ime jezika"</string> <string name="language_picker_section_suggested" msgid="8414489646861640885">"Predloženo"</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index 043bcab999f9..5fa9e1d12861 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demostració comercial"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Connexió USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Aplicacions que s\'estan executant en segon pla"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> s\'està executant en segon pla"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicacions s\'estan executant en segon pla"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Aplicacions que consumeixen bateria"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> està consumint bateria"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicacions estan consumint bateria"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Toca per obtenir informació sobre l\'ús de dades i de bateria"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Mode segur"</string> @@ -1199,7 +1199,7 @@ <string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTEIX"</string> <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"REBUTJA"</string> <string name="select_input_method" msgid="8547250819326693584">"Canvia el teclat"</string> - <string name="show_ime" msgid="2506087537466597099">"El deixa a la pantalla mentre el teclat físic està actiu"</string> + <string name="show_ime" msgid="2506087537466597099">"Mantén-lo a la pantalla mentre el teclat físic està actiu"</string> <string name="hardware" msgid="194658061510127999">"Mostra el teclat virtual"</string> <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configura el teclat físic"</string> <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toca per seleccionar l\'idioma i el disseny"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Connectat a <xliff:g id="SESSION">%s</xliff:g>. Pica per gestionar la xarxa."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"T\'estàs connectant a la VPN sempre activada…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Estàs connectat a la VPN sempre activada"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"La VPN sempre activada està desconnectada"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"S\'ha desconnectat de la VPN sempre activada"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Error de la VPN sempre activada"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Toca per configurar"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Canvia la configuració de la xarxa o de la VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Tria un fitxer"</string> <string name="no_file_chosen" msgid="6363648562170759465">"No s\'ha escollit cap fitxer"</string> <string name="reset" msgid="2448168080964209908">"Restableix"</string> @@ -1458,7 +1458,7 @@ <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Codi PIN incorrecte."</string> <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Escriu un PIN que tingui de 4 a 8 números."</string> <string name="kg_invalid_sim_puk_hint" msgid="6025069204539532000">"El codi PUK ha de tenir 8 números."</string> - <string name="kg_invalid_puk" msgid="3638289409676051243">"Torna a introduir el codi PUK correcte. Els intents repetits faran que es desactivi la SIM de manera permanent."</string> + <string name="kg_invalid_puk" msgid="3638289409676051243">"Torna a introduir el codi PUK correcte. Els intents repetits faran que es desactivi la SIM permanentment."</string> <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"Els codis PIN no coincideixen"</string> <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Massa intents incorrectes"</string> <string name="kg_login_instructions" msgid="1100551261265506448">"Per desbloquejar el telèfon, inicia la sessió amb el compte de Google."</string> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 98ce236ba465..9a3b86a61529 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -254,9 +254,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozornění"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Prodejní ukázka"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Připojení USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Aplikace běžící na pozadí"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> běží na pozadí"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"Aplikace (<xliff:g id="NUMBER">%1$d</xliff:g>) běží na pozadí"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Aplikace spotřebovávají baterii"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> využívá baterii"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"Aplikace (<xliff:g id="NUMBER">%1$d</xliff:g>) využívají baterii"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Klepnutím zobrazíte podrobnosti o využití baterie a dat"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Nouzový režim"</string> @@ -1338,9 +1338,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Připojeno k relaci <xliff:g id="SESSION">%s</xliff:g>. Klepnutím můžete síť spravovat."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Připojování k trvalé síti VPN…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Je připojena trvalá síť VPN"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Trvalá síť VPN je odpojena"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Odpojeno od trvalé sítě VPN"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Chyba trvalé sítě VPN"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Klepnutím přejděte do Nastavení"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Změňte síť nebo nastavení VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Zvolit soubor"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Není vybrán žádný soubor"</string> <string name="reset" msgid="2448168080964209908">"Resetovat"</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 658bbcb3cb90..fb76f1e91128 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Underretninger"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demo til udstilling i butik"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB-forbindelse"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Apps, der kører i baggrunden"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> kører i baggrunden"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> apps kører i baggrunden"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Apps, der bruger batteri"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> bruger batteri"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> apps bruger batteri"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Tryk for at se oplysninger om batteri- og dataforbrug"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Sikker tilstand"</string> @@ -261,7 +261,7 @@ <string name="permgroupdesc_contacts" msgid="6951499528303668046">"have adgang til dine kontaktpersoner"</string> <string name="permgrouprequest_contacts" msgid="1601591667800538208">"Giv <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> adgang til dine kontaktpersoner"</string> <string name="permgrouplab_location" msgid="7275582855722310164">"Placering"</string> - <string name="permgroupdesc_location" msgid="1346617465127855033">"at få adgang til enhedens placering"</string> + <string name="permgroupdesc_location" msgid="1346617465127855033">"få adgang til enhedens placering"</string> <string name="permgrouprequest_location" msgid="8903573681261610809">"Giv <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> adgang til enhedens placering"</string> <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalender"</string> <string name="permgroupdesc_calendar" msgid="3889615280211184106">"have adgang til din kalender"</string> @@ -296,7 +296,7 @@ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Kan trykke, stryge, knibe sammen og udføre andre bevægelser."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Fingeraftryksbevægelser"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Kan registrere bevægelser, der foretages på enhedernes fingeraftrykslæser."</string> - <string name="permlab_statusBar" msgid="7417192629601890791">"deaktiver eller rediger statuslinje"</string> + <string name="permlab_statusBar" msgid="7417192629601890791">"deaktivere eller redigere statuslinje"</string> <string name="permdesc_statusBar" msgid="8434669549504290975">"Tillader, at appen kan deaktivere statusbjælken eller tilføje og fjerne systemikoner."</string> <string name="permlab_statusBarService" msgid="4826835508226139688">"vær statusbjælken"</string> <string name="permdesc_statusBarService" msgid="716113660795976060">"Tillader, at appen er statusbjælken."</string> @@ -777,7 +777,7 @@ <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"Brugervælger"</string> <string name="keyguard_accessibility_status" msgid="8008264603935930611">"Status"</string> <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"Kamera"</string> - <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Mediekontrolelementer"</string> + <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"Mediestyring"</string> <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"Omrokering af widgets er påbegyndt."</string> <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Omrokering af widgets er afsluttet."</string> <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"Widgetten <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> er slettet."</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Forbundet til <xliff:g id="SESSION">%s</xliff:g>. Tryk for at administrere netværket."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Opretter forbindelse til konstant VPN…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Konstant VPN er forbundet"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Forbindelsen til konstant VPN er afbrudt"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Forbindelsen til konstant VPN blev afbrudt"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Fejl i konstant VPN"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tryk for at konfigurere"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Skift netværks- eller VPN-indstillinger"</string> <string name="upload_file" msgid="2897957172366730416">"Vælg fil"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Ingen fil er valgt"</string> <string name="reset" msgid="2448168080964209908">"Nulstil"</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 3d78c2ac139e..054a3bd9ca1b 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Warnmeldungen"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demo für Einzelhandel"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB-Verbindung"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Apps, die im Hintergrund ausgeführt werden"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> wird im Hintergrund ausgeführt"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> Apps werden im Hintergrund ausgeführt"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Strom verbrauchende Apps"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> verbraucht Strom"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> Apps verbrauchen Strom"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Für Details zur Akku- und Datennutzung tippen"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Abgesicherter Modus"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Verbunden mit <xliff:g id="SESSION">%s</xliff:g>. Zum Verwalten des Netzwerks tippen"</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Verbindung zu durchgehend aktivem VPN wird hergestellt…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Mit durchgehend aktivem VPN verbunden"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Verbindung zu durchgehend aktivem VPN getrennt"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Verbindung mit dauerhaft aktivem VPN getrennt"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Durchgehend aktives VPN – Verbindungsfehler"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Zum Einrichten tippen"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Netzwerk- oder VPN-Einstellungen ändern"</string> <string name="upload_file" msgid="2897957172366730416">"Datei auswählen"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Keine ausgewählt"</string> <string name="reset" msgid="2448168080964209908">"Zurücksetzen"</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index b6f433f2869b..edccd2ea6902 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Ειδοποιήσεις"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Επίδειξη λιανικής"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Σύνδεση USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Εφαρμογές που εκτελούνται στο παρασκήνιο"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> εκτελείται στο παρασκήνιο"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> εφαρμογές εκτελούνται στο παρασκήνιο"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Εφαρμογές που καταναλώνουν μπαταρία"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> χρησιμοποιεί μπαταρία"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> εφαρμογές χρησιμοποιούν μπαταρία"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Πατήστε για λεπτομέρειες σχετικά με τη χρήση μπαταρίας και δεδομένων"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Ασφαλής λειτουργία"</string> @@ -259,31 +259,31 @@ <string name="managed_profile_label" msgid="5289992269827577857">"Μετάβαση σε προφίλ εργασίας"</string> <string name="permgrouplab_contacts" msgid="3657758145679177612">"Επαφές"</string> <string name="permgroupdesc_contacts" msgid="6951499528303668046">"πρόσβαση στις επαφές σας"</string> - <string name="permgrouprequest_contacts" msgid="1601591667800538208">"Να επιτρέπεται στο <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> να έχει πρόσβαση στις επαφές σας"</string> + <string name="permgrouprequest_contacts" msgid="1601591667800538208">"Να επιτρέπεται στην εφαρμογή <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> να έχει πρόσβαση στις επαφές σας"</string> <string name="permgrouplab_location" msgid="7275582855722310164">"Τοποθεσία"</string> <string name="permgroupdesc_location" msgid="1346617465127855033">"έχει πρόσβαση στην τοποθεσία της συσκευής"</string> - <string name="permgrouprequest_location" msgid="8903573681261610809">"Να επιτρέπεται στο <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> να έχει πρόσβαση στην τοποθεσία της συσκευής"</string> + <string name="permgrouprequest_location" msgid="8903573681261610809">"Να επιτρέπεται στην εφαρμογή <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> να έχει πρόσβαση στην τοποθεσία της συσκευής"</string> <string name="permgrouplab_calendar" msgid="5863508437783683902">"Ημερολόγιο"</string> <string name="permgroupdesc_calendar" msgid="3889615280211184106">"έχει πρόσβαση στο ημερολόγιό σας"</string> - <string name="permgrouprequest_calendar" msgid="6704529828699071445">"Να επιτρέπεται στο <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> να έχει πρόσβαση στο ημερολόγιό σας"</string> + <string name="permgrouprequest_calendar" msgid="6704529828699071445">"Να επιτρέπεται στην εφαρμογή <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> να έχει πρόσβαση στο ημερολόγιό σας"</string> <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string> <string name="permgroupdesc_sms" msgid="4656988620100940350">"στέλνει και να διαβάζει μηνύματα SMS"</string> - <string name="permgrouprequest_sms" msgid="605618939583628306">"Να επιτρέπεται στο <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> η αποστολή και η προβολή μηνυμάτων SMS"</string> + <string name="permgrouprequest_sms" msgid="605618939583628306">"Να επιτρέπεται στην εφαρμογή <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> η αποστολή και η προβολή μηνυμάτων SMS"</string> <string name="permgrouplab_storage" msgid="1971118770546336966">"Αποθηκευτικός χώρος"</string> <string name="permgroupdesc_storage" msgid="637758554581589203">"έχει πρόσβαση στις φωτογραφίες/πολυμέσα/αρχεία στη συσκευή σας"</string> - <string name="permgrouprequest_storage" msgid="7429669910547860218">"Να επιτρέπεται στο <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> να έχει πρόσβαση σε φωτογραφίες, μέσα και αρχεία στη συσκευή σας"</string> + <string name="permgrouprequest_storage" msgid="7429669910547860218">"Να επιτρέπεται στην εφαρμογή <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> να έχει πρόσβαση σε φωτογραφίες, μέσα και αρχεία στη συσκευή σας"</string> <string name="permgrouplab_microphone" msgid="171539900250043464">"Μικρόφωνο"</string> <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ηχογραφεί"</string> - <string name="permgrouprequest_microphone" msgid="8065941268709600606">"Να επιτρέπεται στο <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> η εγγραφή ήχου"</string> + <string name="permgrouprequest_microphone" msgid="8065941268709600606">"Να επιτρέπεται στην εφαρμογή <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> η εγγραφή ήχου"</string> <string name="permgrouplab_camera" msgid="4820372495894586615">"Κάμερα"</string> <string name="permgroupdesc_camera" msgid="3250611594678347720">"γίνεται λήψη φωτογραφιών και εγγραφή βίντεο"</string> - <string name="permgrouprequest_camera" msgid="810824326507258410">"Να επιτρέπεται στο <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> η λήψη φωτογραφιών και η εγγραφή βίντεο"</string> + <string name="permgrouprequest_camera" msgid="810824326507258410">"Να επιτρέπεται στην εφαρμογή <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> η λήψη φωτογραφιών και η εγγραφή βίντεο"</string> <string name="permgrouplab_phone" msgid="5229115638567440675">"Τηλέφωνο"</string> <string name="permgroupdesc_phone" msgid="6234224354060641055">"πραγματοποιεί και να διαχειρίζεται τηλ/κές κλήσεις"</string> - <string name="permgrouprequest_phone" msgid="7084161459732093690">"Να επιτρέπεται στο <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> η πραγματοποίηση και η διαχείριση τηλεφωνικών κλήσεων"</string> + <string name="permgrouprequest_phone" msgid="7084161459732093690">"Να επιτρέπεται στην εφαρμογή <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> η πραγματοποίηση και η διαχείριση τηλεφωνικών κλήσεων"</string> <string name="permgrouplab_sensors" msgid="416037179223226722">"Αισθητήρες σώματος"</string> <string name="permgroupdesc_sensors" msgid="7147968539346634043">"πρόσβαση στα δεδομένα αισθητήρα σχετικά με τις ζωτικές ενδείξεις σας"</string> - <string name="permgrouprequest_sensors" msgid="8631146669524259656">"Να επιτρέπεται στο <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> να έχει πρόσβαση στα δεδομένα αισθητήρα σχετικά με τις ζωτικές ενδείξεις σας."</string> + <string name="permgrouprequest_sensors" msgid="8631146669524259656">"Να επιτρέπεται στην εφαρμογή <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> να έχει πρόσβαση στα δεδομένα αισθητήρα σχετικά με τις ζωτικές ενδείξεις σας."</string> <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Ανάκτηση του περιεχομένου του παραθύρου"</string> <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Έλεγχος του περιεχομένου ενός παραθύρου με το οποίο αλληλεπιδράτε."</string> <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Ενεργοποίηση της \"Εξερεύνησης με άγγιγμα\""</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Συνδέθηκε με <xliff:g id="SESSION">%s</xliff:g>. Πατήστε για να διαχειριστείτε το δίκτυο."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Σύνδεση πάντα ενεργοποιημένου VPN…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Έχει συνδεθεί πάντα ενεργοποιημένο VPN"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Το πάντα ενεργοποιημένο VPN αποσυνδέθηκε"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Αποσύνδεση από μονίμως ενεργό VPN"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Σφάλμα πάντα ενεργοποιημένου VPN"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Πατήστε για ρύθμιση"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Αλλαγή δικτύου ή ρυθμίσεις VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Επιλογή αρχείου"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Δεν επιλέχθηκε κανένα αρχείο."</string> <string name="reset" msgid="2448168080964209908">"Επαναφορά"</string> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index 60bff67bc31e..013017d48eea 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -85,8 +85,7 @@ <string name="notification_channel_network_alert" msgid="4427736684338074967">"Alerts"</string> <string name="notification_channel_call_forward" msgid="2419697808481833249">"Call forwarding"</string> <string name="notification_channel_emergency_callback" msgid="6686166232265733921">"Emergency callback mode"</string> - <!-- no translation found for notification_channel_mobile_data_status (4575131690860945836) --> - <skip /> + <string name="notification_channel_mobile_data_status" msgid="4575131690860945836">"Mobile data status"</string> <string name="notification_channel_sms" msgid="3441746047346135073">"SMS messages"</string> <string name="notification_channel_voice_mail" msgid="3954099424160511919">"Voicemail messages"</string> <string name="notification_channel_wfc" msgid="2130802501654254801">"Wi-Fi Calling"</string> @@ -249,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Retail demo"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB connection"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Apps running in background"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> is running in the background"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are running in the background"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Apps consuming battery"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using battery"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are using battery"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Tap for details on battery and data usage"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string> @@ -1295,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Connected to <xliff:g id="SESSION">%s</xliff:g>. Tap to manage the network."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Always-on VPN connecting…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Always-on VPN connected"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Always-on VPN disconnected"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Disconnected from always-on VPN"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Always-on VPN error"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tap to set up"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Change network or VPN settings"</string> <string name="upload_file" msgid="2897957172366730416">"Choose file"</string> <string name="no_file_chosen" msgid="6363648562170759465">"No file chosen"</string> <string name="reset" msgid="2448168080964209908">"Reset"</string> diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index 60bff67bc31e..013017d48eea 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -85,8 +85,7 @@ <string name="notification_channel_network_alert" msgid="4427736684338074967">"Alerts"</string> <string name="notification_channel_call_forward" msgid="2419697808481833249">"Call forwarding"</string> <string name="notification_channel_emergency_callback" msgid="6686166232265733921">"Emergency callback mode"</string> - <!-- no translation found for notification_channel_mobile_data_status (4575131690860945836) --> - <skip /> + <string name="notification_channel_mobile_data_status" msgid="4575131690860945836">"Mobile data status"</string> <string name="notification_channel_sms" msgid="3441746047346135073">"SMS messages"</string> <string name="notification_channel_voice_mail" msgid="3954099424160511919">"Voicemail messages"</string> <string name="notification_channel_wfc" msgid="2130802501654254801">"Wi-Fi Calling"</string> @@ -249,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Retail demo"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB connection"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Apps running in background"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> is running in the background"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are running in the background"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Apps consuming battery"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using battery"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are using battery"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Tap for details on battery and data usage"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string> @@ -1295,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Connected to <xliff:g id="SESSION">%s</xliff:g>. Tap to manage the network."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Always-on VPN connecting…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Always-on VPN connected"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Always-on VPN disconnected"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Disconnected from always-on VPN"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Always-on VPN error"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tap to set up"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Change network or VPN settings"</string> <string name="upload_file" msgid="2897957172366730416">"Choose file"</string> <string name="no_file_chosen" msgid="6363648562170759465">"No file chosen"</string> <string name="reset" msgid="2448168080964209908">"Reset"</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index 60bff67bc31e..013017d48eea 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -85,8 +85,7 @@ <string name="notification_channel_network_alert" msgid="4427736684338074967">"Alerts"</string> <string name="notification_channel_call_forward" msgid="2419697808481833249">"Call forwarding"</string> <string name="notification_channel_emergency_callback" msgid="6686166232265733921">"Emergency callback mode"</string> - <!-- no translation found for notification_channel_mobile_data_status (4575131690860945836) --> - <skip /> + <string name="notification_channel_mobile_data_status" msgid="4575131690860945836">"Mobile data status"</string> <string name="notification_channel_sms" msgid="3441746047346135073">"SMS messages"</string> <string name="notification_channel_voice_mail" msgid="3954099424160511919">"Voicemail messages"</string> <string name="notification_channel_wfc" msgid="2130802501654254801">"Wi-Fi Calling"</string> @@ -249,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Retail demo"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB connection"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Apps running in background"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> is running in the background"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are running in the background"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Apps consuming battery"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using battery"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are using battery"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Tap for details on battery and data usage"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string> @@ -1295,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Connected to <xliff:g id="SESSION">%s</xliff:g>. Tap to manage the network."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Always-on VPN connecting…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Always-on VPN connected"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Always-on VPN disconnected"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Disconnected from always-on VPN"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Always-on VPN error"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tap to set up"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Change network or VPN settings"</string> <string name="upload_file" msgid="2897957172366730416">"Choose file"</string> <string name="no_file_chosen" msgid="6363648562170759465">"No file chosen"</string> <string name="reset" msgid="2448168080964209908">"Reset"</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index 60bff67bc31e..013017d48eea 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -85,8 +85,7 @@ <string name="notification_channel_network_alert" msgid="4427736684338074967">"Alerts"</string> <string name="notification_channel_call_forward" msgid="2419697808481833249">"Call forwarding"</string> <string name="notification_channel_emergency_callback" msgid="6686166232265733921">"Emergency callback mode"</string> - <!-- no translation found for notification_channel_mobile_data_status (4575131690860945836) --> - <skip /> + <string name="notification_channel_mobile_data_status" msgid="4575131690860945836">"Mobile data status"</string> <string name="notification_channel_sms" msgid="3441746047346135073">"SMS messages"</string> <string name="notification_channel_voice_mail" msgid="3954099424160511919">"Voicemail messages"</string> <string name="notification_channel_wfc" msgid="2130802501654254801">"Wi-Fi Calling"</string> @@ -249,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Retail demo"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB connection"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Apps running in background"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> is running in the background"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are running in the background"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Apps consuming battery"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using battery"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are using battery"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Tap for details on battery and data usage"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string> @@ -1295,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Connected to <xliff:g id="SESSION">%s</xliff:g>. Tap to manage the network."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Always-on VPN connecting…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Always-on VPN connected"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Always-on VPN disconnected"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Disconnected from always-on VPN"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Always-on VPN error"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tap to set up"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Change network or VPN settings"</string> <string name="upload_file" msgid="2897957172366730416">"Choose file"</string> <string name="no_file_chosen" msgid="6363648562170759465">"No file chosen"</string> <string name="reset" msgid="2448168080964209908">"Reset"</string> diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml index f001147d35e0..eff2bd264bc7 100644 --- a/core/res/res/values-en-rXC/strings.xml +++ b/core/res/res/values-en-rXC/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Retail demo"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB connection"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Apps running in background"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> is running in the background"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are running in the background"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Apps consuming battery"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> is using battery"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> apps are using battery"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Tap for details on battery and data usage"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Connected to <xliff:g id="SESSION">%s</xliff:g>. Tap to manage the network."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Always-on VPN connecting…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Always-on VPN connected"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Always-on VPN disconnected"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Disconnected from always-on VPN"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Always-on VPN error"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tap to set up"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Change network or VPN settings"</string> <string name="upload_file" msgid="2897957172366730416">"Choose file"</string> <string name="no_file_chosen" msgid="6363648562170759465">"No file chosen"</string> <string name="reset" msgid="2448168080964209908">"Reset"</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 0ebceaf10d33..a96f02eafdd9 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demo para punto de venta"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Conexión USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Apps que se ejecutan en segundo plano"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> se está ejecutando en segundo plano"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> apps se están ejecutando en segundo plano"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Apps que consumen batería"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> está consumiendo batería"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> apps están consumiendo batería"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Presiona para obtener información sobre el uso de datos y de la batería"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Conectado a <xliff:g id="SESSION">%s</xliff:g>. Pulsa para gestionar la red."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Estableciendo conexión con la VPN siempre activada..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Se estableció conexión con la VPN siempre activada."</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Se desconectó la VPN siempre activada"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Desconectado de la VPN siempre activa"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Se produjo un error al establecer conexión con la VPN siempre activada."</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Presiona para configurar"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Cambiar configuración de red o VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Elegir archivo"</string> <string name="no_file_chosen" msgid="6363648562170759465">"No se seleccionó un archivo."</string> <string name="reset" msgid="2448168080964209908">"Restablecer"</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 478e4aa90c91..3f49aa8ef91c 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demo para tiendas"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Conexión USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Aplicaciones que se están ejecutando en segundo plano"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> se está ejecutando en segundo plano"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicaciones se están ejecutando en segundo plano"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Aplicaciones que consumen batería"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> está usando la batería"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicaciones están usando la batería"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Toca para ver información detallada sobre el uso de datos y de la batería"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string> @@ -1199,7 +1199,7 @@ <string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTIR"</string> <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RECHAZAR"</string> <string name="select_input_method" msgid="8547250819326693584">"Cambiar teclado"</string> - <string name="show_ime" msgid="2506087537466597099">"Debe seguir en pantalla mientras el teclado físico esté activo"</string> + <string name="show_ime" msgid="2506087537466597099">"Sigue en pantalla mientras el teclado físico está activo"</string> <string name="hardware" msgid="194658061510127999">"Mostrar teclado virtual"</string> <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Configura el teclado físico"</string> <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toca para seleccionar el idioma y el diseño"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Conectado a <xliff:g id="SESSION">%s</xliff:g>. Toca para administrar la red."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Conectando VPN siempre activada…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN siempre activada conectada"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"VPN siempre activada desconectada"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Desconectado de VPN siempre activada"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Error de VPN siempre activada"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Toca para configurar"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Cambiar ajustes de red o VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Seleccionar archivo"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Archivo no seleccionado"</string> <string name="reset" msgid="2448168080964209908">"Restablecer"</string> diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml index 18d76114a9f8..661ac0baf63f 100644 --- a/core/res/res/values-et/strings.xml +++ b/core/res/res/values-et/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Teatised"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Poedemo"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB-ühendus"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Rakendusi käitatakse taustal"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"Rakendust <xliff:g id="APP_NAME">%1$s</xliff:g> käitatakse taustal"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> rakendust käitatakse taustal"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Rakendused kasutavad akutoidet"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> kasutab akutoidet"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> rakendust kasutab akutoidet"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Aku ja andmekasutuse üksikasjade nägemiseks puudutage"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Turvarežiim"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Ühendatud seansiga <xliff:g id="SESSION">%s</xliff:g>. Koputage võrgu haldamiseks"</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Ühendamine alati sees VPN-iga …"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Ühendatud alati sees VPN-iga"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Alati sees VPN pole ühendatud"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Ühendus alati sisselülitatud VPN-iga katkestati"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Alati sees VPN-i viga"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Puudutage seadistamiseks"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Vahetage võrku või muutke VPN-i seadeid"</string> <string name="upload_file" msgid="2897957172366730416">"Valige fail"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Ühtegi faili pole valitud"</string> <string name="reset" msgid="2448168080964209908">"Lähtesta"</string> diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index 343bf7ecc9f1..87dc06e898aa 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Abisuak"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Saltzaileentzako demoa"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB konexioa"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Aplikazioak exekutatzen ari dira atzeko planoan"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> exekutatzen ari da atzeko planoan"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> exekutatzen ari dira atzeko planoan"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Bateria kontsumitzen ari diren aplikazioak"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> ari da bateria erabiltzen"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikazio ari dira bateria erabiltzen"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Sakatu bateria eta datuen erabilerari buruzko xehetasunak ikusteko"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Modu segurua"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> saiora konektatuta. Sakatu sarea kudeatzeko."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Beti aktibatuta dagoen VPNa konektatzen…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Beti aktibatuta dagoen VPNa konektatu da"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Deskonektatu egin da beti aktibatuta dagoen VPN konexioa"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Beti aktibatuta dagoen VPN sarea deskonektatuta dago"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Beti aktibatuta dagoen VPN errorea"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Konfiguratzeko, sakatu hau"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Aldatu sarearen edo VPN sarearen ezarpenak"</string> <string name="upload_file" msgid="2897957172366730416">"Aukeratu fitxategia"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Ez da fitxategirik aukeratu"</string> <string name="reset" msgid="2448168080964209908">"Berrezarri"</string> @@ -1380,7 +1380,7 @@ <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB unitatea"</string> <string name="storage_usb" msgid="3017954059538517278">"USB memoria"</string> <string name="extract_edit_menu_button" msgid="8940478730496610137">"Editatu"</string> - <string name="data_usage_warning_title" msgid="3620440638180218181">"Datu-erabilerari buruzko abisua"</string> + <string name="data_usage_warning_title" msgid="3620440638180218181">"Datuen erabilerari buruzko abisua"</string> <string name="data_usage_warning_body" msgid="6660692274311972007">"Sakatu erabilera eta ezarpenak ikusteko."</string> <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2-3 GB-ko mugara iritsi zara"</string> <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4 GB-ko mugara iritsi zara"</string> @@ -1603,7 +1603,7 @@ <item quantity="one">Saiatu berriro segundo bat igarotakoan</item> </plurals> <string name="restr_pin_try_later" msgid="973144472490532377">"Saiatu berriro geroago"</string> - <string name="immersive_cling_title" msgid="8394201622932303336">"Pantaila osoan ikusten"</string> + <string name="immersive_cling_title" msgid="8394201622932303336">"Pantaila osoko ikuspegia"</string> <string name="immersive_cling_description" msgid="3482371193207536040">"Irteteko, pasatu hatza goitik behera."</string> <string name="immersive_cling_positive" msgid="5016839404568297683">"Ados"</string> <string name="done_label" msgid="2093726099505892398">"Eginda"</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index cf02c4aedff4..4bd826388fd8 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"هشدارها"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"نمونه برای خردهفروشان"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"اتصال USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"برنامههایی که در پسزمینه اجرا میشوند"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> در پسزمینه درحال اجرا شدن است"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> برنامه در پسزمینه درحال اجرا شدن هستند"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"برنامههای مصرفکننده باتری"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> درحال استفاده کردن از باتری است"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> برنامه درحال استفاده کردن از باتری هستند"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"برای جزئیات مربوط به مصرف باتری و داده، ضربه بزنید"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>، <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"حالت ایمن"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"به <xliff:g id="SESSION">%s</xliff:g> متصل شد. برای مدیریت شبکه ضربه بزنید."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"در حال اتصال VPN همیشه فعال…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN همیشه فعال متصل شد"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"ارتباط VPN همیشه روشن قطع شد"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"ارتباط VPN همیشه روشن قطع شد"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"خطای VPN همیشه فعال"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"برای راهاندازی ضربه بزنید"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"تغییر شبکه یا تنظیمات VPN"</string> <string name="upload_file" msgid="2897957172366730416">"انتخاب فایل"</string> <string name="no_file_chosen" msgid="6363648562170759465">"هیچ فایلی انتخاب نشد"</string> <string name="reset" msgid="2448168080964209908">"بازنشانی"</string> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index 9c8d02c28cbf..55f3f2a6608d 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Ilmoitukset"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Esittelytila"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB-yhteys"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Sovelluksia käynnissä taustalla"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> on käynnissä taustalla"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> sovellusta on käynnissä taustalla."</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Akkua kuluttavat sovellukset"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> käyttää akkua."</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> sovellusta käyttää akkua."</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Katso lisätietoja akun ja datan käytöstä napauttamalla."</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Suojattu tila"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Yhdistetty: <xliff:g id="SESSION">%s</xliff:g>. Hallinnoi verkkoa napauttamalla."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Yhdistetään aina käytössä olevaan VPN-verkkoon..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Yhdistetty aina käytössä olevaan VPN-verkkoon"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Aina käytössä olevan VPN:n yhteys on katkaistu"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Yhteys aina päällä olevaan VPN:ään katkennut"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Aina käytössä oleva VPN: virhe"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Määritä koskettamalla."</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Muuta verkko- tai VPN-asetuksia"</string> <string name="upload_file" msgid="2897957172366730416">"Valitse tiedosto"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Ei valittua tiedostoa"</string> <string name="reset" msgid="2448168080964209908">"Palauta"</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index 9e1d11d005b5..6c4a1d5e64a7 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Démo en magasin"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Connexion USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Applications qui fonctionnent en arrière-plan"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> fonctionne en arrière-plan"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> applications fonctionnent en arrière-plan"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Applications qui sollicitent la pile"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> sollicite la pile"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> applications sollicitent la pile"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Touchez pour afficher des détails sur l\'utilisation de la pile et des données"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string> @@ -1088,7 +1088,7 @@ <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume des notifications"</string> <string name="ringtone_default" msgid="3789758980357696936">"Sonnerie par défaut"</string> <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Défaut (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string> - <string name="ringtone_silent" msgid="7937634392408977062">"Aucun"</string> + <string name="ringtone_silent" msgid="7937634392408977062">"Aucun(e)"</string> <string name="ringtone_picker_title" msgid="3515143939175119094">"Sonneries"</string> <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"Sons d\'alarme"</string> <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Sons de notification"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Connecté à <xliff:g id="SESSION">%s</xliff:g>. Appuyez ici pour gérer le réseau."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"RPV permanent en cours de connexion…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"RPV permanent connecté"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"RPV permanent déconnecté"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Déconnecté du RPV permanent"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Erreur du RPV permanent"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Touchez pour configurer"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Modifier les paramètres réseau ou RPV"</string> <string name="upload_file" msgid="2897957172366730416">"Choisir un fichier"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Aucun fichier sélectionné"</string> <string name="reset" msgid="2448168080964209908">"Réinitialiser"</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index d3ccd223da67..9340c7cfa1a5 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Démonstration en magasin"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Connexion USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Applications en cours d\'exécution en arrière-plan"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> s\'exécute en arrière-plan"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> applications s\'exécutent en arrière-plan"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Applications utilisant la batterie"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> utilise la batterie"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> applications utilisent la batterie"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Appuyer pour obtenir des informations sur l\'utilisation de la batterie et des données"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Connecté à <xliff:g id="SESSION">%s</xliff:g>. Appuyez ici pour gérer le réseau."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN permanent en cours de connexion…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN permanent connecté"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"VPN permanent déconnecté"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Déconnecté du VPN permanent"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Erreur du VPN permanent"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Appuyer pour configurer"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Modifier les paramètres réseau ou VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Sélectionner un fichier"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Aucun fichier sélectionné"</string> <string name="reset" msgid="2448168080964209908">"Réinitialiser"</string> diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml index 7818166f15b2..ea93ca46f6e6 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demostración comercial"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"conexión USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Aplicacións que se executan en segundo plano"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"Estase executando en segundo plano a aplicación <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"Estanse executando en segundo plano <xliff:g id="NUMBER">%1$d</xliff:g> aplicacións"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Aplicacións que consumen batería"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"A aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> está consumindo batería"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicacións están consumindo batería"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Toca para obter información sobre o uso de datos e a batería"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string> @@ -315,7 +315,7 @@ <string name="permlab_receiveMms" msgid="1821317344668257098">"recibir mensaxes de texto (MMS)"</string> <string name="permdesc_receiveMms" msgid="533019437263212260">"Permite á aplicación recibir e procesar mensaxes MMS. Isto significa que a aplicación pode supervisar ou eliminar mensaxes enviadas ao teu dispositivo sen mostrarchas."</string> <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ler mensaxes de difusión móbil"</string> - <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite á aplicación ler mensaxes de difusión móbil recibidas polo teu dispositivo. As alertas de difusión móbil entréganse nalgunhas situacións para avisar de situacións de emerxencia. É posible que aplicacións maliciosas afecten ao rendemento ou funcionamento do teu dispositivo cando se recibe unha difusión móbil de emerxencia."</string> + <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Permite á aplicación ler mensaxes de difusión móbil recibidas polo teu dispositivo. As alertas de difusión móbil envíanse nalgunhas localizacións para avisar de situacións de emerxencia. É posible que aplicacións maliciosas afecten ao rendemento ou funcionamento do teu dispositivo cando se recibe unha difusión móbil de emerxencia."</string> <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ler feeds subscritos"</string> <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Permite á aplicación obter detalles acerca dos feeds sincronizados actualmente."</string> <string name="permlab_sendSms" msgid="7544599214260982981">"enviar e consultar mensaxes de SMS"</string> @@ -382,7 +382,7 @@ <string name="permdesc_writeCalendar" product="tablet" msgid="1675270619903625982">"Esta aplicación pode engadir, quitar ou cambiar eventos do calendario almacenados na túa tableta. Tamén pode enviar mensaxes que parezan dos propietarios do calendario e cambiar eventos sen comunicárllelo aos propietarios."</string> <string name="permdesc_writeCalendar" product="tv" msgid="9017809326268135866">"Esta aplicación pode engadir, quitar ou cambiar eventos do calendario almacenados na túa televisión. Tamén pode enviar mensaxes que parezan dos propietarios do calendario e cambiar eventos sen comunicárllelo aos propietarios."</string> <string name="permdesc_writeCalendar" product="default" msgid="7592791790516943173">"Esta aplicación pode engadir, quitar ou cambiar eventos do calendario almacenados no teu teléfono. Tamén pode enviar mensaxes que parezan dos propietarios do calendario e cambiar eventos sen comunicárllelo aos propietarios."</string> - <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"acceder a comandos adicionais do provedor de situación"</string> + <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"acceder a comandos adicionais do provedor de localización"</string> <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permite á aplicación acceder a comandos adicionais de fornecedor de localizacións. É posible que isto provoque que a aplicación interfira co funcionamento do GPS ou doutras fontes da localización."</string> <string name="permlab_accessFineLocation" msgid="251034415460950944">"acceder á localización precisa (baseada no GPS e na rede)"</string> <string name="permdesc_accessFineLocation" msgid="5821994817969957884">"Esta aplicación pode obter a túa localización a partir do GPS ou de fontes de localización de rede como torres de telecomunicacións e redes wifi. Para que a aplicación poida utilizar os servizos de localización, deben estar activados e dispoñibles no teu teléfono. Ten en conta que con esta acción pode aumentar o consumo de batería."</string> @@ -580,7 +580,7 @@ <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"Desactivar algunhas funcións de bloqueo da pantalla"</string> <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Impide o uso dalgunhas funcións de bloqueo da pantalla."</string> <string-array name="phoneTypes"> - <item msgid="8901098336658710359">"Particular"</item> + <item msgid="8901098336658710359">"Casa"</item> <item msgid="869923650527136615">"Móbil"</item> <item msgid="7897544654242874543">"Traballo"</item> <item msgid="1103601433382158155">"Fax do traballo"</item> @@ -590,7 +590,7 @@ <item msgid="9192514806975898961">"Personalizado"</item> </string-array> <string-array name="emailAddressTypes"> - <item msgid="8073994352956129127">"Particular"</item> + <item msgid="8073994352956129127">"Casa"</item> <item msgid="7084237356602625604">"Traballo"</item> <item msgid="1112044410659011023">"Outros"</item> <item msgid="2374913952870110618">"Personalizado"</item> @@ -602,7 +602,7 @@ <item msgid="4932682847595299369">"Personalizado"</item> </string-array> <string-array name="imAddressTypes"> - <item msgid="1738585194601476694">"Particular"</item> + <item msgid="1738585194601476694">"Casa"</item> <item msgid="1359644565647383708">"Traballo"</item> <item msgid="7868549401053615677">"Outros"</item> <item msgid="3145118944639869809">"Personalizado"</item> @@ -623,7 +623,7 @@ <item msgid="1648797903785279353">"Jabber"</item> </string-array> <string name="phoneTypeCustom" msgid="1644738059053355820">"Personalizado"</string> - <string name="phoneTypeHome" msgid="2570923463033985887">"Particular"</string> + <string name="phoneTypeHome" msgid="2570923463033985887">"Casa"</string> <string name="phoneTypeMobile" msgid="6501463557754751037">"Móbil"</string> <string name="phoneTypeWork" msgid="8863939667059911633">"Traballo"</string> <string name="phoneTypeFaxWork" msgid="3517792160008890912">"Fax do traballo"</string> @@ -648,16 +648,16 @@ <string name="eventTypeAnniversary" msgid="3876779744518284000">"Aniversario"</string> <string name="eventTypeOther" msgid="7388178939010143077">"Outros"</string> <string name="emailTypeCustom" msgid="8525960257804213846">"Personalizado"</string> - <string name="emailTypeHome" msgid="449227236140433919">"Particular"</string> + <string name="emailTypeHome" msgid="449227236140433919">"Casa"</string> <string name="emailTypeWork" msgid="3548058059601149973">"Traballo"</string> <string name="emailTypeOther" msgid="2923008695272639549">"Outro"</string> <string name="emailTypeMobile" msgid="119919005321166205">"Móbil"</string> <string name="postalTypeCustom" msgid="8903206903060479902">"Personalizado"</string> - <string name="postalTypeHome" msgid="8165756977184483097">"Particular"</string> + <string name="postalTypeHome" msgid="8165756977184483097">"Casa"</string> <string name="postalTypeWork" msgid="5268172772387694495">"Traballo"</string> <string name="postalTypeOther" msgid="2726111966623584341">"Outro"</string> <string name="imTypeCustom" msgid="2074028755527826046">"Personalizado"</string> - <string name="imTypeHome" msgid="6241181032954263892">"Particular"</string> + <string name="imTypeHome" msgid="6241181032954263892">"Casa"</string> <string name="imTypeWork" msgid="1371489290242433090">"Traballo"</string> <string name="imTypeOther" msgid="5377007495735915478">"Outro"</string> <string name="imProtocolCustom" msgid="6919453836618749992">"Personalizado"</string> @@ -680,16 +680,16 @@ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Parella de feito"</string> <string name="relationTypeFather" msgid="5228034687082050725">"Pai"</string> <string name="relationTypeFriend" msgid="7313106762483391262">"Amigo/a"</string> - <string name="relationTypeManager" msgid="6365677861610137895">"Xestor"</string> + <string name="relationTypeManager" msgid="6365677861610137895">"Xefe/a"</string> <string name="relationTypeMother" msgid="4578571352962758304">"Nai"</string> - <string name="relationTypeParent" msgid="4755635567562925226">"Pai ou nai"</string> - <string name="relationTypePartner" msgid="7266490285120262781">"Socio"</string> + <string name="relationTypeParent" msgid="4755635567562925226">"Pai/nai"</string> + <string name="relationTypePartner" msgid="7266490285120262781">"Socio/a"</string> <string name="relationTypeReferredBy" msgid="101573059844135524">"Recomendado por"</string> <string name="relationTypeRelative" msgid="1799819930085610271">"Parente"</string> <string name="relationTypeSister" msgid="1735983554479076481">"Irmá"</string> <string name="relationTypeSpouse" msgid="394136939428698117">"Cónxuxe"</string> <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Personalizado"</string> - <string name="sipAddressTypeHome" msgid="6093598181069359295">"Particular"</string> + <string name="sipAddressTypeHome" msgid="6093598181069359295">"Casa"</string> <string name="sipAddressTypeWork" msgid="6920725730797099047">"Traballo"</string> <string name="sipAddressTypeOther" msgid="4408436162950119849">"Outro"</string> <string name="quick_contacts_not_available" msgid="746098007828579688">"Non se atopou ningunha aplicación para ver este contacto."</string> @@ -1266,7 +1266,7 @@ <string name="ime_action_send" msgid="2316166556349314424">"Enviar"</string> <string name="ime_action_next" msgid="3138843904009813834">"Seguinte"</string> <string name="ime_action_done" msgid="8971516117910934605">"Feito"</string> - <string name="ime_action_previous" msgid="1443550039250105948">"Ant"</string> + <string name="ime_action_previous" msgid="1443550039250105948">"Ant."</string> <string name="ime_action_default" msgid="2840921885558045721">"Executar"</string> <string name="dial_number_using" msgid="5789176425167573586">"Marcar número\nutilizando o <xliff:g id="NUMBER">%s</xliff:g>"</string> <string name="create_contact_using" msgid="4947405226788104538">"Crear contacto\na partir de <xliff:g id="NUMBER">%s</xliff:g>"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Conectado a <xliff:g id="SESSION">%s</xliff:g>. Toca aquí para xestionar a rede."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN sempre activada conectándose..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN sempre activada conectada"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Desconectouse a VPN sempre activada"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Desconectácheste da VPN sempre activada"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Erro na VPN sempre activada"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tocar para configurar"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Cambia a configuración da rede ou da VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Escoller un ficheiro"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Non se seleccionou ningún ficheiro"</string> <string name="reset" msgid="2448168080964209908">"Restablecer"</string> @@ -1604,7 +1604,7 @@ </plurals> <string name="restr_pin_try_later" msgid="973144472490532377">"Téntao de novo máis tarde"</string> <string name="immersive_cling_title" msgid="8394201622932303336">"Vendo pantalla completa"</string> - <string name="immersive_cling_description" msgid="3482371193207536040">"Para saír, pasa o dedo cara abaixo desde arriba."</string> + <string name="immersive_cling_description" msgid="3482371193207536040">"Para saír, pasa o dedo cara abaixo desde a parte superior."</string> <string name="immersive_cling_positive" msgid="5016839404568297683">"De acordo"</string> <string name="done_label" msgid="2093726099505892398">"Feito"</string> <string name="hour_picker_description" msgid="6698199186859736512">"Control desprazable circular das horas"</string> @@ -1725,7 +1725,7 @@ <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"Toca para ver os ficheiros"</string> <string name="pin_target" msgid="3052256031352291362">"Fixar"</string> <string name="unpin_target" msgid="3556545602439143442">"Soltar"</string> - <string name="app_info" msgid="6856026610594615344">"Información de aplicacións"</string> + <string name="app_info" msgid="6856026610594615344">"Info. da aplicación"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="demo_starting_message" msgid="5268556852031489931">"Iniciando demostración…"</string> <string name="demo_restarting_message" msgid="952118052531642451">"Restablecendo dispositivo…"</string> @@ -1747,7 +1747,7 @@ <string name="time_picker_header_text" msgid="143536825321922567">"Definir hora"</string> <string name="time_picker_input_error" msgid="7574999942502513765">"Introduce unha hora válida"</string> <string name="time_picker_prompt_label" msgid="7588093983899966783">"Escribe a hora"</string> - <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Cambia ao modo de entrada de texto para introducir a hora."</string> + <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Cambia ao modo de introdución de texto para introducir a hora."</string> <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Cambiar ao modo de reloxo para introducir a hora."</string> <string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Opcións de autocompletar"</string> <string name="autofill_save_accessibility_title" msgid="7244365268417107822">"Garda a información no servizo Autocompletar"</string> diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index 20c1a7e9389b..f9041ca0cbe8 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -127,9 +127,9 @@ <item msgid="4397097370387921767">"%s વાઇ-ફાઇ કૉલિંગ"</item> </string-array> <string name="wifi_calling_off_summary" msgid="8720659586041656098">"બંધ"</string> - <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi પસંદ કર્યું"</string> + <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"વાઇ-ફાઇ પસંદ કર્યું"</string> <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"મોબાઇલને પસંદગી"</string> - <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"ફક્ત Wi-Fi"</string> + <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"ફક્ત વાઇ-ફાઇ"</string> <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ફોરવર્ડ કર્યો નથી"</string> <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string> <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="TIME_DELAY">{2}</xliff:g> સેકંડ પછી <xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string> @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"ચેતવણીઓ"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"રિટેલ ડેમો"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB કનેક્શન"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"પૃષ્ઠભૂમિમાં ચાલી રહેલ ઍપ્લિકેશનો"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> પૃષ્ઠભૂમિમાં ચાલી રહી છે"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> ઍપ્લિકેશન પૃષ્ઠભૂમિમાં ચાલી રહી છે"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"ઍપ બૅટરીનો વપરાશ કરી રહ્યાં છે"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> બૅટરીનો ઉપયોગ કરી રહ્યું છે"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> ઍપ બૅટરીનો ઉપયોગ કરી રહ્યાં છે"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"બૅટરી અને ડેટા વપરાશ વિશેની વિગતો માટે ટૅપ કરો"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"સુરક્ષિત મોડ"</string> @@ -335,7 +335,7 @@ <string name="permlab_enableCarMode" msgid="5684504058192921098">"કાર મોડ સક્ષમ કરો"</string> <string name="permdesc_enableCarMode" msgid="4853187425751419467">"એપ્લિકેશનને કાર મોડ સક્ષમ કરવાની મંજૂરી આપે છે."</string> <string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"અન્ય ઍપ્લિકેશનો બંધ કરો"</string> - <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"એપ્લિકેશનને અન્ય ઍપ્લિકેશનોની પૃષ્ઠભૂમિ પ્રક્રિયા સમાપ્ત કરવાની મંજૂરી આપે છે. આનાથી અન્ય ઍપ્લિકેશનો ચાલવાથી બંધ થઈ શકે છે."</string> + <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"એપ્લિકેશનને અન્ય ઍપ્લિકેશનોની બૅકગ્રાઉન્ડ પ્રક્રિયા સમાપ્ત કરવાની મંજૂરી આપે છે. આનાથી અન્ય ઍપ્લિકેશનો ચાલવાથી બંધ થઈ શકે છે."</string> <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"આ ઍપ્લિકેશન, અન્ય ઍપ્લિકેશનોની ટોચ પર દેખાઈ શકે છે"</string> <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"આ ઍપ્લિકેશન, અન્ય ઍપ્લિકેશોની ટોચ પર અથવા સ્ક્રીનના અન્ય ભાગોમાં દેખાઈ શકે છે. આ સામાન્ય ઍપ્લિકેશન વપરાશમાં હસ્તક્ષેપ કરી શકે છે અને અન્ય ઍપ્લિકેશનોની દેખાવાની રીતને બદલી શકે છે."</string> <string name="permlab_runInBackground" msgid="7365290743781858803">"પૃષ્ઠભૂમિમાં ચલાવો"</string> @@ -385,11 +385,11 @@ <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"વધારાના સ્થાન પ્રદાતા આદેશોને ઍક્સેસ કરો"</string> <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"એપ્લિકેશનને વધારાના સ્થાન પ્રદાતા આદેશોને ઍક્સેસ કરવાની મંજૂરી આપે છે. આ એપ્લિકેશનને GPS અથવા અન્ય સ્થાન સ્રોતોના ઓપરેશનમાં દખલ કરવાની મંજૂરી આપી શકે છે."</string> <string name="permlab_accessFineLocation" msgid="251034415460950944">"નિશ્ચિત સ્થાન ઍક્સેસ કરો (GPS અને નેટવર્ક-આધારિત)"</string> - <string name="permdesc_accessFineLocation" msgid="5821994817969957884">"આ ઍપ્લિકેશન, GPS અથવા સેલ ટાવર્સ અને Wi-Fi નેટવર્ક્સ જેવા નેટવર્ક સ્રોતોના આધારે તમારું સ્થાન મેળવી શકે છે. ઍપ્લિકેશન દ્વારા આ સ્થાન સેવાઓનો ઉપયોગ કરવામાં સમર્થ થવા માટે તમારા ફોન પર આ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે. આ બૅટરી વપરાશ વધારી શકે છે."</string> + <string name="permdesc_accessFineLocation" msgid="5821994817969957884">"આ ઍપ્લિકેશન, GPS અથવા સેલ ટાવર્સ અને વાઇ-ફાઇ નેટવર્ક્સ જેવા નેટવર્ક સ્રોતોના આધારે તમારું સ્થાન મેળવી શકે છે. ઍપ્લિકેશન દ્વારા આ સ્થાન સેવાઓનો ઉપયોગ કરવામાં સમર્થ થવા માટે તમારા ફોન પર આ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે. આ બૅટરી વપરાશ વધારી શકે છે."</string> <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"અંદાજિત સ્થાન ઍક્સેસ કરો (નેટવર્ક-આધારિત)"</string> - <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"આ ઍપ્લિકેશન, સેલ ટાવર્સ અને Wi-Fi નેટવર્ક્સ જેવા નેટવર્ક સ્રોતોના આધારે તમારું સ્થાન મેળવી શકે છે. ઍપ્લિકેશન દ્વારા આ સ્થાન સેવાઓનો ઉપયોગ કરવામાં સમર્થ થવા માટે તમારા ટેબ્લેટ પર આ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે."</string> - <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"આ ઍપ્લિકેશન, સેલ ટાવર્સ અને Wi-Fi નેટવર્ક્સ જેવા નેટવર્ક સ્રોતોના આધારે તમારું સ્થાન મેળવી શકે છે. ઍપ્લિકેશન દ્વારા આ સ્થાન સેવાઓનો ઉપયોગ કરવામાં સમર્થ થવા માટે તમારા ટીવી પર આ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે."</string> - <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"આ ઍપ્લિકેશન, સેલ ટાવર્સ અને Wi-Fi નેટવર્ક્સ જેવા નેટવર્ક સ્રોતોના આધારે તમારું સ્થાન મેળવી શકે છે. ઍપ્લિકેશન દ્વારા આ સ્થાન સેવાઓનો ઉપયોગ કરવામાં સમર્થ થવા માટે તમારા ફોન પર આ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે."</string> + <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"આ ઍપ્લિકેશન, સેલ ટાવર્સ અને વાઇ-ફાઇ નેટવર્ક્સ જેવા નેટવર્ક સ્રોતોના આધારે તમારું સ્થાન મેળવી શકે છે. ઍપ્લિકેશન દ્વારા આ સ્થાન સેવાઓનો ઉપયોગ કરવામાં સમર્થ થવા માટે તમારા ટેબ્લેટ પર આ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે."</string> + <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"આ ઍપ્લિકેશન, સેલ ટાવર્સ અને વાઇ-ફાઇ નેટવર્ક્સ જેવા નેટવર્ક સ્રોતોના આધારે તમારું સ્થાન મેળવી શકે છે. ઍપ્લિકેશન દ્વારા આ સ્થાન સેવાઓનો ઉપયોગ કરવામાં સમર્થ થવા માટે તમારા ટીવી પર આ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે."</string> + <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"આ ઍપ્લિકેશન, સેલ ટાવર્સ અને વાઇ-ફાઇ નેટવર્ક્સ જેવા નેટવર્ક સ્રોતોના આધારે તમારું સ્થાન મેળવી શકે છે. ઍપ્લિકેશન દ્વારા આ સ્થાન સેવાઓનો ઉપયોગ કરવામાં સમર્થ થવા માટે તમારા ફોન પર આ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે."</string> <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"તમારી ઑડિઓ સેટિંગ્સ બદલો"</string> <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"એપ્લિકેશનને વૈશ્વિક ઑડિઓ સેટિંગ્સને સંશોધિત કરવાની મંજૂરી આપે છે, જેમ કે વોલ્યુમ અને આઉટપુટ માટે કયા સ્પીકરનો ઉપયોગ કરવો."</string> <string name="permlab_recordAudio" msgid="3876049771427466323">"ઑડિઓ રેકોર્ડ કરવાની"</string> @@ -440,18 +440,18 @@ <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"એપ્લિકેશનને નેટવર્ક કનેક્ટિવિટીની સ્થિતિ બદલવાની મંજૂરી આપે છે."</string> <string name="permlab_changeTetherState" msgid="5952584964373017960">"ટિથર કરેલ કનેક્ટિવિટી બદલો"</string> <string name="permdesc_changeTetherState" msgid="1524441344412319780">"એપ્લિકેશનને ટિથર્ડ નેટવર્ક કનેક્ટિવિટીની સ્થિતિ બદલવાની મંજૂરી આપે છે."</string> - <string name="permlab_accessWifiState" msgid="5202012949247040011">"Wi-Fi કનેક્શન્સ જુઓ"</string> - <string name="permdesc_accessWifiState" msgid="5002798077387803726">"એપ્લિકેશનને Wi-Fi નેટવર્કિંગ વિશેની માહિતી જોવાની મંજૂરી આપે છે, જેમ કે Wi-Fi સક્ષમ છે કે કેમ અને કનેક્ટ થયેલ Wi-Fi ઉપકરણોના નામ."</string> - <string name="permlab_changeWifiState" msgid="6550641188749128035">"Wi-Fi થી કનેક્ટ અને ડિસ્કનેક્ટ કરો"</string> - <string name="permdesc_changeWifiState" msgid="7137950297386127533">"એપ્લિકેશનને Wi-Fi ઍક્સેસ બિંદુઓથી કનેક્ટ થવા અને ડિસ્કનેક્ટ થવાની અને Wi-Fi નેટવર્ક્સ માટે ઉપકરણ ગોઠવણી પર ફેરફારો કરવાની મંજૂરી આપે છે."</string> - <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"Wi-Fi મલ્ટિકાસ્ટ રિસેપ્શનને મંજૂરી આપો"</string> - <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"એપ્લિકેશનને ફક્ત તમારા ટેબ્લેટ પર નહીં, પણ મલ્ટિકાસ્ટ સરનામાંનો ઉપયોગ કરીને Wi-Fi નેટવર્ક પરના તમામ ઉપકરણોને મોકલાયેલ પૅકેટ્સ પ્રાપ્ત કરવાની મંજૂરી આપે છે. તે બિન-મલ્ટિકાસ્ટ મોડ કરતાં વધુ પાવર વાપરે છે."</string> - <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"એપ્લિકેશનને ફક્ત તમારા ટીવી પર નહીં, પણ મલ્ટિકાસ્ટ સરનામાંનો ઉપયોગ કરીને Wi-Fi નેટવર્ક પરના તમામ ઉપકરણોને મોકલાયેલ પૅકેટ્સ પ્રાપ્ત કરવાની મંજૂરી આપે છે. તે બિન-મલ્ટિકાસ્ટ મોડ કરતાં વધુ પાવર વાપરે છે."</string> - <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"એપ્લિકેશનને ફક્ત તમારા ફોન પર નહીં, પણ મલ્ટિકાસ્ટ સરનામાંનો ઉપયોગ કરીને Wi-Fi નેટવર્ક પર તમામ ઉપકરણોને મોકલાયેલ પૅકેટ્સ પ્રાપ્ત કરવાની મંજૂરી આપે છે. તે બિન-મલ્ટિકાસ્ટ મોડ કરતાં વધુ પાવર વાપરે છે."</string> - <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"Bluetooth સેટિંગ્સ ઍક્સેસ કરો"</string> - <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"એપ્લિકેશનને સ્થાનિક Bluetooth ટેબ્લેટ ગોઠવવાની અને રિમોટ ઉપકરણો શોધવા અને તેમની સાથે જોડી કરવાની મંજૂરી આપે છે."</string> - <string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"એપ્લિકેશનને સ્થાનિક Bluetooth ટીવી ગોઠવવાની અને રિમોટ ઉપકરણો શોધવા અને તેમની સાથે જોડી કરવાની મંજૂરી આપે છે."</string> - <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"એપ્લિકેશનને સ્થાનિક Bluetooth ફોન ગોઠવવાની અને રિમોટ ઉપકરણો શોધવા અને તેમની સાથે જોડી કરવાની મંજૂરી આપે છે."</string> + <string name="permlab_accessWifiState" msgid="5202012949247040011">"વાઇ-ફાઇ કનેક્શન્સ જુઓ"</string> + <string name="permdesc_accessWifiState" msgid="5002798077387803726">"એપ્લિકેશનને વાઇ-ફાઇ નેટવર્કિંગ વિશેની માહિતી જોવાની મંજૂરી આપે છે, જેમ કે વાઇ-ફાઇ સક્ષમ છે કે કેમ અને કનેક્ટ થયેલ વાઇ-ફાઇ ઉપકરણોના નામ."</string> + <string name="permlab_changeWifiState" msgid="6550641188749128035">"વાઇ-ફાઇ થી કનેક્ટ અને ડિસ્કનેક્ટ કરો"</string> + <string name="permdesc_changeWifiState" msgid="7137950297386127533">"એપ્લિકેશનને વાઇ-ફાઇ ઍક્સેસ બિંદુઓથી કનેક્ટ થવા અને ડિસ્કનેક્ટ થવાની અને વાઇ-ફાઇ નેટવર્ક્સ માટે ઉપકરણ ગોઠવણી પર ફેરફારો કરવાની મંજૂરી આપે છે."</string> + <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"વાઇ-ફાઇ મલ્ટિકાસ્ટ રિસેપ્શનને મંજૂરી આપો"</string> + <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"એપ્લિકેશનને ફક્ત તમારા ટેબ્લેટ પર નહીં, પણ મલ્ટિકાસ્ટ સરનામાંનો ઉપયોગ કરીને વાઇ-ફાઇ નેટવર્ક પરના તમામ ઉપકરણોને મોકલાયેલ પૅકેટ્સ પ્રાપ્ત કરવાની મંજૂરી આપે છે. તે બિન-મલ્ટિકાસ્ટ મોડ કરતાં વધુ પાવર વાપરે છે."</string> + <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"એપ્લિકેશનને ફક્ત તમારા ટીવી પર નહીં, પણ મલ્ટિકાસ્ટ સરનામાંનો ઉપયોગ કરીને વાઇ-ફાઇ નેટવર્ક પરના તમામ ઉપકરણોને મોકલાયેલ પૅકેટ્સ પ્રાપ્ત કરવાની મંજૂરી આપે છે. તે બિન-મલ્ટિકાસ્ટ મોડ કરતાં વધુ પાવર વાપરે છે."</string> + <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"એપ્લિકેશનને ફક્ત તમારા ફોન પર નહીં, પણ મલ્ટિકાસ્ટ સરનામાંનો ઉપયોગ કરીને વાઇ-ફાઇ નેટવર્ક પર તમામ ઉપકરણોને મોકલાયેલ પૅકેટ્સ પ્રાપ્ત કરવાની મંજૂરી આપે છે. તે બિન-મલ્ટિકાસ્ટ મોડ કરતાં વધુ પાવર વાપરે છે."</string> + <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"બ્લૂટૂથ સેટિંગ્સ ઍક્સેસ કરો"</string> + <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"એપ્લિકેશનને સ્થાનિક બ્લૂટૂથ ટેબ્લેટ ગોઠવવાની અને રિમોટ ઉપકરણો શોધવા અને તેમની સાથે જોડી કરવાની મંજૂરી આપે છે."</string> + <string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"એપ્લિકેશનને સ્થાનિક બ્લૂટૂથ ટીવી ગોઠવવાની અને રિમોટ ઉપકરણો શોધવા અને તેમની સાથે જોડી કરવાની મંજૂરી આપે છે."</string> + <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"એપ્લિકેશનને સ્થાનિક બ્લૂટૂથ ફોન ગોઠવવાની અને રિમોટ ઉપકરણો શોધવા અને તેમની સાથે જોડી કરવાની મંજૂરી આપે છે."</string> <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAX થી કનેક્ટ અને ડિસ્કનેક્ટ કરો"</string> <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"એપ્લિકેશનને WiMAX સક્ષમ છે કે કેમ અને કનેક્ટ થયેલ છે તે કોઈપણ WiMAX નેટવર્ક્સ વિશેની માહિતી નિર્ધારિત કરવાની મંજૂરી આપે છે."</string> <string name="permlab_changeWimaxState" msgid="340465839241528618">"WiMAX સ્થિતિ બદલો"</string> @@ -459,9 +459,9 @@ <string name="permdesc_changeWimaxState" product="tv" msgid="6022307083934827718">"ટીવીને WiMAX નેટવર્ક્સ પર કનેક્ટ કરવાની અને ટીવીને તેનાથી ડિસ્કનેક્ટ કરવાની મંજૂરી એપ્લિકેશનને આપે છે."</string> <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"ફોનને WiMAX નેટવર્ક્સ પર કનેક્ટ કરવાની અને ફોનને તેનાથી ડિસ્કનેક્ટ કરવાની મંજૂરી એપ્લિકેશનને આપે છે."</string> <string name="permlab_bluetooth" msgid="6127769336339276828">"બ્લૂટૂથ ઉપકરણો સાથે જોડાણ બનાવો"</string> - <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"એપ્લિકેશનને ટેબ્લેટ પર Bluetooth ની ગોઠવણી જોવાની અને જોડી કરેલ ઉપકરણો સાથે કનેક્શન્સ કરવાની અને સ્વીકારવાની મંજૂરી આપે છે."</string> - <string name="permdesc_bluetooth" product="tv" msgid="3974124940101104206">"એપ્લિકેશનને ટીવી પર Bluetooth ની ગોઠવણી જોવાની અને જોડી કરેલ ઉપકરણો સાથે કનેક્શન્સ કરવાની અને સ્વીકારવાની મંજૂરી આપે છે."</string> - <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"એપ્લિકેશનને ફોન પર Bluetooth ની ગોઠવણી જોવાની અને જોડી કરેલ ઉપકરણો સાથે કનેક્શન્સ કરવાની અને સ્વીકારવાની મંજૂરી આપે છે."</string> + <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"એપ્લિકેશનને ટેબ્લેટ પર બ્લૂટૂથ ની ગોઠવણી જોવાની અને જોડી કરેલ ઉપકરણો સાથે કનેક્શન્સ કરવાની અને સ્વીકારવાની મંજૂરી આપે છે."</string> + <string name="permdesc_bluetooth" product="tv" msgid="3974124940101104206">"એપ્લિકેશનને ટીવી પર બ્લૂટૂથ ની ગોઠવણી જોવાની અને જોડી કરેલ ઉપકરણો સાથે કનેક્શન્સ કરવાની અને સ્વીકારવાની મંજૂરી આપે છે."</string> + <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"એપ્લિકેશનને ફોન પર બ્લૂટૂથ ની ગોઠવણી જોવાની અને જોડી કરેલ ઉપકરણો સાથે કનેક્શન્સ કરવાની અને સ્વીકારવાની મંજૂરી આપે છે."</string> <string name="permlab_nfc" msgid="4423351274757876953">"નિઅર ફીલ્ડ કમ્યુનિકેશન નિયંત્રિત કરો"</string> <string name="permdesc_nfc" msgid="7120611819401789907">"ઍપ્લિકેશનને નિઅર ફીલ્ડ કમ્યુનિકેશન (NFC) ટૅગ, કાર્ડ અને રીડર સાથે સંચાર કરવાની મંજૂરી આપે છે."</string> <string name="permlab_disableKeyguard" msgid="3598496301486439258">"તમારું સ્ક્રીન લૉક અક્ષમ કરો"</string> @@ -1074,14 +1074,14 @@ <string name="sendText" msgid="5209874571959469142">"ટેક્સ્ટ માટે ક્રિયા પસંદ કરો"</string> <string name="volume_ringtone" msgid="6885421406845734650">"રિંગર વૉલ્યૂમ"</string> <string name="volume_music" msgid="5421651157138628171">"મીડિયા વૉલ્યૂમ"</string> - <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"Bluetooth મારફતે ચાલી રહ્યું છે"</string> + <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"બ્લૂટૂથ મારફતે ચાલી રહ્યું છે"</string> <string name="volume_music_hint_silent_ringtone_selected" msgid="8310739960973156272">"સાઇલેન્ટ રિંગટોન સેટ કરી"</string> <string name="volume_call" msgid="3941680041282788711">"ઇન-કૉલ વૉલ્યૂમ"</string> - <string name="volume_bluetooth_call" msgid="2002891926351151534">"Bluetooth ઇન-કૉલ વોલ્યુમ"</string> + <string name="volume_bluetooth_call" msgid="2002891926351151534">"બ્લૂટૂથ ઇન-કૉલ વોલ્યુમ"</string> <string name="volume_alarm" msgid="1985191616042689100">"એલાર્મ વૉલ્યૂમ"</string> <string name="volume_notification" msgid="2422265656744276715">"સૂચના વૉલ્યૂમ"</string> <string name="volume_unknown" msgid="1400219669770445902">"વૉલ્યૂમ"</string> - <string name="volume_icon_description_bluetooth" msgid="6538894177255964340">"Bluetooth વૉલ્યૂમ"</string> + <string name="volume_icon_description_bluetooth" msgid="6538894177255964340">"બ્લૂટૂથ વૉલ્યૂમ"</string> <string name="volume_icon_description_ringer" msgid="3326003847006162496">"રિંગટોન વોલ્યુમ"</string> <string name="volume_icon_description_incall" msgid="8890073218154543397">"કૉલ વોલ્યુમ"</string> <string name="volume_icon_description_media" msgid="4217311719665194215">"મીડિયા વોલ્યુમ"</string> @@ -1094,46 +1094,46 @@ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"સૂચના ધ્વનિઓ"</string> <string name="ringtone_unknown" msgid="3914515995813061520">"અજાણી"</string> <plurals name="wifi_available" formatted="false" msgid="7900333017752027322"> - <item quantity="one">Wi-Fi નેટવર્ક્સ ઉપલબ્ધ</item> - <item quantity="other">Wi-Fi નેટવર્ક્સ ઉપલબ્ધ</item> + <item quantity="one">વાઇ-ફાઇ નેટવર્ક્સ ઉપલબ્ધ</item> + <item quantity="other">વાઇ-ફાઇ નેટવર્ક્સ ઉપલબ્ધ</item> </plurals> <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606"> - <item quantity="one">ખુલ્લા Wi-Fi નેટવર્ક્સ ઉપલબ્ધ છે</item> - <item quantity="other">ખુલ્લા Wi-Fi નેટવર્ક્સ ઉપલબ્ધ છે</item> + <item quantity="one">ખુલ્લા વાઇ-ફાઇ નેટવર્ક્સ ઉપલબ્ધ છે</item> + <item quantity="other">ખુલ્લા વાઇ-ફાઇ નેટવર્ક્સ ઉપલબ્ધ છે</item> </plurals> - <string name="wifi_available_title" msgid="3817100557900599505">"ખુલ્લા Wi‑Fi નેટવર્ક સાથે કનેક્ટ કરો"</string> - <string name="wifi_available_title_connecting" msgid="1557292688310330032">"ખુલ્લા Wi‑Fi નેટવર્ક સાથે કનેક્ટ કરી રહ્યાં છીએ"</string> - <string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi નેટવર્ક સાથે કનેક્ટ કર્યુ"</string> - <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi નેટવર્ક સાથે કનેક્ટ કરી શકાયું નથી"</string> + <string name="wifi_available_title" msgid="3817100557900599505">"ખુલ્લા વાઇ-ફાઇ નેટવર્ક સાથે કનેક્ટ કરો"</string> + <string name="wifi_available_title_connecting" msgid="1557292688310330032">"ખુલ્લા વાઇ-ફાઇ નેટવર્ક સાથે કનેક્ટ કરી રહ્યાં છીએ"</string> + <string name="wifi_available_title_connected" msgid="7542672851522241548">"વાઇ-ફાઇ નેટવર્ક સાથે કનેક્ટ કર્યુ"</string> + <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"વાઇ-ફાઇ નેટવર્ક સાથે કનેક્ટ કરી શકાયું નથી"</string> <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"બધા નેટવર્ક જોવા ટૅપ કરો"</string> <string name="wifi_available_action_connect" msgid="2635699628459488788">"કનેક્ટ કરો"</string> <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"બધા નેટવર્ક"</string> - <string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi નેટવર્ક પર સાઇન ઇન કરો"</string> + <string name="wifi_available_sign_in" msgid="9157196203958866662">"વાઇ-ફાઇ નેટવર્ક પર સાઇન ઇન કરો"</string> <string name="network_available_sign_in" msgid="1848877297365446605">"નેટવર્ક પર સાઇન ઇન કરો"</string> <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) --> <skip /> - <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi ને કોઈ ઇન્ટરનેટ ઍક્સેસ નથી"</string> + <string name="wifi_no_internet" msgid="8451173622563841546">"વાઇ-ફાઇ ને કોઈ ઇન્ટરનેટ ઍક્સેસ નથી"</string> <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"વિકલ્પો માટે ટૅપ કરો"</string> <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> પર સ્વિચ કર્યું"</string> <string name="network_switch_metered_detail" msgid="5325661434777870353">"જ્યારે <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> પાસે કોઈ ઇન્ટરનેટ ઍક્સેસ ન હોય ત્યારે ઉપકરણ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> નો ઉપયોગ કરે છે. શુલ્ક લાગુ થઈ શકે છે."</string> <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> પરથી <xliff:g id="NEW_NETWORK">%2$s</xliff:g> પર સ્વિચ કર્યું"</string> <string-array name="network_switch_type_name"> <item msgid="3979506840912951943">"મોબાઇલ ડેટા"</item> - <item msgid="75483255295529161">"Wi-Fi"</item> - <item msgid="6862614801537202646">"Bluetooth"</item> + <item msgid="75483255295529161">"વાઇ-ફાઇ"</item> + <item msgid="6862614801537202646">"બ્લૂટૂથ"</item> <item msgid="5447331121797802871">"ઇથરનેટ"</item> <item msgid="8257233890381651999">"VPN"</item> </string-array> <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"અજાણ્યો નેટવર્ક પ્રકાર"</string> - <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi સાથે કનેક્ટ કરી શકાયું નથી"</string> + <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"વાઇ-ફાઇ સાથે કનેક્ટ કરી શકાયું નથી"</string> <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" નબળું ઇન્ટરનેટ કનેક્શન ધરાવે છે."</string> <string name="wifi_connect_alert_title" msgid="8455846016001810172">"કનેક્શનની મંજૂરી આપીએ?"</string> <string name="wifi_connect_alert_message" msgid="6451273376815958922">"%1$s ઍપ્લિકેશન Wifi નેટવર્ક %2$s થી કનેક્ટ થવા માગે છે"</string> <string name="wifi_connect_default_application" msgid="7143109390475484319">"ઍપ્લિકેશન"</string> - <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string> - <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi Direct પ્રારંભ કરો. આ Wi-Fi ક્લાઇન્ટ/હોટસ્પોટને બંધ કરશે."</string> - <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Wi-Fi Direct પ્રારંભ કરી શકાયું નથી."</string> - <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct ચાલુ છે"</string> + <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"વાઇ-ફાઇ ડાઇરેક્ટ"</string> + <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"વાઇ-ફાઇ ડાઇરેક્ટ પ્રારંભ કરો. આ વાઇ-ફાઇ ક્લાઇન્ટ/હોટસ્પોટને બંધ કરશે."</string> + <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"વાઇ-ફાઇ ડાઇરેક્ટ પ્રારંભ કરી શકાયું નથી."</string> + <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"વાઇ-ફાઇ ડાઇરેક્ટ ચાલુ છે"</string> <string name="wifi_p2p_enabled_notification_message" msgid="8064677407830620023">"સેટિંગ્સ માટે ટૅપ કરો"</string> <string name="accept" msgid="1645267259272829559">"સ્વીકારો"</string> <string name="decline" msgid="2112225451706137894">"નકારો"</string> @@ -1143,9 +1143,9 @@ <string name="wifi_p2p_to_message" msgid="248968974522044099">"પ્રતિ:"</string> <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"આવશ્યક પિન લખો:"</string> <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"પિન:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"ટેબ્લેટ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> થી કનેક્ટ હોય તે વખતે Wi-Fi થી અસ્થાયી રૂપે ડિસ્કનેક્ટ કરવામાં આવશે"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="3087858235069421128">"ટીવી <xliff:g id="DEVICE_NAME">%1$s</xliff:g> થી કનેક્ટ હોય તે વખતે Wi-Fi થી અસ્થાયી રૂપે ડિસ્કનેક્ટ કરવામાં આવશે"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"ફોન <xliff:g id="DEVICE_NAME">%1$s</xliff:g> થી કનેક્ટ હોય તે વખતે Wi-Fi થી અસ્થાયી રૂપે ડિસ્કનેક્ટ કરવામાં આવશે"</string> + <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"ટેબ્લેટ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> થી કનેક્ટ હોય તે વખતે વાઇ-ફાઇ થી અસ્થાયી રૂપે ડિસ્કનેક્ટ કરવામાં આવશે"</string> + <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="3087858235069421128">"ટીવી <xliff:g id="DEVICE_NAME">%1$s</xliff:g> થી કનેક્ટ હોય તે વખતે વાઇ-ફાઇ થી અસ્થાયી રૂપે ડિસ્કનેક્ટ કરવામાં આવશે"</string> + <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"ફોન <xliff:g id="DEVICE_NAME">%1$s</xliff:g> થી કનેક્ટ હોય તે વખતે વાઇ-ફાઇ થી અસ્થાયી રૂપે ડિસ્કનેક્ટ કરવામાં આવશે"</string> <string name="select_character" msgid="3365550120617701745">"અક્ષર શામેલ કરો"</string> <string name="sms_control_title" msgid="7296612781128917719">"SMS સંદેશા મોકલી રહ્યું છે"</string> <string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> મોટા પ્રમાણમાં SMS સંદેશા મોકલી રહ્યું છે. શું તમે સંદેશા મોકલવાનું ચાલુ રાખવા માટે આ એપ્લિકેશનને મંજૂરી આપવા માગો છો?"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> થી કનેક્ટ થયાં. નેટવર્કને સંચાલિત કરવા માટે ટૅપ કરો."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"હંમેશા-ચાલુ VPN કનેક્ટ થઈ રહ્યું છે…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"હંમેશા-ચાલુ VPN કનેક્ટ થયું"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"હંમેશાં-ચાલુ VPN ડિસ્કનેક્ટ થયું"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"હંમેશાં-ચાલુ VPN થી ડિસ્કનેક્ટ થયું"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"હંમેશાં ચાલુ VPN ભૂલ"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"સેટ કરવા માટે ટૅપ કરો"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"નેટવર્ક અથવા VPN સેટિંગ્સ બદલો"</string> <string name="upload_file" msgid="2897957172366730416">"ફાઇલ પસંદ કરો"</string> <string name="no_file_chosen" msgid="6363648562170759465">"કોઈ ફાઇલ પસંદ કરેલી નથી"</string> <string name="reset" msgid="2448168080964209908">"ફરીથી સેટ કરો"</string> @@ -1385,12 +1385,12 @@ <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G ડેટા મર્યાદા પર પહોંચ્યાં"</string> <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G ડેટા મર્યાદા સુધી પહોંચ્યાં"</string> <string name="data_usage_mobile_limit_title" msgid="6561099244084267376">"મોબાઇલ ડેટાની મર્યાદા આવી ગઈ"</string> - <string name="data_usage_wifi_limit_title" msgid="5803363779034792676">"Wi-Fi ડેટા સીમા પર પહોંચ્યાં"</string> + <string name="data_usage_wifi_limit_title" msgid="5803363779034792676">"વાઇ-ફાઇ ડેટા સીમા પર પહોંચ્યાં"</string> <string name="data_usage_limit_body" msgid="291731708279614081">"બાકીના ચક્ર માટે ડેટા થોભાવ્યો"</string> <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"2G-3G ડેટા મર્યાદા ઓળંગાઈ"</string> <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"4G ડેટા મર્યાદા ઓળંગાઈ"</string> <string name="data_usage_mobile_limit_snoozed_title" msgid="279240572165412168">"મોબાઇલ ડેટા મર્યાદા ઓળંગાઈ"</string> - <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Wi-Fi ડેટા મર્યાદા ઓળંગાઈ"</string> + <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"વાઇ-ફાઇ ડેટા મર્યાદા ઓળંગાઈ"</string> <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"ઉલ્લેખિત મર્યાદાથી <xliff:g id="SIZE">%s</xliff:g> વધુ."</string> <string name="data_usage_restricted_title" msgid="5965157361036321914">"બૅકગ્રાઉન્ડ ડેટા પ્રતિબંધિત"</string> <string name="data_usage_restricted_body" msgid="469866376337242726">"પ્રતિબંધ દૂર કરવા માટે ટૅપ કરો."</string> @@ -1424,7 +1424,7 @@ <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"સ્પીકર્સ ડૉક કરો"</string> <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"સિસ્ટમ"</string> - <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth ઑડિઓ"</string> + <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"બ્લૂટૂથ ઑડિઓ"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"વાયરલેસ ડિસ્પ્લે"</string> <string name="media_route_button_content_description" msgid="591703006349356016">"કાસ્ટ કરો"</string> <string name="media_route_chooser_title" msgid="1751618554539087622">"ઉપકરણ સાથે કનેક્ટ કરો"</string> @@ -1627,7 +1627,7 @@ <string name="package_installed_device_owner" msgid="6875717669960212648">"તમારા વ્યવસ્થાપક દ્વારા ઇન્સ્ટૉલ કરવામાં આવેલ છે"</string> <string name="package_updated_device_owner" msgid="1847154566357862089">"તમારા વ્યવસ્થાપક દ્વારા અપડેટ કરવામાં આવેલ છે"</string> <string name="package_deleted_device_owner" msgid="2307122077550236438">"તમારા વ્યવસ્થાપક દ્વારા કાઢી નાખવામાં આવેલ છે"</string> - <string name="battery_saver_description" msgid="1960431123816253034">"બૅટરી આવરદા વધુ સારી કરવામાં સહાય માટે, બૅટરી સેવર તમારા ઉપકરણના પ્રદર્શનને ઘટાડે છે અને વાઇબ્રેશન, સ્થાન સેવાઓ અને મોટાભાગના પૃષ્ઠભૂમિ ડેટાને સીમિત કરે છે. ઇમેઇલ, મેસેજિંગ અને અન્ય ઍપ્લિકેશનો જે સમન્વયન પર આધાર રાખે છે તે તમે તેમને ખોલશો નહીં ત્યાં સુધી અપડેટ થઈ શકતી નથી.\n\nજ્યારે તમારું ઉપકરણ ચાર્જ થઈ રહ્યું હોય ત્યારે બૅટરી સેવર આપમેળે બંધ થઈ જાય છે."</string> + <string name="battery_saver_description" msgid="1960431123816253034">"બૅટરી આવરદા વધુ સારી કરવામાં સહાય માટે, બૅટરી સેવર તમારા ઉપકરણના પ્રદર્શનને ઘટાડે છે અને વાઇબ્રેશન, સ્થાન સેવાઓ અને મોટાભાગના બૅકગ્રાઉન્ડ ડેટાને સીમિત કરે છે. ઇમેઇલ, મેસેજિંગ અને અન્ય ઍપ્લિકેશનો જે સમન્વયન પર આધાર રાખે છે તે તમે તેમને ખોલશો નહીં ત્યાં સુધી અપડેટ થઈ શકતી નથી.\n\nજ્યારે તમારું ઉપકરણ ચાર્જ થઈ રહ્યું હોય ત્યારે બૅટરી સેવર આપમેળે બંધ થઈ જાય છે."</string> <string name="data_saver_description" msgid="6015391409098303235">"ડેટા વપરાશને ઘટાડવામાં સહાય માટે, ડેટા સેવર કેટલીક ઍપ્લિકેશનોને પૃષ્ઠભૂમિમાં ડેટા મોકલવા અથવા પ્રાપ્ત કરવાથી અટકાવે છે. તમે હાલમાં ઉપયોગ કરી રહ્યાં છો તે ઍપ્લિકેશન ડેટાને ઍક્સેસ કરી શકે છે, પરંતુ તે આ ક્યારેક જ કરી શકે છે. આનો અર્થ એ હોઈ શકે છે, ઉદાહરણ તરીકે, છબીઓ ત્યાં સુધી પ્રદર્શિત થશે નહીં જ્યાં સુધી તમે તેને ટૅપ નહીં કરો."</string> <string name="data_saver_enable_title" msgid="4674073932722787417">"ડેટા સેવર ચાલુ કરીએ?"</string> <string name="data_saver_enable_button" msgid="7147735965247211818">"ચાલુ કરો"</string> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 2699617f87fe..c7d8b1fe6b48 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -40,7 +40,7 @@ <string name="mmiComplete" msgid="8232527495411698359">"MMI पूर्ण."</string> <string name="badPin" msgid="9015277645546710014">"आपके द्वारा लिखा गया पुराना पिन सही नहीं है."</string> <string name="badPuk" msgid="5487257647081132201">"आपके द्वारा लिखा गया PUK सही नहीं है."</string> - <string name="mismatchPin" msgid="609379054496863419">"आपके द्वारा लिखे गए पिन का मिलान नहीं होता."</string> + <string name="mismatchPin" msgid="609379054496863419">"आपने जो पिन लिखे हैं उसका मिलान नहीं होता."</string> <string name="invalidPin" msgid="3850018445187475377">"कोई ऐसा पिन लिखें, जिसमें 4 से 8 अंक हों."</string> <string name="invalidPuk" msgid="8761456210898036513">"ऐसा PUK लिखें जो 8 अंकों या अधिक का हो."</string> <string name="needPuk" msgid="919668385956251611">"आपका सिम कार्ड PUK लॉक किया गया है. इसे अनलॉक करने के लिए PUK कोड लिखें."</string> @@ -86,7 +86,7 @@ <string name="notification_channel_call_forward" msgid="2419697808481833249">"कॉल को दूसरे नंबर पर भेजना"</string> <string name="notification_channel_emergency_callback" msgid="6686166232265733921">"आपातकालीन कॉलबैक मोड"</string> <string name="notification_channel_mobile_data_status" msgid="4575131690860945836">"मोबाइल डेटा की स्थिति"</string> - <string name="notification_channel_sms" msgid="3441746047346135073">"SMS संदेश"</string> + <string name="notification_channel_sms" msgid="3441746047346135073">"मैसेज (एसएमएस)"</string> <string name="notification_channel_voice_mail" msgid="3954099424160511919">"वॉइसमेल संदेश"</string> <string name="notification_channel_wfc" msgid="2130802501654254801">"वाई-फ़ाई कॉलिंग"</string> <string name="peerTtyModeFull" msgid="6165351790010341421">"पीयर ने टेलीटाइपराइटर (TTY) मोड फ़ुल का अनुरोध किया"</string> @@ -96,7 +96,7 @@ <string name="serviceClassVoice" msgid="1258393812335258019">"ध्वनि"</string> <string name="serviceClassData" msgid="872456782077937893">"डेटा"</string> <string name="serviceClassFAX" msgid="5566624998840486475">"फ़ैक्स"</string> - <string name="serviceClassSMS" msgid="2015460373701527489">"SMS"</string> + <string name="serviceClassSMS" msgid="2015460373701527489">"मैसेज (एसएमएस)"</string> <string name="serviceClassDataAsync" msgid="4523454783498551468">"Async"</string> <string name="serviceClassDataSync" msgid="7530000519646054776">"समन्वयन"</string> <string name="serviceClassPacket" msgid="6991006557993423453">"पैकेट"</string> @@ -114,13 +114,13 @@ <string name="roamingText10" msgid="3992906999815316417">"रोमिंग - आंशिक सेवा कार्यक्षमता"</string> <string name="roamingText11" msgid="4154476854426920970">"रोमिंग बैनर चालू"</string> <string name="roamingText12" msgid="1189071119992726320">"रोमिंग बैनर बंद"</string> - <string name="roamingTextSearching" msgid="8360141885972279963">"सेवा खोज रहा है"</string> + <string name="roamingTextSearching" msgid="8360141885972279963">"नेटवर्क खोज रहा है"</string> <string name="wfcRegErrorTitle" msgid="2301376280632110664">"वाई-फ़ाई कॉलिंग"</string> <string-array name="wfcOperatorErrorAlertMessages"> <item msgid="3910386316304772394">"वाई-फ़ाई से फ़ोन करने और मैसेज भेजने के लिए, सबसे पहले अपनी मोबाइल और इंटरनेट सेवा देने वाली कंपनी से इस सेवा को सेट अप करने के लिए कहें. उसके बाद सेटिंग से वाई-फ़ाई कॉलिंग को फिर से चालू करें. (गड़बड़ी कोड: <xliff:g id="CODE">%1$s</xliff:g>)"</item> </string-array> <string-array name="wfcOperatorErrorNotificationMessages"> - <item msgid="7472393097168811593">"अपनी मोबाइल और इंटरनेट सेवा देने वाली कंपनी से पंजीकृत करें (गड़बड़ी कोड: <xliff:g id="CODE">%1$s</xliff:g>)"</item> + <item msgid="7472393097168811593">"अपनी मोबाइल और इंटरनेट सेवा देने वाली कंपनी के साथ रजिस्टर करें (गड़बड़ी कोड: <xliff:g id="CODE">%1$s</xliff:g>)"</item> </string-array> <string-array name="wfcSpnFormats"> <item msgid="6830082633573257149">"%s"</item> @@ -139,17 +139,17 @@ <string name="fcError" msgid="3327560126588500777">"कनेक्शन समस्या या अमान्य सुविधा कोड."</string> <string name="httpErrorOk" msgid="1191919378083472204">"ठीक है"</string> <string name="httpError" msgid="7956392511146698522">"कोई नेटवर्क गड़बड़ी हुई थी."</string> - <string name="httpErrorLookup" msgid="4711687456111963163">"URL नहीं मिल सका."</string> + <string name="httpErrorLookup" msgid="4711687456111963163">"यूआरएल नहीं मिल सका."</string> <string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"साइट प्रमाणीकरण योजना समर्थित नहीं है."</string> <string name="httpErrorAuth" msgid="1435065629438044534">"प्रमाणीकृत नहीं किया जा सका."</string> <string name="httpErrorProxyAuth" msgid="1788207010559081331">"प्रॉक्सी सर्वर द्वारा प्रमाणीकरण असफल था."</string> <string name="httpErrorConnect" msgid="8714273236364640549">"सर्वर से कनेक्ट नहीं किया जा सका."</string> <string name="httpErrorIO" msgid="2340558197489302188">"सर्वर से संचार नहीं किया जा सका. बाद में पुन: प्रयास करें."</string> <string name="httpErrorTimeout" msgid="4743403703762883954">"सर्वर से कनेक्शन का समय समाप्त हुआ."</string> - <string name="httpErrorRedirectLoop" msgid="8679596090392779516">"पेज में कई सर्वर रीडायरेक्ट हैं."</string> + <string name="httpErrorRedirectLoop" msgid="8679596090392779516">"पेज में कई ऐसे कई वेबलिंक हैं जो दूसरे सर्वर पर ले जाते हैं."</string> <string name="httpErrorUnsupportedScheme" msgid="5015730812906192208">"प्रोटोकॉल समर्थित नहीं है."</string> <string name="httpErrorFailedSslHandshake" msgid="96549606000658641">"सुरक्षित कनेक्शन स्थापित नहीं किया जा सका."</string> - <string name="httpErrorBadUrl" msgid="3636929722728881972">"URL अमान्य होने के कारण पेज नहीं खोला जा सका."</string> + <string name="httpErrorBadUrl" msgid="3636929722728881972">"यूआरएल गलत होने की वजह से पेज नहीं खोला जा सका."</string> <string name="httpErrorFile" msgid="2170788515052558676">"फ़ाइल पर नहीं पहुंचा जा सका."</string> <string name="httpErrorFileNotFound" msgid="6203856612042655084">"अनुरोधित फ़ाइल नहीं मिल सकी."</string> <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"बहुत सारे अनुरोधों का संसाधन हो रहा है. बाद में पुन: प्रयास करें."</string> @@ -157,13 +157,13 @@ <string name="contentServiceSync" msgid="8353523060269335667">"समन्वयन"</string> <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"समन्वयन"</string> <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"बहुत से <xliff:g id="CONTENT_TYPE">%s</xliff:g> हटाए जाते हैं."</string> - <string name="low_memory" product="tablet" msgid="6494019234102154896">"टेबलेट मेमोरी भर गया है. स्थान खाली करने के लिए कुछ फ़ाइलें हटाएं."</string> + <string name="low_memory" product="tablet" msgid="6494019234102154896">"टैबलेट मेमोरी भर गया है. स्थान खाली करने के लिए कुछ फ़ाइलें हटाएं."</string> <string name="low_memory" product="watch" msgid="4415914910770005166">"घड़ी मेमोरी भर गया है. स्थान खाली करने के लिए कुछ फ़ाइलें हटाएं."</string> <string name="low_memory" product="tv" msgid="516619861191025923">"टीवी की मेमोरी पूरी हो गई है. स्थान खाली करने के लिए कुछ फ़ाइलें हटाएं."</string> <string name="low_memory" product="default" msgid="3475999286680000541">"फ़ोन मेमोरी भर गया है. स्थान खाली करने के लिए कुछ फ़ाइलें हटाएं."</string> <plurals name="ssl_ca_cert_warning" formatted="false" msgid="5106721205300213569"> - <item quantity="one">प्रमाणपत्र प्राधिकरण इंस्टॉल किए हुए हैं</item> - <item quantity="other">प्रमाणपत्र प्राधिकरण इंस्टॉल किए हुए हैं</item> + <item quantity="one">प्रमाणपत्र अनुमतियों को इंस्टॉल किया गया</item> + <item quantity="other">प्रमाणपत्र अनुमतियों को इंस्टॉल किया गया</item> </plurals> <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"किसी अज्ञात तृतीय पक्ष के द्वारा"</string> <string name="ssl_ca_cert_noti_by_administrator" msgid="3541729986326153557">"आपकी कार्य प्रोफ़ाइल का व्यवस्थापक करता है"</string> @@ -177,7 +177,7 @@ <string name="factory_reset_warning" msgid="5423253125642394387">"आपके डिवाइस को मिटा दिया जाएगा"</string> <string name="factory_reset_message" msgid="7972496262232832457">"व्यवस्थापक ऐप्लिकेशन का उपयोग नहीं किया जा सकता. अब आपके डिवाइस को मिटा दिया जाएगा.\n\nअगर आप सवाल पूछना चाहते हैं, तो अपने संगठन के व्यवस्थापक से संपर्क करें."</string> <string name="me" msgid="6545696007631404292">"मैं"</string> - <string name="power_dialog" product="tablet" msgid="8545351420865202853">"टेबलेट विकल्प"</string> + <string name="power_dialog" product="tablet" msgid="8545351420865202853">"टैबलेट विकल्प"</string> <string name="power_dialog" product="tv" msgid="6153888706430556356">"टीवी के विकल्प"</string> <string name="power_dialog" product="default" msgid="1319919075463988638">"फ़ोन विकल्प"</string> <string name="silent_mode" msgid="7167703389802618663">"साइलेंट मोड (खामोश)"</string> @@ -186,16 +186,16 @@ <string name="screen_lock" msgid="799094655496098153">"स्क्रीन लॉक"</string> <string name="power_off" msgid="4266614107412865048">"पावर बंद"</string> <string name="silent_mode_silent" msgid="319298163018473078">"रिंगर बंद"</string> - <string name="silent_mode_vibrate" msgid="7072043388581551395">"रिंगर कंपन"</string> + <string name="silent_mode_vibrate" msgid="7072043388581551395">"रिंगर कंपन (वाइब्रेशन)"</string> <string name="silent_mode_ring" msgid="8592241816194074353">"रिंगर चालू"</string> - <string name="reboot_to_update_title" msgid="6212636802536823850">"Android सिस्टम से संबद्ध नई जानकारी"</string> + <string name="reboot_to_update_title" msgid="6212636802536823850">"Android सिस्टम उपडेट हो रहा है"</string> <string name="reboot_to_update_prepare" msgid="6305853831955310890">"अपडेट करने के लिए तैयार हो रहा है…"</string> <string name="reboot_to_update_package" msgid="3871302324500927291">"अपडेट पैकेज को संसाधित कर रहा है…"</string> <string name="reboot_to_update_reboot" msgid="6428441000951565185">"पुन: प्रारंभ हो रहा है…"</string> <string name="reboot_to_reset_title" msgid="4142355915340627490">"फ़ैक्टरी डेटा रीसेट"</string> <string name="reboot_to_reset_message" msgid="2432077491101416345">"पुन: प्रारंभ हो रहा है…"</string> <string name="shutdown_progress" msgid="2281079257329981203">"शट डाउन हो रहा है..."</string> - <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"आपकी टेबलेट शट डाउन हो जाएगी."</string> + <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"आपकी टैबलेट शट डाउन हो जाएगी."</string> <string name="shutdown_confirm" product="tv" msgid="476672373995075359">"आपका टीवी बंद हो जाएगा."</string> <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"आपकी घड़ी बंद हो जाएगी."</string> <string name="shutdown_confirm" product="default" msgid="649792175242821353">"आपका फ़ोन शट डाउन हो जाएगा."</string> @@ -204,22 +204,22 @@ <string name="reboot_safemode_confirm" msgid="55293944502784668">"क्या आप सुरक्षित मोड में रीबूट करना चाहते हैं? इससे आपके इंस्टॉल किए हुए सभी तृतीय पक्ष ऐप्स अक्षम हो जाएंगे. जब आप फिर से रीबूट करेंगे तो वे पुनर्स्थापित हो जाएंगे."</string> <string name="recent_tasks_title" msgid="3691764623638127888">"हाल के"</string> <string name="no_recent_tasks" msgid="8794906658732193473">"कोई हाल ही के ऐप्स नहीं."</string> - <string name="global_actions" product="tablet" msgid="408477140088053665">"टेबलेट विकल्प"</string> + <string name="global_actions" product="tablet" msgid="408477140088053665">"टैबलेट विकल्प"</string> <string name="global_actions" product="tv" msgid="7240386462508182976">"टीवी के विकल्प"</string> <string name="global_actions" product="default" msgid="2406416831541615258">"फ़ोन विकल्प"</string> <string name="global_action_lock" msgid="2844945191792119712">"स्क्रीन लॉक"</string> <string name="global_action_power_off" msgid="4471879440839879722">"पावर बंद"</string> <string name="global_action_emergency" msgid="7112311161137421166">"आपातकाल"</string> - <string name="global_action_bug_report" msgid="7934010578922304799">"बग रिपोर्ट"</string> - <string name="bugreport_title" msgid="2667494803742548533">"बग रिपोर्ट प्राप्त करें"</string> - <string name="bugreport_message" msgid="398447048750350456">"ईमेल संदेश के रूप में भेजने के लिए, इसके द्वारा आपके डिवाइस की वर्तमान स्थिति के बारे में जानकारी एकत्र की जाएगी. बग रिपोर्ट प्रारंभ करने से लेकर भेजने के लिए तैयार होने तक कुछ समय लगेगा; कृपया धैर्य रखें."</string> + <string name="global_action_bug_report" msgid="7934010578922304799">"गड़बड़ी की रिपोर्ट"</string> + <string name="bugreport_title" msgid="2667494803742548533">"गड़बड़ी की रिपोर्ट लें"</string> + <string name="bugreport_message" msgid="398447048750350456">"इससे ईमेल भेजने के लिए, आपके डिवाइस की मौजूदा स्थिति से जुड़ी जानकारी इकट्ठा की जाएगी. गड़बड़ी की रिपोर्ट बनना शुरू होने से लेकर भेजने के लिए तैयार होने तक कुछ समय लगेगा; कृपया इंतज़ार करें."</string> <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"सहभागी रिपोर्ट"</string> <string name="bugreport_option_interactive_summary" msgid="229299488536107968">"अधिकांश परिस्थितियों में इसका उपयोग करें. यह आपको रिपोर्ट की प्रगति ट्रैक करने देता है, समस्या के बारे में अधिक विवरण डालने देता है और स्क्रीनशॉट लेने देता है. यह आपको ऐसे कम उपयोग किए गए अनुभाग मिटाने दे सकता है जिनकी रिपोर्ट करने में अधिक समय लगता है."</string> <string name="bugreport_option_full_title" msgid="6354382025840076439">"पूर्ण रिपोर्ट"</string> <string name="bugreport_option_full_summary" msgid="7210859858969115745">"जब आपका डिवाइस ठीक से काम नहीं कर रहा हो या बहुत धीमा हो या जब आपको रिपोर्ट के सभी भागों की ज़रूरत हो, तो सिस्टम से कम से कम रोक-टोक के लिए इस विकल्प का इस्तेमाल करें. यह आपको ज़्यादा जानकारी डालने या अतिरिक्त स्क्रीनशॉट लेने नहीं देता."</string> <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368"> - <item quantity="one">बग रिपोर्ट के लिए <xliff:g id="NUMBER_1">%d</xliff:g> सेकंड में स्क्रीनशॉट लिया जा रहा है.</item> - <item quantity="other">बग रिपोर्ट के लिए <xliff:g id="NUMBER_1">%d</xliff:g> सेकंड में स्क्रीनशॉट लिया जा रहा है.</item> + <item quantity="one">गड़बड़ी की रिपोर्ट के लिए <xliff:g id="NUMBER_1">%d</xliff:g> सेकंड में स्क्रीनशॉट लिया जा रहा है.</item> + <item quantity="other">गड़बड़ी की रिपोर्ट के लिए <xliff:g id="NUMBER_1">%d</xliff:g> सेकंड में स्क्रीनशॉट लिया जा रहा है.</item> </plurals> <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"साइलेंट मोड (खामोश)"</string> <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"ध्वनि बंद है"</string> @@ -232,7 +232,7 @@ <string name="global_action_voice_assist" msgid="7751191495200504480">"आवाज़ से डिवाइस का इस्तेमाल"</string> <string name="global_action_lockdown" msgid="8751542514724332873">"अभी लॉक करें"</string> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string> - <string name="notification_hidden_text" msgid="6351207030447943784">"नया नोटिफ़िकेशन"</string> + <string name="notification_hidden_text" msgid="6351207030447943784">"नई सूचना"</string> <string name="notification_channel_virtual_keyboard" msgid="6969925135507955575">"वर्चुअल कीबोर्ड"</string> <string name="notification_channel_physical_keyboard" msgid="7297661826966861459">"भौतिक कीबोर्ड"</string> <string name="notification_channel_security" msgid="7345516133431326347">"सुरक्षा"</string> @@ -248,10 +248,10 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"सूचनाएं"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"खुदरा डेमो"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB कनेक्शन"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"बैकग्राउंड में चल रहे ऐप्लिकेशन"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> बैकग्राउंड में चल रहा है"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> ऐप्लिकेशन बैकग्राउंड में चल रहे हैं"</string> - <string name="foreground_service_tap_for_details" msgid="372046743534354644">"बैटरी और डेटा खर्च की जानकारी के लिए टैप करें"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"बैटरी की खपत करने वाले ऐप"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> बैटरी का इस्तेमाल कर रहा है"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> ऐप बैटरी का इस्तेमाल कर रहे हैं"</string> + <string name="foreground_service_tap_for_details" msgid="372046743534354644">"बैटरी और डेटा खर्च की जानकारी के लिए छूएं"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string> <string name="android_system_label" msgid="6577375335728551336">"Android सिस्टम"</string> @@ -266,9 +266,9 @@ <string name="permgrouplab_calendar" msgid="5863508437783683902">"कैलेंडर"</string> <string name="permgroupdesc_calendar" msgid="3889615280211184106">"अपने कैलेंडर को ऐक्सेस करने"</string> <string name="permgrouprequest_calendar" msgid="6704529828699071445">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> को अपना कैलेंडर एक्सेस करने दें"</string> - <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string> - <string name="permgroupdesc_sms" msgid="4656988620100940350">"SMS संदेश भेजें और देखने की"</string> - <string name="permgrouprequest_sms" msgid="605618939583628306">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> को SMS संदेश भेजने और देखने दें"</string> + <string name="permgrouplab_sms" msgid="228308803364967808">"मैसेज (एसएमएस)"</string> + <string name="permgroupdesc_sms" msgid="4656988620100940350">"मैसेज (एसएमएस) भेजें और देखें"</string> + <string name="permgrouprequest_sms" msgid="605618939583628306">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> को मैसेज (एसएमएस) भेजने और देखने दें"</string> <string name="permgrouplab_storage" msgid="1971118770546336966">"मेमोरी"</string> <string name="permgroupdesc_storage" msgid="637758554581589203">"अपने डिवाइस पर मौजूद फ़ोटो, मीडिया और फ़ाइलें ऐक्सेस करने की"</string> <string name="permgrouprequest_storage" msgid="7429669910547860218">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> को अपने डिवाइस पर फ़ोटो, मीडिया और फ़ाइलें एक्सेस करने दें"</string> @@ -290,44 +290,44 @@ <string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"टैप किए गए आइटम ज़ोर से बोले जाएंगे और स्क्रीन को जेस्चर के ज़रिए एक्सप्लोर किया जा सकता है."</string> <string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"आपके द्वारा लिखे हुए लेख को ध्यान से देखें"</string> <string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"क्रेडिट कार्ड नंबर और पासवर्ड जैसा व्यक्तिगत डेटा शामिल होता है."</string> - <string name="capability_title_canControlMagnification" msgid="3593493281059424855">"प्रदर्शन आवर्धन नियंत्रित करें"</string> - <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"प्रदर्शन का ज़ूम स्तर और स्थिति निर्धारण नियंत्रित करें."</string> + <string name="capability_title_canControlMagnification" msgid="3593493281059424855">"डिसप्ले को बड़ा-छोटा करने की सुविधा को नियंत्रित करें"</string> + <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"डिसप्ले के ज़ूम का स्तर और पोज़िशनिंग नियंत्रित करें."</string> <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"जेस्चर करें"</string> <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"इस सेवा के ज़रिए टैप, स्वाइप, पिंच और बाकी जेस्चर किए जा सकते हैं."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"फ़िंगरप्रिंट जेस्चर"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"डिवाइस फ़िंगरप्रिंट सेंसर पर किए गए जेस्चर कैप्चर किए जा सकते हैं."</string> <string name="permlab_statusBar" msgid="7417192629601890791">"स्टेटस बार को अक्षम करें या बदलें"</string> - <string name="permdesc_statusBar" msgid="8434669549504290975">"ऐप को, स्टेटस बार को अक्षम करने या सिस्टम आइकन को जोड़ने या निकालने की अनुमति देता है."</string> + <string name="permdesc_statusBar" msgid="8434669549504290975">"ऐप को, स्टेटस बार को बंद करने या सिस्टम आइकॉन को जोड़ने और निकालने की अनुमति देता है."</string> <string name="permlab_statusBarService" msgid="4826835508226139688">"स्टेटस बार को रहने दें"</string> <string name="permdesc_statusBarService" msgid="716113660795976060">"ऐप को स्टेटस बार बने रहने की अनुमति देता है."</string> <string name="permlab_expandStatusBar" msgid="1148198785937489264">"स्टेटस बार खोलकर बड़ा करें/छोटा करें"</string> <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"ऐप को, स्टेटस बार खोलकर बड़ा करने या उसे छोटा करने की अनुमति देता है."</string> <string name="permlab_install_shortcut" msgid="4279070216371564234">"शॉर्टकट इंस्टॉल करें"</string> - <string name="permdesc_install_shortcut" msgid="8341295916286736996">"एप्लिकेशन को उपयोगकर्ता के हस्तक्षेप के बिना होमस्क्रीन शॉर्टकट जोड़ने की अनुमति देता है."</string> + <string name="permdesc_install_shortcut" msgid="8341295916286736996">"एप्लिकेशन को उपयोगकर्ता की रोक के बिना होमस्क्रीन शॉर्टकट जोड़ने की अनुमति देता है."</string> <string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"शॉर्टकट अनइंस्टॉल करें"</string> - <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"एप्लिकेशन को उपयोगकर्ता के हस्तक्षेप के बिना होमस्क्रीन शॉर्टकट निकालने की अनुमति देता है."</string> + <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"एप्लिकेशन को उपयोगकर्ता की रोक के बिना होमस्क्रीन शॉर्टकट निकालने की अनुमति देता है."</string> <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"किया जाने वाला कॉल (आउटगोइंग) कहीं और भेजें"</string> <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"एेप कॉल को किसी और नंबर पर भेजने या कॉल को पूरी तरह रद्द करने के विकल्प के साथ, किए गए कॉल (आउटगोइंग) के नंबर को देख सकता है."</string> <string name="permlab_answerPhoneCalls" msgid="4077162841226223337">"फ़ोन कॉल का जवाब दें"</string> <string name="permdesc_answerPhoneCalls" msgid="2901889867993572266">"ऐप्लिकेशन को किसी इनकमिंग फ़ोन कॉल का जवाब देने देती है."</string> - <string name="permlab_receiveSms" msgid="8673471768947895082">"लेख संदेश (SMS) प्राप्त करें"</string> - <string name="permdesc_receiveSms" msgid="6424387754228766939">"ऐप्स को SMS संदेशों को प्राप्त और संसाधित करने देता है. इसका अर्थ है कि ऐप्स आपके डिवाइस पर भेजे गए संदेशों की निगरानी आपको दिखाए बिना कर सकता है और उन्हें हटा सकता है."</string> - <string name="permlab_receiveMms" msgid="1821317344668257098">"लेख संदेश (MMS) प्राप्त करें"</string> - <string name="permdesc_receiveMms" msgid="533019437263212260">"ऐप्स को MMS संदेशों को प्राप्त और संसाधित करने देता है. इसका अर्थ है कि ऐप्स आपके डिवाइस पर भेजे गए संदेशों की निगरानी आपको दिखाए बिना कर सकता है और उन्हें हटा सकता है."</string> + <string name="permlab_receiveSms" msgid="8673471768947895082">"मैसेज (एसएमएस) पाएं"</string> + <string name="permdesc_receiveSms" msgid="6424387754228766939">"ऐप को मैसेज (एसएमएस) को प्राप्त और संसाधित करने देता है. इसका अर्थ है कि ऐप आपके डिवाइस पर भेजे गए संदेशों की निगरानी आपको दिखाए बिना कर सकता है और उन्हें हटा सकता है."</string> + <string name="permlab_receiveMms" msgid="1821317344668257098">"मैसेज (एमएमएस) पाएं"</string> + <string name="permdesc_receiveMms" msgid="533019437263212260">"ऐप को मल्टीमीडिया मैसेज (एमएमएस) को पाने और उन पर कार्रवाई करने देता है. इसका मतलब है कि ऐप आपके डिवाइस पर भेजे गए मैसेज की निगरानी आपको दिखाए बिना कर सकता है और उन्हें हटा सकता है."</string> <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"सेल ब्रॉडकास्ट (CBC) मैसेज पढ़ें"</string> <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ऐप को, वो सेल ब्रॉडकास्ट (CBC) मैसेज पढ़ने देता है जो आपके डिवाइस को मिले हैं. सेल ब्रॉडकास्ट (CBC) अलर्ट कुछ स्थानों (लोकेशन) पर आपको आपातकालीन स्थितियों की चेतावनी देने के लिए दिए जाते हैं. आपातकालीन सेल ब्रॉडकास्ट (CBC) मिलने पर, धोखा देने वाले ऐप आपके डिवाइस के परफ़ॉर्मेंस या कार्यवाही में दखल दे सकते हैं."</string> <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"सदस्यता-प्राप्त फ़ीड पढ़ें"</string> <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"ऐप्स को वर्तमान में समन्वयित फ़ीड के बारे में विवरण प्राप्त करने देता है."</string> - <string name="permlab_sendSms" msgid="7544599214260982981">"SMS संदेश भेजें और देखें"</string> - <string name="permdesc_sendSms" msgid="7094729298204937667">"ऐप्स को SMS संदेशों को भेजने देता है. इसके परिणामस्वरूप अप्रत्याशित शुल्क लागू हो सकते हैं. दुर्भावनापूर्ण ऐप्स आपकी पुष्टि के बिना संदेश भेजकर आपका धन व्यय कर सकते हैं."</string> - <string name="permlab_readSms" msgid="8745086572213270480">"अपने लेख संदेश (SMS या MMS) पढ़ें"</string> - <string name="permdesc_readSms" product="tablet" msgid="4741697454888074891">"यह ऐप्लिकेशन आपके टैबलेट पर संग्रहित सभी SMS (लेख) संदेश पढ़ सकता है."</string> - <string name="permdesc_readSms" product="tv" msgid="5796670395641116592">"यह ऐप्लिकेशन आपके टीवी पर संग्रहित सभी SMS (लेख) संदेश पढ़ सकता है."</string> - <string name="permdesc_readSms" product="default" msgid="6826832415656437652">"यह ऐप्लिकेशन आपके फ़ोन पर संग्रहित सभी SMS (लेख) संदेश पढ़ सकता है."</string> + <string name="permlab_sendSms" msgid="7544599214260982981">"मैसेज (एमएमएस) भेजें और देखें"</string> + <string name="permdesc_sendSms" msgid="7094729298204937667">"ऐप को मैसेज (एसएमएस) भेजने देता है. इसकी वजह से उम्मीद से ज़्यादा शुल्क लग सकते हैं. धोखा देने वाले ऐप आपकी पुष्टि के बिना मैसेज भेजकर आपका पैसा खर्च करवा सकते हैं."</string> + <string name="permlab_readSms" msgid="8745086572213270480">"अपने मैसेज (एसएमएस या एमएमएस) पढ़ें"</string> + <string name="permdesc_readSms" product="tablet" msgid="4741697454888074891">"यह ऐप आपके टैबलेट पर सहेजे गए सभी मैसेज (एसएमएस) पढ़ सकता है."</string> + <string name="permdesc_readSms" product="tv" msgid="5796670395641116592">"यह ऐप आपके टीवी पर सहेजे गए सभी मैसेज (एसएमएस) पढ़ सकता है."</string> + <string name="permdesc_readSms" product="default" msgid="6826832415656437652">"यह ऐप आपके फ़ोन पर सहेजे गए सभी मैसेज (एसएमएस) पढ़ सकता है."</string> <string name="permlab_receiveWapPush" msgid="5991398711936590410">"लेख संदेश (WAP) प्राप्त करें"</string> <string name="permdesc_receiveWapPush" msgid="748232190220583385">"ऐप्स को WAP संदेशों को प्राप्त और संसाधित करने देता है. इस अनुमति में आपको भेजे गए संदेशों की निगरानी आपको दिखाए बिना करने और हटाने की क्षमता शामिल है."</string> <string name="permlab_getTasks" msgid="6466095396623933906">"चल रहे ऐप्स पुनर्प्राप्त करें"</string> - <string name="permdesc_getTasks" msgid="7454215995847658102">"ऐप्स को वर्तमान में और हाल ही में चल रहे कार्यों के बारे में जानकारी को पुन: प्राप्त करने देता है. इससे ऐप्स डिवाइस पर उपयोग किए गए ऐप्स के बारे में जानकारी खोज सकता है."</string> + <string name="permdesc_getTasks" msgid="7454215995847658102">"ऐप को माजूदा समय में और हाल ही में चल रही कार्रवाइयों के बारे में जानकारी निकालने देता है. इससे ऐप डिवाइस पर इस्तेमाल किए गए ऐप के बारे में जानकारी खोज सकता है."</string> <string name="permlab_manageProfileAndDeviceOwners" msgid="7918181259098220004">"प्रोफ़ाइल और डिवाइस स्वामियों को प्रबंधित करें"</string> <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"ऐप्स को प्रोफ़ाइल स्वामी और डिवाइस स्वामी सेट करने दें."</string> <string name="permlab_reorderTasks" msgid="2018575526934422779">"चल रहे ऐप्स पुन: क्रमित करें"</string> @@ -343,7 +343,7 @@ <string name="permlab_useDataInBackground" msgid="8694951340794341809">"बैकग्राउंड में डेटा का उपयोग करता है"</string> <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"यह ऐप बैकग्राउंड में डेटा का उपयोग कर सकता है. इससे डेटा का उपयोग बढ़ सकता है."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"ऐप्स को हमेशा चलने वाला बनाएं"</string> - <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"ऐप्स को मेमोरी में स्वयं के कुछ हिस्सों को लगातार बनाने की अनुमति देता है. यह अन्य ऐप्स के लिए उपलब्ध स्मृति को सीमित कर टेबलेट को धीमा कर सकता है."</string> + <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"ऐप्स को मेमोरी में स्वयं के कुछ हिस्सों को लगातार बनाने की अनुमति देता है. यह अन्य ऐप्स के लिए उपलब्ध स्मृति को सीमित कर टैबलेट को धीमा कर सकता है."</string> <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"ऐप को मेमोरी में स्वयं के दीर्घस्थायी भाग बनाने देती है. इससे अन्य ऐप्स के लिए उपलब्ध मेमोरी सीमित हो सकती है जिससे टीवी धीमा हो सकता है."</string> <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"ऐप्स को मेमोरी में स्वयं के कुछ हिस्सों को लगातार बनाने देता है. यह अन्य ऐप्स के लिए उपलब्ध स्मृति को सीमित कर फ़ोन को धीमा कर सकता है."</string> <string name="permlab_getPackageSize" msgid="7472921768357981986">"ऐप्स मेमोरी स्थान मापें"</string> @@ -351,19 +351,19 @@ <string name="permlab_writeSettings" msgid="2226195290955224730">"सिस्टम सेटिंग बदलें"</string> <string name="permdesc_writeSettings" msgid="7775723441558907181">"ऐप्स को सिस्टम सेटिंग डेटा संशोधित करने देता है. दुर्भावनापूर्ण ऐप्स आपके सिस्टम के कॉन्फ़िगरेशन को दूषित कर सकते हैं."</string> <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"प्रारंभ होने पर चलाएं"</string> - <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"ऐप्स को सिस्टम द्वारा बूटिंग पूर्ण करते ही स्वतः आरंभ करने देता है. इससे टेबलेट को आरंभ होने में अधिक समय लग सकता है और ऐप्स को निरंतर चलाकर संपूर्ण टेबलेट को धीमा करने देता है."</string> + <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"ऐप्स को सिस्टम द्वारा बूटिंग पूर्ण करते ही स्वतः आरंभ करने देता है. इससे टैबलेट को आरंभ होने में अधिक समय लग सकता है और ऐप्स को निरंतर चलाकर संपूर्ण टैबलेट को धीमा करने देता है."</string> <string name="permdesc_receiveBootCompleted" product="tv" msgid="4525890122209673621">"ऐप्स को सिस्टम का बूट होना पूर्ण होते ही स्वत: प्रारंभ होने देती है. इससे टीवी को प्रारंभ होने में अधिक समय लग सकता है और ऐप के हमेशा चलने से संपूर्ण टैबलेट धीमा हो सकता है."</string> <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"ऐप्स को सिस्टम द्वारा बूटिंग पूर्ण करते ही स्वतः प्रारंभ होने देता है. इससे फ़ोन को प्रारंभ होने में अधिक समय लग सकता है और ऐप्स के निरंतर चलते रहने से संपूर्ण फ़ोन प्रक्रियाएं धीमी हो सकती हैं."</string> <string name="permlab_broadcastSticky" msgid="7919126372606881614">"स्टिकी प्रसारण भेजें"</string> - <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"ऐप्स को स्टिकी प्रसारण भेजने देता है, जो प्रसारण समाप्त होने के बाद भी बने रहते हैं. अत्यधिक उपयोग, टेबलेट की बहुत अधिक मेमोरी का उपयोग करके उसे धीमा या अस्थिर कर सकता है."</string> + <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"ऐप्स को स्टिकी प्रसारण भेजने देता है, जो प्रसारण समाप्त होने के बाद भी बने रहते हैं. अत्यधिक उपयोग, टैबलेट की बहुत अधिक मेमोरी का उपयोग करके उसे धीमा या अस्थिर कर सकता है."</string> <string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"ऐप को स्िटकी प्रसारण भेजने देती है, जो प्रसारण बंद होने के बाद भी बने रहते हैं. अत्यधिक उपयोग से टीवी धीमा या अस्थिर हो सकता है जिससे वह बहुत सारी मेमोरी का उपयोग कर सकता है."</string> <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"ऐप्स को स्टिकी प्रसारण भेजने देता है, जो प्रसारण समाप्त होने के बाद भी बने रहते हैं. अत्यधिक उपयोग, फ़ोन की बहुत अधिक मेमोरी का उपयोग करके उसे धीमा या अस्थिर कर सकता है."</string> <string name="permlab_readContacts" msgid="8348481131899886131">"अपने संपर्क पढ़ें"</string> - <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"ऐप्स को आपके टेबलेट में संग्रहित संपर्कों के डेटा को, साथ ही आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्य तरीके से डॉयलॉग करने की आवृत्ति को पढ़ने देता है. यह अनुमति ऐप्स को आपके संपर्क डेटा को सहेजने देती है, और दुर्भावनापूर्ण ऐप्स आपकी जानकारी के बिना संपर्क डेटा को साझा कर सकते हैं."</string> - <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"ऐप को आपके टीवी पर संग्रहित आपके संपर्कों का डेटा पढ़ने देती है, जिसमें आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल भेजने या उनसे संचार करने की आवृत्ति भी शामिल होती है. यह अनुमति ऐप्स को आपका संपर्क डेटा सहेजने देती है और दुर्भावनापूर्ण ऐप्स संपर्क डेटा को आपकी जानकारी के बिना साझा कर सकते हैं."</string> - <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"ऐप्स को आपके फ़ोन में संग्रहित संपर्कों के डेटा को, साथ ही आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्य तरीके से डॉयलॉग करने की आवृत्ति को पढ़ने देता है. यह अनुमति ऐप्स को आपके संपर्क डेटा को सहेजने देती है, और दुर्भावनापूर्ण ऐप्स आपकी जानकारी के बिना संपर्क डेटा को साझा कर सकते हैं."</string> + <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"ऐप को आपके टैबलेट पर मौजूद आपके संपर्कों का डेटा पढ़ने देती है, जिसमें ये भी शामिल है कि आपने कुछ ख़ास लोगों से कितनी बार कॉल, ईमेल, या कुछ और तरीकों से बातचीत की. यह अनुमति ऐप को आपका संपर्क डेटा सेव करने देती है और धोखा देने वाले ऐप संपर्क डेटा को आपकी जानकारी के बिना शेयर कर सकते हैं."</string> + <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"ऐप को आपके टीवी पर मौजूद आपके संपर्कों का डेटा पढ़ने देती है, जिसमें ये भी शामिल है कि आपने कुछ ख़ास लोगों से कितनी बार कॉल, ईमेल, या कुछ और तरीकों से बातचीत की. यह अनुमति ऐप को आपका संपर्क डेटा सेव करने देती है और धोखा देने वाले ऐप संपर्क डेटा को आपकी जानकारी के बिना शेयर कर सकते हैं."</string> + <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"ऐप को आपके फ़ोन पर मौजूद आपके संपर्कों का डेटा पढ़ने देती है, जिसमें ये भी शामिल है कि आपने कुछ ख़ास लोगों से कितनी बार कॉल, ईमेल, या कुछ और तरीकों से बातचीत की. यह अनुमति ऐप को आपका संपर्क डेटा सेव करने देती है और धोखा देने वाले ऐप, संपर्क डेटा को आपकी जानकारी के बिना शेयर कर सकते हैं."</string> <string name="permlab_writeContacts" msgid="5107492086416793544">"अपने संपर्क बदलें"</string> - <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"ऐप्स को आपके टेबलेट में संग्रहित संपर्कों के डेटा को, साथ ही आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्य तरीके से डॉयलॉग करने की आवृत्ति को संशोधित करने देता है. यह अनुमति ऐप्स को आपके संपर्क डेटा को हटाने देती है."</string> + <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"ऐप्स को आपके टैबलेट में संग्रहित संपर्कों के डेटा को, साथ ही आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्य तरीके से डॉयलॉग करने की आवृत्ति को संशोधित करने देता है. यह अनुमति ऐप्स को आपके संपर्क डेटा को हटाने देती है."</string> <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"ऐप को आपके टीवी पर संग्रहित आपके संपर्कों के बारे में संग्रहित डेटा में बदलाव करने देती है, जिसमें आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल भेजने या अन्य तरीकों से संचार किए जाने की आवृत्ति भी शामिल है. यह अनुमति ऐप्स को संपर्क डेटा हटाने देती है."</string> <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"ऐप्स को आपके फ़ोन में संग्रहित संपर्कों के डेटा को, साथ ही आपके द्वारा विशिष्ट व्यक्तियों को कॉल करने, ईमेल करने, या अन्य तरीके से डॉयलॉग करने की आवृत्ति को संशोधित करने देता है. यह अनुमति ऐप्स को आपके संपर्क डेटा को हटाने देती है."</string> <string name="permlab_readCallLog" msgid="3478133184624102739">"कॉल लॉग पढ़ें"</string> @@ -378,7 +378,7 @@ <string name="permdesc_readCalendar" product="tablet" msgid="4993979255403945892">"यह ऐप्लिकेशन आपके टैबलेट पर संग्रहित सभी कैलेंडर इवेंट पढ़ सकता है और आपका कैलेंडर डेटा साझा कर सकता है या सहेज सकता है."</string> <string name="permdesc_readCalendar" product="tv" msgid="8837931557573064315">"यह ऐप्लिकेशन आपके टीवी पर संग्रहित सभी कैलेंडर इवेंट पढ़ सकता है और आपका कैलेंडर डेटा साझा कर सकता है या सहेज सकता है."</string> <string name="permdesc_readCalendar" product="default" msgid="4373978642145196715">"यह ऐप्लिकेशन आपके फ़ोन पर संग्रहित सभी कैलेंडर इवेंट पढ़ सकता है और आपका कैलेंडर डेटा साझा कर सकता है या सहेज सकता है."</string> - <string name="permlab_writeCalendar" msgid="8438874755193825647">"अपनी जानकारी के बिना कैलेंडर इवेंट जोड़ें या संशोधित करें और अतिथियों को ईमेल भेजें"</string> + <string name="permlab_writeCalendar" msgid="8438874755193825647">"आपकी जानकारी के बिना कैलेंडर इवेंट जोड़ें या उनमें बदलाव करें और अतिथियों को ईमेल भेजें"</string> <string name="permdesc_writeCalendar" product="tablet" msgid="1675270619903625982">"यह ऐप्लिकेशन आपके टैबलेट पर मौजूद कैलेंडर इवेंट जोड़, निकाल या बदल सकता है. यह ऐप्लिकेशन ऐसे संदेश भेज सकता है जो कैलेंडर स्वामियों से आए हुए लग सकते हैं या यह स्वामियों को सूचित किए बिना इवेंट में बदलाव कर सकता है."</string> <string name="permdesc_writeCalendar" product="tv" msgid="9017809326268135866">"यह ऐप्लिकेशन आपके टीवी पर मौजूद कैलेंडर इवेंट जोड़, निकाल या बदल सकता है. यह ऐप्लिकेशन ऐसे संदेश भेज सकता है जो कैलेंडर स्वामियों से आए हुए लग सकते हैं या यह स्वामियों को सूचित किए बिना इवेंट में बदलाव कर सकता है."</string> <string name="permdesc_writeCalendar" product="default" msgid="7592791790516943173">"यह ऐप्लिकेशन आपके फ़ोन पर मौजूद कैलेंडर इवेंट जोड़, निकाल या बदल सकता है. यह ऐप्लिकेशन ऐसे संदेश भेज सकता है जो कैलेंडर स्वामियों से आए हुए लग सकते हैं या यह स्वामियों को सूचित किए बिना इवेंट में बदलाव कर सकता है."</string> @@ -394,11 +394,11 @@ <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ऐप्स को वैश्विक ऑडियो सेटिंग, जैसे वॉल्यूम और कौन-सा स्पीकर आउटपुट के लिए उपयोग किया गया, संशोधित करने देता है."</string> <string name="permlab_recordAudio" msgid="3876049771427466323">"ऑडियो रिकॉर्ड करने"</string> <string name="permdesc_recordAudio" msgid="4245930455135321433">"यह ऐप्लिकेशन किसी भी समय माइक्रोफ़ोन का उपयोग करके ऑडियो रिकॉर्ड कर सकता है."</string> - <string name="permlab_sim_communication" msgid="2935852302216852065">"SIM पर आदेश भेजें"</string> - <string name="permdesc_sim_communication" msgid="5725159654279639498">"ऐप्स को सिम में आदेश भेजने देती है. यह बहुत ही खतरनाक है."</string> + <string name="permlab_sim_communication" msgid="2935852302216852065">"सिम पर निर्देश भेजें"</string> + <string name="permdesc_sim_communication" msgid="5725159654279639498">"ऐप को सिम पर निर्देश भेजने देती है. यह बहुत ही खतरनाक है."</string> <string name="permlab_camera" msgid="3616391919559751192">"चित्र और वीडियो लें"</string> <string name="permdesc_camera" msgid="5392231870049240670">"यह ऐप्लिकेशन किसी भी समय कैमरे का उपयोग करके चित्र ले सकता है और वीडियो रिकॉर्ड कर सकता है."</string> - <string name="permlab_vibrate" msgid="7696427026057705834">"कंपन नियंत्रित करें"</string> + <string name="permlab_vibrate" msgid="7696427026057705834">"कंपन (वाइब्रेशन) को नियंत्रित करें"</string> <string name="permdesc_vibrate" msgid="6284989245902300945">"ऐप्स को कंपनकर्ता नियंत्रित करने देता है."</string> <string name="permlab_callPhone" msgid="3925836347681847954">"फ़ोन नंबर पर सीधे कॉल करें"</string> <string name="permdesc_callPhone" msgid="3740797576113760827">"ऐप्स को आपके हस्तक्षेप के बिना फ़ोन नंबर पर कॉल करने देता है. इसके परिणाम अप्रत्याशित शुल्क या कॉल हो सकते हैं. ध्यान दें कि यह ऐप्स को आपातकालीन नंबर पर कॉल नहीं करने देता. दुर्भावनापूर्ण ऐप्स आपकी पुष्टि के बिना कॉल करके आपका धन व्यय कर सकते हैं."</string> @@ -410,14 +410,14 @@ <string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"कॉल करने के अनुभव को बेहतर बनाने के लिए ऐप्लिकेशन को सिस्टम के माध्यम से उसके कॉल रूट करने देती है."</string> <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"फ़ोन नंबर पढ़ना"</string> <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"ऐप्लिकेशन को डिवाइस के फ़ोन नंबर एक्सेस करने देती है."</string> - <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"टेबलेट को सोने (कम बैटरी मोड) से रोकें"</string> + <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"टैबलेट को सोने (कम बैटरी मोड) से रोकें"</string> <string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"टीवी को सोने (कम बैटरी मोड) से रोकें"</string> <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"टीवी को सोने (कम बैटरी मोड) से रोकें"</string> - <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"ऐप्स को टेबलेट को प्रयोग में नहीं हो जाने से रोकता है."</string> + <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"ऐप्स को टैबलेट को प्रयोग में नहीं हो जाने से रोकता है."</string> <string name="permdesc_wakeLock" product="tv" msgid="3208534859208996974">"ऐप को टीवी को सोने (कम बैटरी मोड) से रोकने की अनुमति देता है."</string> <string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"ऐप्स को फ़ोन को प्रयोग में नहीं होने से रोकता है."</string> <string name="permlab_transmitIr" msgid="7545858504238530105">"इंफ़्रारेड संचारित करें"</string> - <string name="permdesc_transmitIr" product="tablet" msgid="5358308854306529170">"ऐप्लिकेशन को टेबलेट के इंफ़्रारेड ट्रांसमीटर का उपयोग करने देती है."</string> + <string name="permdesc_transmitIr" product="tablet" msgid="5358308854306529170">"ऐप्लिकेशन को टैबलेट के इंफ़्रारेड ट्रांसमीटर का उपयोग करने देती है."</string> <string name="permdesc_transmitIr" product="tv" msgid="3926790828514867101">"ऐप को टीवी के इंफ़्रारेड ट्रांसमीटर का उपयोग करने देती है."</string> <string name="permdesc_transmitIr" product="default" msgid="7957763745020300725">"ऐप्लिकेशन को फ़ोन के इंफ़्रारेड ट्रांसमीटर का उपयोग करने देती है."</string> <string name="permlab_setWallpaper" msgid="6627192333373465143">"वॉलपेपर सेट करें"</string> @@ -425,15 +425,15 @@ <string name="permlab_setWallpaperHints" msgid="3278608165977736538">"अपने वॉलपेपर का आकार एडजस्ट करें"</string> <string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"ऐप्स को सिस्टम वॉलपेपर आकार संकेत सेट करने देता है."</string> <string name="permlab_setTimeZone" msgid="2945079801013077340">"समय क्षेत्र सेट करें"</string> - <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"ऐप्स को टेबलेट का समय क्षेत्र बदलने देता है."</string> + <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"ऐप्स को टैबलेट का समय क्षेत्र बदलने देता है."</string> <string name="permdesc_setTimeZone" product="tv" msgid="888864653946175955">"ऐप को टीवी का समय क्षेत्र बदलने देती है."</string> - <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"ऐप्स को टेबलेट का समय क्षेत्र बदलने देता है."</string> + <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"ऐप्स को टैबलेट का समय क्षेत्र बदलने देता है."</string> <string name="permlab_getAccounts" msgid="1086795467760122114">"डिवाइस पर खाते ढूंढें"</string> - <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"ऐप्स को टेबलेट द्वारा ज्ञात खातों की सूची प्राप्त करने देता है. इसमें वे खाते शामिल हो सकते हैं जिन्हें आपके द्वारा इंस्टॉल किए गए ऐप्स ने बनाया है."</string> + <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"ऐप्स को टैबलेट द्वारा ज्ञात खातों की सूची प्राप्त करने देता है. इसमें वे खाते शामिल हो सकते हैं जिन्हें आपके द्वारा इंस्टॉल किए गए ऐप्स ने बनाया है."</string> <string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"ऐप को टीवी द्वारा ज्ञात खातों की सूची प्राप्त करने देती है. इसमें आपके द्वारा इंस्टॉल किए गए ऐप्लिकेशन के द्वारा बनाए गए खाते शामिल हो सकते हैं."</string> <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"ऐप्स को फ़ोन द्वारा ज्ञात खातों की सूची प्राप्त करने देता है. इसमें वे खाते शामिल हो सकते हैं जिन्हें आपके द्वारा इंस्टॉल किए गए ऐप्स ने बनाया है."</string> <string name="permlab_accessNetworkState" msgid="4951027964348974773">"नेटवर्क कनेक्शन देखें"</string> - <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"ऐप्स को नेटवर्क कनेक्शन के बारे में जानकारी देखने देता है जैसे कौन से नेटवर्क मौजूद हैं और कनेक्ट हैं."</string> + <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"ऐप को नेटवर्क कनेक्शन के बारे में जानकारी देखने देता है, जैसे कौन से नेटवर्क मौजूद हैं और कनेक्ट हैं."</string> <string name="permlab_createNetworkSockets" msgid="7934516631384168107">"पूर्ण नेटवर्क एक्सेस पाएं"</string> <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"ऐप्स को नेटवर्क सॉकेट बनाने और कस्टम नेटवर्क प्रोटोकॉल का उपयोग करने देता है. ब्राउज़र और अन्य ऐप्स इंटरनेट को डेटा भेजने के साधन उपलब्ध कराते हैं, ताकि इंटरनेट को डेटा भेजने के लिए इस अनुमति की आवश्यकता नहीं हो."</string> <string name="permlab_changeNetworkState" msgid="958884291454327309">"नेटवर्क कनेक्टिविटी बदलें"</string> @@ -441,25 +441,25 @@ <string name="permlab_changeTetherState" msgid="5952584964373017960">"टेदर की गई कनेक्टिविटी बदलें"</string> <string name="permdesc_changeTetherState" msgid="1524441344412319780">"ऐप्स को टेदर की गई नेटवर्क कनेक्टिविटी की स्थिति बदलने देता है."</string> <string name="permlab_accessWifiState" msgid="5202012949247040011">"वाई-फ़ाई कनेक्शन देखें"</string> - <string name="permdesc_accessWifiState" msgid="5002798077387803726">"ऐप्स को वाई-फ़ाई नेटवर्क के बारे में जानकारी, जैसे WI-Fi सक्षम है या नहीं और कनेक्ट किए गए वाई-फ़ाई डिवाइस के नाम, देखने देता है."</string> + <string name="permdesc_accessWifiState" msgid="5002798077387803726">"ऐप को वाई-फ़ाई नेटवर्क के बारे में जानकारी, जैसे WI-Fi चालू है या नहीं और कनेक्ट किए गए वाई-फ़ाई डिवाइस के नाम, देखने देता है."</string> <string name="permlab_changeWifiState" msgid="6550641188749128035">"वाई-फ़ाई से कनेक्ट और डिस्कनेक्ट करें"</string> <string name="permdesc_changeWifiState" msgid="7137950297386127533">"ऐप्स को वाई-फ़ाई पहुंच बिंदुओं से कनेक्ट और डिसकनेक्ट करने और वाई-फ़ाई नेटवर्क के लिए डिवाइस कॉन्फ़िगरेशन में परिवर्तन करने देता है."</string> <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"वाई-फ़ाई मल्टीकास्ट प्राप्ति को अनुमति दें"</string> - <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"ऐप्स को वाई-फ़ाई नेटवर्क पर मल्टीकास्ट पते के उपयोग से केवल आपके टेबलेट पर ही नहीं, बल्कि सभी डिवाइस पर भेजे गए पैकेट प्राप्त करने देता है. यह गैर-मल्टीकास्ट मोड से अधिक पावर का उपयोग करता है."</string> + <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"ऐप्स को वाई-फ़ाई नेटवर्क पर मल्टीकास्ट पते के उपयोग से केवल आपके टैबलेट पर ही नहीं, बल्कि सभी डिवाइस पर भेजे गए पैकेट प्राप्त करने देता है. यह गैर-मल्टीकास्ट मोड से अधिक पावर का उपयोग करता है."</string> <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"ऐप को मल्टीकास्ट पतों का उपयोग करके ना केवल आपके टीवी को, बल्कि वाई-फ़ाई पर मौजूद सभी डिवाइसों को पैकेट भेजने और प्राप्त करने देती है. इसमें गैर-मल्टीकास्ट मोड की अपेक्षा अधिक पावर का उपयोग होता है."</string> <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"ऐप्स को वाई-फ़ाई नेटवर्क पर मल्टीकास्ट पते के उपयोग से केवल आपके फ़ोन पर ही नहीं, बल्कि सभी डिवाइस पर भेजे गए पैकेट प्राप्त करने देता है. यह गैर-मल्टीकास्ट मोड से अधिक पावर का उपयोग करता है."</string> <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"ब्लूटूथ सेटिंग पर पहुंचें"</string> - <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"किसी ऐप्स को स्थानीय ब्लूटूथ टेबलेट कॉन्फ़िगर करने की और रिमोट डिवाइस के साथ खोजने और युग्मित करने देता है."</string> + <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"किसी ऐप्स को स्थानीय ब्लूटूथ टैबलेट कॉन्फ़िगर करने की और रिमोट डिवाइस के साथ खोजने और युग्मित करने देता है."</string> <string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"ऐप को स्थानीय ब्लूटूथ टीवी कॉन्फ़िगर करने देती है और दूरस्थ डिवाइसों को खोजने और उनसे युग्मित करने देती है."</string> <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"ऐप्स को स्थानीय ब्लूटूथ फ़ोन कॉन्फ़िगर करने देता है, और रिमोट डिवाइस के साथ खोजने और युग्मित करने देता है."</string> <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAX से कनेक्ट और डिसकनेक्ट करें"</string> - <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"ऐप्स को WiMAX सक्षम है या नहीं और कनेक्ट किए गए किसी WiMAX नेटवर्क के बारे में जानकारी निर्धारित करने देता है."</string> + <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"ऐप को तय करने देता है कि WiMAX चालू है या नहीं और कनेक्ट किए गए किसी WiMAX नेटवर्क के बारे में जानकारी लेने देता है."</string> <string name="permlab_changeWimaxState" msgid="340465839241528618">"WiMAX स्थिति बदलें"</string> - <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"ऐप्स को WiMAX नेटवर्क से टेबलेट को कनेक्ट और डिस्कनेक्ट करने देता है."</string> + <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"ऐप्स को WiMAX नेटवर्क से टैबलेट को कनेक्ट और डिस्कनेक्ट करने देता है."</string> <string name="permdesc_changeWimaxState" product="tv" msgid="6022307083934827718">"ऐप को, टीवी को WiMAX नेटवर्कों से कनेक्ट करने और उनसे डिस्कनेक्ट करने देती है."</string> <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"ऐप्स को WiMAX नेटवर्क से फ़ोन को कनेक्ट और डिस्कनेक्ट करने देता है."</string> <string name="permlab_bluetooth" msgid="6127769336339276828">"ब्लूटूथ डिवाइस को दूसरे डिवाइस से जोड़ें"</string> - <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"ऐप्स को टेबलेट पर ब्लूटूथ का कॉन्फ़िगरेशन देखने, और युग्मित डिवाइस के साथ कनेक्शन बनाने और स्वीकार करने देता है."</string> + <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"ऐप्स को टैबलेट पर ब्लूटूथ का कॉन्फ़िगरेशन देखने, और युग्मित डिवाइस के साथ कनेक्शन बनाने और स्वीकार करने देता है."</string> <string name="permdesc_bluetooth" product="tv" msgid="3974124940101104206">"ऐप को टीवी पर ब्लूटूथ का कॉन्फ़िगरेशन देखने देती है और युग्मित डिवाइसों के साथ कनेक्शन बनाने और स्वीकार करने देती है."</string> <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"ऐप्स को फ़ोन पर ब्लूटूथ का कॉन्फ़िगरेशन देखने, और युग्मित डिवाइस के साथ कनेक्शन बनाने और स्वीकार करने देता है."</string> <string name="permlab_nfc" msgid="4423351274757876953">"नियर फ़ील्ड कम्यूनिकेशन नियंत्रित करें"</string> @@ -487,7 +487,7 @@ <string name="fingerprint_name_template" msgid="5870957565512716938">"अंगुली <xliff:g id="FINGERID">%d</xliff:g>"</string> <string-array name="fingerprint_error_vendor"> </string-array> - <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"फ़िंगरप्रिंट आइकन"</string> + <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"फ़िंगरप्रिंट आइकॉन"</string> <string name="permlab_readSyncSettings" msgid="6201810008230503052">"समन्वयन सेटिंग पढ़ें"</string> <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ऐप्स को किसी खाते की समन्वयन सेटिंग पढ़ने देता है. उदाहरण के लिए, इससे यह निर्धारित किया जा सकता है कि लोग ऐप्स किसी खाते के साथ समन्वयित है या नहीं."</string> <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"समन्वयन बंद या चालू टॉगल करें"</string> @@ -504,28 +504,28 @@ <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"ऐप्स को SD कार्ड पर लिखने देता है."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP कॉल करें/प्राप्त करें"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"ऐप्स को SIP कॉल करने और प्राप्त करने देती है."</string> - <string name="permlab_register_sim_subscription" msgid="3166535485877549177">"नए टेलिकॉम सिम कनेक्शन पंजीकृत करें"</string> + <string name="permlab_register_sim_subscription" msgid="3166535485877549177">"नए टेलिकॉम सिम कनेक्शन रजिस्टर करें"</string> <string name="permdesc_register_sim_subscription" msgid="2138909035926222911">"ऐप को नए टेलिकॉम सिम कनेक्शन पंजीकृत करने देती है."</string> - <string name="permlab_register_call_provider" msgid="108102120289029841">"नए टेलिकॉम कनेक्शन पंजीकृत करें"</string> + <string name="permlab_register_call_provider" msgid="108102120289029841">"नए टेलिकॉम कनेक्शन रजिस्टर करें"</string> <string name="permdesc_register_call_provider" msgid="7034310263521081388">"ऐप को नए टेलिकॉम कनेक्शन पंजीकृत करने देती है."</string> <string name="permlab_connection_manager" msgid="1116193254522105375">"टेलीकॉम कनेक्शन प्रबंधित करें"</string> <string name="permdesc_connection_manager" msgid="5925480810356483565">"ऐप को टेलीकॉम कनेक्शन प्रबंधित करने देती है."</string> <string name="permlab_bind_incall_service" msgid="6773648341975287125">"इन-कॉल स्क्रीन से सहभागिता करें"</string> - <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"ऐप्स को यह नियंत्रित करने देती है कि उपयोगकर्ता को इन-कॉल स्क्रीन कब और कैसी दिखाई देती है."</string> + <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"ऐप को यह नियंत्रित करने देती है कि उपयोगकर्ता को इन-कॉल स्क्रीन कब और कैसी दिखाई देती है."</string> <string name="permlab_bind_connection_service" msgid="3557341439297014940">"टेलीफ़ोनी सेवाओं के साथ सहभागिता करें"</string> <string name="permdesc_bind_connection_service" msgid="4008754499822478114">"कॉल करने/प्राप्त करने के लिए ऐप्स को टेलीफ़ोनी सेवा के साथ सहभागिता करने दें."</string> - <string name="permlab_control_incall_experience" msgid="9061024437607777619">"इन कॉल उपयोगकर्ता अनुभव प्रदान करना"</string> - <string name="permdesc_control_incall_experience" msgid="915159066039828124">"ऐप्स को इन कॉल उपयोगकर्ता अनुभव लेने देती है."</string> + <string name="permlab_control_incall_experience" msgid="9061024437607777619">"इन कॉल उपयोगकर्ता अनुभव लें"</string> + <string name="permdesc_control_incall_experience" msgid="915159066039828124">"ऐप को इन कॉल उपयोगकर्ता अनुभव लेने देती है."</string> <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"ऐतिहासिक नेटवर्क उपयोग पढें"</string> <string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"किसी ऐप्स को विशिष्ट नेटवर्क और ऐप्स के लिए ऐतिहासिक नेटवर्क उपयोग को पढ़ने देता है."</string> <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"नेटवर्क नीति प्रबंधित करें"</string> <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"ऐप्स को नेटवर्क नीतियां प्रबंधित करने और ऐप्स-विशिष्ट नियमों को परिभाषित करने देता है."</string> <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"नेटवर्क उपयोग हिसाब बदलें"</string> <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"ऐप्स को यह संशोधित करने देता है कि ऐप्स की तुलना में नेटवर्क उपयोग का मूल्यांकन कैसे किया जाता है. सामान्य ऐप्स द्वारा उपयोग करने के लिए नहीं."</string> - <string name="permlab_accessNotifications" msgid="7673416487873432268">"नोटिफ़िकेशन तक पहुंचें"</string> - <string name="permdesc_accessNotifications" msgid="458457742683431387">"ऐप्स को नोटिफ़िकेशन को प्राप्त करने, जांच करने, और साफ़ करने देता है, जिनमें अन्य ऐप्स के द्वारा पोस्ट की गई सूचनाएं भी शामिल हैं."</string> - <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"नोटिफ़िकेशन श्रवणकर्ता सेवा से जुड़ें"</string> - <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"धारक को नोटिफ़िकेशन श्रवणकर्ता सेवा के शीर्ष स्तरीय इंटरफ़ेस से जुड़ने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होनी चाहिए."</string> + <string name="permlab_accessNotifications" msgid="7673416487873432268">"सूचना तक पहुंचें"</string> + <string name="permdesc_accessNotifications" msgid="458457742683431387">"ऐप को सूचना पाने, जांच करने और साफ़ करने देता है, जिनमें अन्य ऐप के ज़रिए पोस्ट की गई सूचनाएं भी शामिल हैं."</string> + <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"सूचना श्रवणकर्ता सेवा से जुड़ें"</string> + <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"उपयोगकर्ता को सूचना सुनने वाली सेवा के सबसे बेहतर इंटरफ़ेस से जुड़ने देती है. सामान्य ऐप के लिए कभी भी इसकी ज़रुरत नहीं होगी."</string> <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"किसी स्थिति प्रदाता सेवा से आबद्ध हों"</string> <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"धारक को किसी स्थिति प्रदाता सेवा के शीर्ष-स्तर के इंटरफ़ेस से आबद्ध होने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string> <string name="permlab_bindDreamService" msgid="4153646965978563462">"भावी सेवा से आबद्ध करें"</string> @@ -551,18 +551,18 @@ <string name="policylab_limitPassword" msgid="4497420728857585791">"पासवर्ड नियम सेट करें"</string> <string name="policydesc_limitPassword" msgid="2502021457917874968">"स्क्रीन लॉक पासवर्ड तथा पिन की लंबाई और उसमें अनुमत वर्णों को नियंत्रित करें."</string> <string name="policylab_watchLogin" msgid="5091404125971980158">"स्क्रीन अनलॉक करने की कोशिशों की निगरानी करें"</string> - <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"स्क्रीन को अनलॉक करते समय गलत लिखे गए पासवर्ड की संख्या पर निगरानी करें, और बहुत अधिक बार गलत पासवर्ड लिखे जाने पर टेबलेट लॉक करें या टेबलेट का संपूर्ण डेटा मिटाएं."</string> + <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"स्क्रीन को अनलॉक करते समय गलत लिखे गए पासवर्ड की संख्या पर निगरानी करें, और बहुत अधिक बार गलत पासवर्ड लिखे जाने पर टैबलेट लॉक करें या टैबलेट का संपूर्ण डेटा मिटाएं."</string> <string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"स्क्रीन को अनलॉक करते समय गलत तरीके से लिखे गए पासवर्ड पर नज़र रखें और यदि बहुत अधिक गलत पासवर्ड लिखे जाते हैं तो टीवी को लॉक करें या टीवी का सभी डेटा मिटा दें."</string> <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"गलत लिखे गए पासवर्ड की संख्या पर निगरानी करें. स्क्रीन अनलॉक करते समय, बहुत अधिक बार गलत पासवर्ड लिखे जाने पर फ़ोन लॉक करें या फ़ोन का संपूर्ण डेटा मिटाएं."</string> - <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"स्क्रीन को अनलॉक करते समय गलत तरीके से लिखे गए पासवर्ड पर नज़र रखें और यदि बार बार अधिक पासवर्ड लिखे जाते हैं तो टैबलेट को लॉक करें या इस उपयोगकर्ता का सभी डेटा मिटा दें."</string> - <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"स्क्रीन को अनलॉक करते समय गलत तरीके से लिखे गए पासवर्ड पर नज़र रखें यदि बार बार गलत पासवर्ड लिखे जाने पर टीवी को लॉक करें या इस उपयोगकर्ता का सभी डेटा मिटा दें."</string> - <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"स्क्रीन को अनलॉक करते समय गलत तरीके से लिखे गए पासवर्ड पर नज़र रखें और यदि बार बार गलत पासवर्ड लिखे जाते हैं तो फ़ोन को लॉक करें या इस उपयोगकर्ता का सभी डेटा मिटा दें."</string> + <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"स्क्रीन का लॉक खोलते समय गलत तरीके से लिखे गए पासवर्ड पर नज़र रखें, और अगर बार-बार अधिक पासवर्ड लिखे जाते हैं तो टैबलेट को लॉक करें या इस उपयोगकर्ता का सभी डेटा मिटा दें."</string> + <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"स्क्रीन का लॉक खोलते समय गलत तरीके से लिखे गए पासवर्ड पर नज़र रखें, और अगर बार-बार गलत पासवर्ड लिखा जाता है तो टीवी को लॉक करें या इस उपयोगकर्ता का सभी डेटा मिटा दें."</string> + <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"स्क्रीनका लॉक खोलते समय गलत तरीके से लिखे गए पासवर्ड पर नज़र रखें, और अगर बार-बार गलत पासवर्ड लिखा जाता है तो फ़ोन को लॉक करें या इस उपयोगकर्ता का सभी डेटा मिटा दें."</string> <string name="policylab_resetPassword" msgid="4934707632423915395">"स्क्रीन लॉक बदलें"</string> <string name="policydesc_resetPassword" msgid="1278323891710619128">"स्क्रीन लॉक को बदलें."</string> <string name="policylab_forceLock" msgid="2274085384704248431">"स्क्रीन लॉक करें"</string> <string name="policydesc_forceLock" msgid="1141797588403827138">"नियंत्रित करें कि स्क्रीन कैसे और कब लॉक हो."</string> <string name="policylab_wipeData" msgid="3910545446758639713">"सभी डेटा हटाएं"</string> - <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"फ़ैक्टरी डेटा रीसेट करके, चेतावनी दिए बिना टेबलेट का डेटा मिटाएं."</string> + <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"फ़ैक्टरी डेटा रीसेट करके, चेतावनी दिए बिना टैबलेट का डेटा मिटाएं."</string> <string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"फ़ैक्टरी डेटा रीसेट करके, चेतावनी दिए बिना टीवी का डेटा मिटाएं."</string> <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"फ़ैक्टरी डेटा रीसेट करके, चेतावनी दिए बिना फ़ोन का डेटा मिटाएं."</string> <string name="policylab_wipeData_secondaryUser" msgid="8362863289455531813">"उपयोगकर्ता डेटा मिटाएं"</string> @@ -573,7 +573,7 @@ <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"नीति सक्षम होने के दौरान डिवाइस वैश्विक प्रॉक्सी सेट करें. केवल डिवाइस स्वामी ही वैश्विक प्रॉक्सी सेट कर सकता है."</string> <string name="policylab_expirePassword" msgid="5610055012328825874">"स्क्रीन लॉक पासवर्ड समाप्ति सेट करें"</string> <string name="policydesc_expirePassword" msgid="5367525762204416046">"यह बदलें कि स्क्रीन लॉक पासवर्ड, पिन या पैटर्न को कितने समय में बदला जाना चाहिए."</string> - <string name="policylab_encryptedStorage" msgid="8901326199909132915">"मेमोरी एन्क्रिप्शन सेट करें"</string> + <string name="policylab_encryptedStorage" msgid="8901326199909132915">"मेमोरी को सुरक्षित करने का तरीका सेट करें"</string> <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"संग्रहित ऐप्स डेटा को एन्क्रिप्ट किया जाना आवश्यक है."</string> <string name="policylab_disableCamera" msgid="6395301023152297826">"कैमरों को अक्षम करें"</string> <string name="policydesc_disableCamera" msgid="2306349042834754597">"सभी डिवाइस कैमरों का उपयोग रोकें."</string> @@ -642,7 +642,7 @@ <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"कार्यालय का मोबाइल"</string> <string name="phoneTypeWorkPager" msgid="649938731231157056">"कार्यालय का पेजर"</string> <string name="phoneTypeAssistant" msgid="5596772636128562884">"सहायक"</string> - <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string> + <string name="phoneTypeMms" msgid="7254492275502768992">"मल्टीमीडिया मैसेज (एमएमएस)"</string> <string name="eventTypeCustom" msgid="7837586198458073404">"कस्टम"</string> <string name="eventTypeBirthday" msgid="2813379844211390740">"जन्मदिन"</string> <string name="eventTypeAnniversary" msgid="3876779744518284000">"वर्षगांठ"</string> @@ -701,12 +701,12 @@ <string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"अनलॉक करने के लिए पासवर्ड लिखें"</string> <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"अनलॉक करने के लिए पिन लिखें"</string> <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"गलत पिन कोड."</string> - <string name="keyguard_label_text" msgid="861796461028298424">"अनलॉक करने के लिए, मेनू दबाएं और फिर 0 दबाएं."</string> + <string name="keyguard_label_text" msgid="861796461028298424">"लॉक खोलने के लिए, मेन्यू दबाएं और फिर 0 दबाएं."</string> <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"आपातकालीन नंबर"</string> <string name="lockscreen_carrier_default" msgid="6169005837238288522">"कोई सेवा नहीं"</string> <string name="lockscreen_screen_locked" msgid="7288443074806832904">"स्क्रीन लॉक की गई है."</string> - <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"अनलॉक करने के लिए मेनू दबाएं या आपातलकालीन कॉल करें."</string> - <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"अनलॉक करने के लिए मेनू दबाएं."</string> + <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"लॉक खोलने के लिए मेन्यू दबाएं या आपातलकालीन कॉल करें."</string> + <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"लॉक खोलने के लिए मेन्यू दबाएं."</string> <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"अनलॉक करने के लिए आकार आरेखित करें"</string> <string name="lockscreen_emergency_call" msgid="5298642613417801888">"आपातकाल"</string> <string name="lockscreen_return_to_call" msgid="5244259785500040021">"कॉल पर वापस लौटें"</string> @@ -716,7 +716,7 @@ <string name="lockscreen_storage_locked" msgid="9167551160010625200">"सभी सुविधाओं और डेटा के लिए अनलॉक करें"</string> <string name="faceunlock_multiple_failures" msgid="754137583022792429">"मालिक का चेहरा पहचानकर अनलॉक करने की तय सीमा खत्म हो गई"</string> <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"कोई सिम कार्ड नहीं है"</string> - <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"टेबलेट में कोई सिम कार्ड नहीं है."</string> + <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"टैबलेट में कोई सिम कार्ड नहीं है."</string> <string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"टीवी में कोई SIM कार्ड नहीं है."</string> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"फ़ोन में कोई सिम कार्ड नहीं है."</string> <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"कोई सिमकार्ड डालें."</string> @@ -733,19 +733,19 @@ <string name="emergency_calls_only" msgid="6733978304386365407">"केवल आपातकालीन कॉल"</string> <string name="lockscreen_network_locked_message" msgid="143389224986028501">"नेटवर्क लॉक किया गया"</string> <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"सिम कार्ड PUK-लॉक किया हुआ है."</string> - <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"कृपया उपयोगकर्ता मार्गदर्शिका देखें या ग्राहक सहायता से संपर्क करें."</string> + <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"कृपया उपयोग के लिए गाइड देखें या ग्राहक सहायता से संपर्क करें."</string> <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"सिम कार्ड लॉक किया गया है."</string> <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"सिम कार्ड अनलॉक कर रहा है…"</string> <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"आपने अपना अनलॉक आकार <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत बनाया है. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंड में पुन: प्रयास करें."</string> <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"आपने अपना पासवर्ड <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से लिखा है. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंड में पुन: प्रयास करें."</string> <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"आपने अपना पिन <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से लिखा है. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंड में फिर से प्रयास करें."</string> - <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"आपने अपना अनलॉक आकार <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत बनाया है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने Google साइन-इन का उपयोग करके आपके टेबलेट को अनलॉक करने को कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड में पुन: प्रयास करें."</string> + <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"आपने अपना अनलॉक आकार <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत बनाया है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने Google साइन-इन का उपयोग करके आपके टैबलेट को अनलॉक करने को कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड में पुन: प्रयास करें."</string> <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"आपने अपना अनलॉक पैटन <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से बनाया है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने टीवी को अपने Google साइन-इन का उपयोग करके अनलॉक करने के लिए कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड में पुन: प्रयास करें."</string> <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"आपने अपना अनलॉक आकार <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत बनाया है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने Google साइन-इन का उपयोग करके आपके फ़ोन को अनलॉक करने को कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड में पुन: प्रयास करें."</string> - <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"आप गलत तरीके से टेबलेट को अनलॉक करने का प्रयास <xliff:g id="NUMBER_0">%1$d</xliff:g> बार कर चुके हैं. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल प्रयास के बाद, टेबलेट फ़ैक्टरी डिफ़ॉल्ट पर रीसेट हो जाएगा और सभी उपयोगकर्ता डेटा खो जाएगा."</string> - <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="950408382418270260">"आपने टीवी को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से प्रयास किया है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल प्रयासों के बाद, टीवी को फ़ैक्टरी डिफ़ॉल्ट पर रीसेट कर दिया जाएगा और सभी उपयोगकर्ता डेटा खो जाएगा."</string> - <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"आप गलत तरीके से फ़ोन को अनलॉक करने का प्रयास <xliff:g id="NUMBER_0">%1$d</xliff:g> बार कर चुके हैं. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल प्रयास के बाद, फ़ोन फ़ैक्टरी डिफ़ॉल्ट पर रीसेट हो जाएगा और सभी उपयोगकर्ता डेटा खो जाएगा."</string> - <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"आप टेबलेट को गलत तरीके से <xliff:g id="NUMBER">%d</xliff:g> बार अनलॉक करने का प्रयास कर चुके हैं. टेबलेट अब फ़ैक्टरी डिफ़ॉल्ट पर रीसेट हो जाएगा."</string> + <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"आप टैबलेट का लॉक खोलने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश कर चुके हैं. <xliff:g id="NUMBER_1">%2$d</xliff:g> बार और गलत कोशिश करने पर, टैबलेट फ़ैक्ट्री डिफ़ॉल्ट पर रीसेट हो जाएगा और सभी उपयोगकर्ता डेटा खो जाएगा."</string> + <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="950408382418270260">"आपने टीवी का लॉक खोलने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश की है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और बार गलत कोशिश करने पर, टीवी को फ़ैक्ट्री डिफ़ॉल्ट पर रीसेट कर दिया जाएगा और सभी उपयोगकर्ता डेटा खो जाएगा."</string> + <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"आप फ़ोन का लॉक खोलने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश कर चुके हैं. <xliff:g id="NUMBER_1">%2$d</xliff:g> बार और गलत कोशिश करने पर, फ़ोन फ़ैक्ट्री डिफ़ॉल्ट पर रीसेट हो जाएगा और सभी उपयोगकर्ता डेटा खो जाएगा."</string> + <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"आप टैबलेट को गलत तरीके से <xliff:g id="NUMBER">%d</xliff:g> बार अनलॉक करने का प्रयास कर चुके हैं. टैबलेट अब फ़ैक्टरी डिफ़ॉल्ट पर रीसेट हो जाएगा."</string> <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="3195755534096192191">"आपने टीवी को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से प्रयास किया है. अब टीवी को फ़ैक्टरी डिफ़ॉल्ट पर रीसेट कर दिया जाएगा."</string> <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"आप फ़ोन को गलत तरीके से <xliff:g id="NUMBER">%d</xliff:g> बार अनलॉक करने का प्रयास कर चुके हैं. फ़ोन अब फ़ैक्टरी डिफ़ॉल्ट पर रीसेट हो जाएगा."</string> <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"<xliff:g id="NUMBER">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string> @@ -756,8 +756,8 @@ <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"उपयोगकर्ता नाम (ईमेल)"</string> <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"पासवर्ड"</string> <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"प्रवेश करें"</string> - <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"अमान्य उपयोगकर्ता नाम या पासवर्ड."</string> - <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"अपना उपयोगकर्ता नाम या पासवर्ड भूल गए?\n"<b>"google.com/accounts/recovery"</b>" पर जाएं."</string> + <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"उपयोगकर्ता नाम या पासवर्ड गलत है."</string> + <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"अपना उपयोगकर्ता नाम या पासवर्ड भूल गए?\n "<b>"google.com/accounts/recovery"</b>" पर जाएं."</string> <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"जांच रहा है…"</string> <string name="lockscreen_unlock_label" msgid="737440483220667054">"अनलॉक करें"</string> <string name="lockscreen_sound_on_label" msgid="9068877576513425970">"ध्वनि चालू करें"</string> @@ -774,7 +774,7 @@ <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"अनलॉक क्षेत्र को विस्तृत कर दिया गया."</string> <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"अनलॉक क्षेत्र को संक्षिप्त कर दिया गया."</string> <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> विजेट."</string> - <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"उपयोगकर्ता चयनकर्ता"</string> + <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"उपयोगकर्ता चुनने वाला"</string> <string name="keyguard_accessibility_status" msgid="8008264603935930611">"स्थिति"</string> <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"कैमरा"</string> <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"मीडिया नियंत्रण"</string> @@ -797,7 +797,7 @@ <string name="granularity_label_link" msgid="5815508880782488267">"लिंक"</string> <string name="granularity_label_line" msgid="5764267235026120888">"पंक्ति"</string> <string name="factorytest_failed" msgid="5410270329114212041">"फ़ैक्ट्री परीक्षण विफल"</string> - <string name="factorytest_not_system" msgid="4435201656767276723">"FACTORY_TEST क्रिया केवल /system/app में इंस्टॉल किए गए पैकेज के लिए समर्थित है."</string> + <string name="factorytest_not_system" msgid="4435201656767276723">"FACTORY_TEST का काम केवल /system/app में इंस्टॉल किए गए पैकेज के लिए ही हो सकता है."</string> <string name="factorytest_no_action" msgid="872991874799998561">"ऐसा कोई पैकेज नहीं मिला था जो FACTORY_TEST कार्रवाई प्रदान करता हो."</string> <string name="factorytest_reboot" msgid="6320168203050791643">"रीबूट करें"</string> <string name="js_dialog_title" msgid="1987483977834603872">"\'<xliff:g id="TITLE">%s</xliff:g>\' पर यह पेज दर्शाता है:"</string> @@ -807,7 +807,7 @@ <string name="js_dialog_before_unload_negative_button" msgid="5614861293026099715">"इस पेज पर बने रहें"</string> <string name="js_dialog_before_unload" msgid="3468816357095378590">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nक्या आप वाकई इस पेज से दूर नेविगेट करना चाहते हैं?"</string> <string name="save_password_label" msgid="6860261758665825069">"दुबारा पूछें"</string> - <string name="double_tap_toast" msgid="4595046515400268881">"युक्ति: ज़ूम इन और आउट करने के लिए डबल-टैप करें."</string> + <string name="double_tap_toast" msgid="4595046515400268881">"सलाह: ज़ूम इन और आउट करने के लिए दो बार छूएं."</string> <string name="autofill_this_form" msgid="4616758841157816676">"स्वत: भरण"</string> <string name="setup_autofill" msgid="7103495070180590814">"स्वत: भरण सेट करें"</string> <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string> @@ -827,9 +827,9 @@ <string name="autofill_area" msgid="3547409050889952423">"क्षेत्र"</string> <string name="autofill_emirate" msgid="2893880978835698818">"अमीरात"</string> <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"अपने वेब बुकमार्क और इतिहास पढ़ें"</string> - <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"ऐप्स को ब्राउज़र द्वारा विज़िट किए गए सभी URL के इतिहास, और सभी ब्राउज़र बुकमार्क पढ़ने देता है. ध्यान दें: यह अनुमति तृतीय-पक्ष ब्राउज़र या वेब ब्राउज़िंग क्षमताओं वाले अन्य ऐप्स द्वारा लागू नहीं की जा सकती."</string> + <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"ऐप को ब्राउज़र के ज़रिये देखे गए सभी यूआरएल के इतिहास, और ब्राउज़र के सभी बुकमार्क पढ़ने देता है. ध्यान दें: हो सकता है कि यह अनुमति तीसरे-पक्ष के ब्राउज़र या वेब ब्राउज़िंग की सुविधा वाले अन्य ऐप के ज़रिये लागू न की जाए."</string> <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"वेब बुकमार्क और इतिहास लिखें"</string> - <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"ऐप्स को आपके टेबलेट में संग्रहित ब्राउज़र के इतिहास या बुकमार्क को संशोधित करने देता है. इससे ऐप्स ब्राउज़र डेटा को मिटा सकता है या संशोधित कर सकता है. ध्यान दें: यह अनुमति तृतीय-पक्ष ब्राउज़र या वेब ब्राउज़िंग क्षमताओं वाले अन्य ऐप्स द्वारा लागू नहीं की जा सकती."</string> + <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"ऐप्स को आपके टैबलेट में संग्रहित ब्राउज़र के इतिहास या बुकमार्क को संशोधित करने देता है. इससे ऐप्स ब्राउज़र डेटा को मिटा सकता है या संशोधित कर सकता है. ध्यान दें: यह अनुमति तृतीय-पक्ष ब्राउज़र या वेब ब्राउज़िंग क्षमताओं वाले अन्य ऐप्स द्वारा लागू नहीं की जा सकती."</string> <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"ऐप को आपके टीवी पर संग्रहित ब्राउज़र के इतिहास या बुकमार्क में बदलाव करने देती है. इससे ऐप को ब्राउज़र डेटा में बदलाव करने या उसे हटाने की अनुमति मिल सकती है. ध्यान दें: यह अनुमति वेब ब्राउज़िंग क्षमताओं वाले तृतीय-पक्ष ब्राउज़र या अन्य ऐप्लिकेशन द्वारा लागू नहीं की जा सकती है."</string> <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"ऐप्स को आपके फ़ोन में संग्रहित ब्राउज़र के इतिहास या बुकमार्क को संशोधित करने देता है. इससे ऐप्स ब्राउज़र डेटा को मिटा सकता है या संशोधित कर सकता है. ध्यान दें: यह अनुमति तृतीय-पक्ष ब्राउज़र या वेब ब्राउज़िंग क्षमताओं वाले अन्य ऐप्स द्वारा लागू नहीं की जा सकती."</string> <string name="permlab_setAlarm" msgid="1379294556362091814">"अलार्म सेट करें"</string> @@ -837,27 +837,27 @@ <string name="permlab_addVoicemail" msgid="5525660026090959044">"ध्वनिमेल जोड़ें"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"ऐप्स को आपके ध्वनिमेल इनबॉक्स में संदेश जोड़ने देता है."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ब्राउज़र भौगोलिक-स्थान अनुमतियों को बदलें"</string> - <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"ऐप्स को ब्राउज़र के भौगोलिक-स्थान की अनुमतियां संशोधित करने देता है. दुर्भावनापूर्ण ऐप्स इसका उपयोग एकपक्षीय वेबसाइट को स्थान जानकारी भेजने में कर सकते हैं."</string> + <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"ऐप को ब्राउज़र की जगह से जुड़ी अनुमतियों को बदलने देता है. धोखा देने वाले ऐप इसका इस्तेमाल गलत वेबसाइट को स्थान (लोकेशन) की जानकारी भेजने में कर सकते हैं."</string> <string name="save_password_message" msgid="767344687139195790">"क्या आप चाहते हैं कि ब्राउज़र पासवर्ड को याद रखे?"</string> - <string name="save_password_notnow" msgid="6389675316706699758">"अभी नहीं"</string> + <string name="save_password_notnow" msgid="6389675316706699758">"रद्द करें"</string> <string name="save_password_remember" msgid="6491879678996749466">"याद रखें"</string> <string name="save_password_never" msgid="8274330296785855105">"कभी नहीं"</string> <string name="open_permission_deny" msgid="7374036708316629800">"आपके पास इस पेज को खोलने की अनुमति नहीं है."</string> <string name="text_copied" msgid="4985729524670131385">"लेख को क्लिपबोर्ड पर कॉपी किया गया."</string> <string name="more_item_label" msgid="4650918923083320495">"अधिक"</string> - <string name="prepend_shortcut_label" msgid="2572214461676015642">"मेनू+"</string> + <string name="prepend_shortcut_label" msgid="2572214461676015642">"मेन्यू+"</string> <string name="menu_space_shortcut_label" msgid="2410328639272162537">"space"</string> <string name="menu_enter_shortcut_label" msgid="2743362785111309668">"enter"</string> <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"हटाएं"</string> - <string name="search_go" msgid="8298016669822141719">"खोजें"</string> - <string name="search_hint" msgid="1733947260773056054">"खोजें…"</string> - <string name="searchview_description_search" msgid="6749826639098512120">"खोजें"</string> - <string name="searchview_description_query" msgid="5911778593125355124">"खोज क्वेरी"</string> + <string name="search_go" msgid="8298016669822141719">"सर्च करें"</string> + <string name="search_hint" msgid="1733947260773056054">"सर्च करें…"</string> + <string name="searchview_description_search" msgid="6749826639098512120">"सर्च करें"</string> + <string name="searchview_description_query" msgid="5911778593125355124">"सर्च क्वेरी"</string> <string name="searchview_description_clear" msgid="1330281990951833033">"क्वेरी साफ़ करें"</string> <string name="searchview_description_submit" msgid="2688450133297983542">"क्वेरी सबमिट करें"</string> - <string name="searchview_description_voice" msgid="2453203695674994440">"बोलकर खोजें"</string> + <string name="searchview_description_voice" msgid="2453203695674994440">"बोलकर सर्च करें"</string> <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"स्पर्श के द्वारा अन्वेषण करें सक्षम करें?"</string> - <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> स्पर्श के द्वारा अन्वेषण करें सक्षम करना चाहती है. स्पर्श के द्वारा अन्वेष करें चालू होने पर, आप अपनी अंगुली के नीचे क्या है उसका विवरण सुन सकते हैं या देख सकते हैं या टेबलेट से डॉयलॉग करने के लिए जेस्चर निष्पादित कर सकते हैं."</string> + <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> स्पर्श के द्वारा अन्वेषण करें सक्षम करना चाहती है. स्पर्श के द्वारा अन्वेष करें चालू होने पर, आप अपनी अंगुली के नीचे क्या है उसका विवरण सुन सकते हैं या देख सकते हैं या टैबलेट से डॉयलॉग करने के लिए जेस्चर निष्पादित कर सकते हैं."</string> <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> स्पर्श के द्वारा अन्वेषण करें सक्षम करना चाहती है. स्पर्श के द्वारा अन्वेष करें चालू होने पर, आप अपनी अंगुली के नीचे क्या है उसका विवरण सुन सकते हैं या देख सकते हैं या फ़ोन से डॉयलॉग करने के लिए जेस्चर निष्पादित कर सकते हैं."</string> <string name="oneMonthDurationPast" msgid="7396384508953779925">"1 माह पहले"</string> <string name="beforeOneMonthDurationPast" msgid="909134546836499826">"1 माह से पहले"</string> @@ -966,7 +966,7 @@ <string name="paste_as_plain_text" msgid="5427792741908010675">"सादे पाठ के रूप में चिपकाएं"</string> <string name="replace" msgid="5781686059063148930">"बदलें•"</string> <string name="delete" msgid="6098684844021697789">"हटाएं"</string> - <string name="copyUrl" msgid="2538211579596067402">"URL को कॉपी करें"</string> + <string name="copyUrl" msgid="2538211579596067402">"यूआरएल को कॉपी करें"</string> <string name="selectTextMode" msgid="1018691815143165326">"लेख को चुनें"</string> <string name="undo" msgid="7905788502491742328">"वापस लाएं"</string> <string name="redo" msgid="7759464876566803888">"फिर से करें"</string> @@ -982,18 +982,18 @@ <string name="browse" msgid="6993590095938149861">"ब्राउज़र"</string> <string name="low_internal_storage_view_title" msgid="5576272496365684834">"मेमोरी स्थान समाप्त हो रहा है"</string> <string name="low_internal_storage_view_text" msgid="6640505817617414371">"हो सकता है कुछ सिस्टम फ़ंक्शन कार्य न करें"</string> - <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"सिस्टम के लिए पर्याप्त मेमोरी नहीं है. सुनिश्चित करें कि आपके पास 250MB का खाली स्थान है और फिर से प्रारंभ करें."</string> + <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"सिस्टम के लिए ज़रूरी मेमोरी नहीं है. पक्का करें कि आपके पास 250एमबी की खाली जगह है और फिर से शुरू करें."</string> <string name="app_running_notification_title" msgid="8718335121060787914">"<xliff:g id="APP_NAME">%1$s</xliff:g> चल रहा है"</string> - <string name="app_running_notification_text" msgid="1197581823314971177">"अधिक जानकारी के लिए या ऐप्लिकेशन रोकने के लिए टैप करें."</string> + <string name="app_running_notification_text" msgid="1197581823314971177">"अधिक जानकारी के लिए या ऐप्लिकेशन को रोकने के लिए छूएं."</string> <string name="ok" msgid="5970060430562524910">"ठीक है"</string> - <string name="cancel" msgid="6442560571259935130">"अभी नहीं"</string> + <string name="cancel" msgid="6442560571259935130">"रद्द करें"</string> <string name="yes" msgid="5362982303337969312">"ठीक है"</string> - <string name="no" msgid="5141531044935541497">"अभी नहीं"</string> + <string name="no" msgid="5141531044935541497">"रद्द करें"</string> <string name="dialog_alert_title" msgid="2049658708609043103">"ध्यान दें"</string> <string name="loading" msgid="7933681260296021180">"लोड हो रहे हैं..."</string> <string name="capital_on" msgid="1544682755514494298">"ऑन"</string> <string name="capital_off" msgid="6815870386972805832">"बंद"</string> - <string name="whichApplication" msgid="4533185947064773386">"इसका उपयोग करके क्रिया पूर्ण करें"</string> + <string name="whichApplication" msgid="4533185947064773386">"इसका इस्तेमाल करके कार्रवाई को पूरा करें"</string> <string name="whichApplicationNamed" msgid="8260158865936942783">"%1$s का उपयोग करके कार्रवाई पूर्ण करें"</string> <string name="whichApplicationLabel" msgid="7425855495383818784">"कार्रवाई पूर्ण करें"</string> <string name="whichViewApplication" msgid="3272778576700572102">"इसमें खोलें"</string> @@ -1014,10 +1014,10 @@ <string name="whichImageCaptureApplication" msgid="3680261417470652882">"चित्र को इसके साथ कैप्चर करें"</string> <string name="whichImageCaptureApplicationNamed" msgid="8619384150737825003">"%1$s के साथ चित्र कैप्चर करें"</string> <string name="whichImageCaptureApplicationLabel" msgid="6390303445371527066">"चित्र कैप्चर करें"</string> - <string name="alwaysUse" msgid="4583018368000610438">"इस क्रिया के लिए डिफ़ॉल्ट रूप से उपयोग करें."</string> + <string name="alwaysUse" msgid="4583018368000610438">"इस कार्रवाई के लिए डिफ़ॉल्ट के तौर पर इस्तेमाल करें"</string> <string name="use_a_different_app" msgid="8134926230585710243">"किसी भिन्न ऐप्स का उपयोग करें"</string> <string name="clearDefaultHintMsg" msgid="3252584689512077257">"सिस्टम सेटिंग > Apps > डाउनलोड किए गए में डिफ़ॉल्ट साफ करें."</string> - <string name="chooseActivity" msgid="7486876147751803333">"कोई क्रिया चुनें"</string> + <string name="chooseActivity" msgid="7486876147751803333">"कोई कार्रवाई चुनें"</string> <string name="chooseUsbActivity" msgid="6894748416073583509">"USB डिवाइस के लिए कोई ऐप्स चुनें"</string> <string name="noApplications" msgid="2991814273936504689">"कोई भी ऐप्स यह कार्यवाही नहीं कर सकता."</string> <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> रुक गया है"</string> @@ -1039,7 +1039,7 @@ <string name="report" msgid="4060218260984795706">"रिपोर्ट करें"</string> <string name="wait" msgid="7147118217226317732">"प्रतीक्षा करें"</string> <string name="webpage_unresponsive" msgid="3272758351138122503">"पेज प्रतिसाद नहीं दे रहा है.\n\nक्या आप इसे बंद करना चाहते हैं?"</string> - <string name="launch_warning_title" msgid="1547997780506713581">"एप्लि. रीडायरेक्ट किया गया"</string> + <string name="launch_warning_title" msgid="1547997780506713581">"ऐप को दूसरे वेबलिंक पर लॉन्च किया गया"</string> <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> अभी चल रहा है."</string> <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> को वास्तविक रूप से लॉन्च किया गया था."</string> <string name="screen_compat_mode_scale" msgid="3202955667675944499">"स्केल"</string> @@ -1053,7 +1053,7 @@ <string name="android_start_title" msgid="8418054686415318207">"Android प्रारंभ हो रहा है…"</string> <string name="android_upgrading_fstrim" msgid="8036718871534640010">"मेमोरी ऑप्टिमाइज़ हो रही है."</string> <string name="android_upgrading_notification_title" msgid="8428357096969413169">"Android अपडेट समाप्त हो रहा है…"</string> - <string name="android_upgrading_notification_body" msgid="5761201379457064286">"जब तक अपग्रेड पूरा नहीं हो जाता, तब तक संभव है कि कुछ ऐप्लिकेशन ठीक से कार्य ना करें"</string> + <string name="android_upgrading_notification_body" msgid="5761201379457064286">"जब तक अपग्रेड पूरा नहीं हो जाता, हो सकता है कि तब तक कुछ ऐप्लिकेशन ठीक से काम ना करें"</string> <string name="app_upgrading_toast" msgid="3008139776215597053">"<xliff:g id="APPLICATION">%1$s</xliff:g> अपग्रेड हो रहा है…"</string> <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> में से <xliff:g id="NUMBER_0">%1$d</xliff:g> ऐप्स अनुकूलित हो रहा है."</string> <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> तैयार हो रहा है."</string> @@ -1065,13 +1065,13 @@ <string name="heavy_weight_switcher_text" msgid="7022631924534406403">"दूसरा ऐप्स पहले से चल रहा है जिसे किसी नए ऐप्स को प्रारंभ करने के पहले बंद किया जाना आवश्यक है."</string> <string name="old_app_action" msgid="493129172238566282">"<xliff:g id="OLD_APP">%1$s</xliff:g> पर वापस लौटें"</string> <string name="old_app_description" msgid="2082094275580358049">"नया ऐप्स प्रारंभ न करें."</string> - <string name="new_app_action" msgid="5472756926945440706">"<xliff:g id="OLD_APP">%1$s</xliff:g> प्रारंभ करें"</string> + <string name="new_app_action" msgid="5472756926945440706">"<xliff:g id="OLD_APP">%1$s</xliff:g> शुरू करें"</string> <string name="new_app_description" msgid="1932143598371537340">"पुराने ऐप्स को बिना सहेजे बंद करें."</string> <string name="dump_heap_notification" msgid="2618183274836056542">"<xliff:g id="PROC">%1$s</xliff:g> मेमोरी सीमा को पार कर गई है"</string> <string name="dump_heap_notification_detail" msgid="6901391084243999274">"हीप डंप का संग्रह कर लिया गया है; शेयर करने के लिए टैप करें"</string> <string name="dump_heap_title" msgid="5864292264307651673">"हीप डंप साझा करें?"</string> - <string name="dump_heap_text" msgid="4809417337240334941">"प्रक्रिया <xliff:g id="PROC">%1$s</xliff:g> इसकी <xliff:g id="SIZE">%2$s</xliff:g> की मेमोरी की सीमा को पार कर गई है. इसके डेवलपर से साझा करने के लिए एक हीप डंप आपके लिए उपलब्ध है. सावधान रहें: इस हीप डंप में आपकी ऐसी कोई भी व्यक्तिगत जानकारी हो सकती है जिस पर ऐप्लिकेशन की ऐक्सेस हो."</string> - <string name="sendText" msgid="5209874571959469142">"लेख के लिए किसी क्रिया को चुनें"</string> + <string name="dump_heap_text" msgid="4809417337240334941">"यह प्रक्रिया <xliff:g id="PROC">%1$s</xliff:g> इसकी <xliff:g id="SIZE">%2$s</xliff:g> की मेमोरी की सीमा को पार कर गई है. एक हीप डंप मौजूद है जिसे आप इसके डेवलपर से शेयर कर सकते हैं. सावधान रहें: इस हीप डंप में आपकी ऐसी कोई भी निजी जानकारी हो सकती है जिस पर ऐप्लिकेशन की पहुंच हो."</string> + <string name="sendText" msgid="5209874571959469142">"मैसेज करने के लिए कोई कार्रवाई चुनें"</string> <string name="volume_ringtone" msgid="6885421406845734650">"रिंगर वॉल्यूम"</string> <string name="volume_music" msgid="5421651157138628171">"मीडिया वॉल्यूम"</string> <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"ब्लूटूथ द्वारा चलाया जा रहा है"</string> @@ -1079,19 +1079,19 @@ <string name="volume_call" msgid="3941680041282788711">"कॉल के दौरान वॉल्यूम"</string> <string name="volume_bluetooth_call" msgid="2002891926351151534">"ब्लूटूथ कॉल के दौरान वॉल्यूम"</string> <string name="volume_alarm" msgid="1985191616042689100">"अलार्म वॉल्यूम"</string> - <string name="volume_notification" msgid="2422265656744276715">"नोटिफ़िकेशन वॉल्यूम"</string> + <string name="volume_notification" msgid="2422265656744276715">"सूचना की आवाज़"</string> <string name="volume_unknown" msgid="1400219669770445902">"आवाज़"</string> <string name="volume_icon_description_bluetooth" msgid="6538894177255964340">"ब्लूटूथ वॉल्यूम"</string> <string name="volume_icon_description_ringer" msgid="3326003847006162496">"रिंगटोन वॉल्यूम"</string> <string name="volume_icon_description_incall" msgid="8890073218154543397">"कॉल वॉल्यूम"</string> <string name="volume_icon_description_media" msgid="4217311719665194215">"मीडिया वॉल्यूम"</string> - <string name="volume_icon_description_notification" msgid="7044986546477282274">"नोटिफ़िकेशन वॉल्यूम"</string> + <string name="volume_icon_description_notification" msgid="7044986546477282274">"सूचना की आवाज़"</string> <string name="ringtone_default" msgid="3789758980357696936">"डिफ़ॉल्ट रिंगटोन"</string> <string name="ringtone_default_with_actual" msgid="1767304850491060581">"डिफ़ॉल्ट (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string> <string name="ringtone_silent" msgid="7937634392408977062">"कोई नहीं"</string> <string name="ringtone_picker_title" msgid="3515143939175119094">"रिंगटोन"</string> <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"अलार्म ध्वनियां"</string> - <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"नोटिफ़िकेशन ध्वनि"</string> + <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"सूचना की आवाज़"</string> <string name="ringtone_unknown" msgid="3914515995813061520">"अज्ञात"</string> <plurals name="wifi_available" formatted="false" msgid="7900333017752027322"> <item quantity="one">वाई-फ़ाई नेटवर्क उपलब्ध</item> @@ -1131,7 +1131,7 @@ <string name="wifi_connect_alert_message" msgid="6451273376815958922">"%1$s ऐप्लिकेशन %2$s वाई-फ़ाई नेटवर्क से कनेक्ट करना चाहता है"</string> <string name="wifi_connect_default_application" msgid="7143109390475484319">"ऐप्लिकेशन"</string> <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"वाई-फ़ाई डायरेक्ट"</string> - <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"वाई-फ़ाई डायरेक्ट प्रारंभ करें. इससे वाई-फ़ाई क्लाइंट/हॉटस्पॉट कार्यवाही बंद हो जाएगी."</string> + <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"वाई-फ़ाई डायरेक्ट चालू करें. इससे वाई-फ़ाई क्लाइंट/हॉटस्पॉट कार्यवाही बंद हो जाएगी."</string> <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"वाई-फ़ाई डायरेक्ट प्रारंभ नहीं किया जा सका."</string> <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"वाई-फ़ाई डायरेक्ट चालू है"</string> <string name="wifi_p2p_enabled_notification_message" msgid="8064677407830620023">"सेटिंग के लिए टैप करें"</string> @@ -1143,19 +1143,19 @@ <string name="wifi_p2p_to_message" msgid="248968974522044099">"प्रति:"</string> <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"आवश्यक पिन लिखें:"</string> <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"पिन:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> से कनेक्ट रहने पर टेबलेट वाई-फ़ाई से अस्थायी रूप से डिसकनेक्ट हो जाएगा"</string> + <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> से कनेक्ट रहने पर टैबलेट वाई-फ़ाई से अस्थायी रूप से डिसकनेक्ट हो जाएगा"</string> <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="3087858235069421128">"जब टीवी <xliff:g id="DEVICE_NAME">%1$s</xliff:g> से कनेक्ट होगा तब वह वाई-फ़ाई से अस्थायी रूप से डिस्कनेक्ट हो जाएगा"</string> <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"फ़ोन <xliff:g id="DEVICE_NAME">%1$s</xliff:g> से कनेक्ट रहते समय वाई-फ़ाई से अस्थायी रूप से डिसकनेक्ट हो जाएगा"</string> <string name="select_character" msgid="3365550120617701745">"वर्ण सम्मिलित करें"</string> - <string name="sms_control_title" msgid="7296612781128917719">"SMS संदेश भेज रहा है"</string> - <string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> बड़ी संख्या में SMS संदेश भेज रहा है. क्या आप इस ऐप्स को संदेश भेजना जारी रखने देना चाहते हैं?"</string> + <string name="sms_control_title" msgid="7296612781128917719">"मैसेज (एसएमएस) भेज रहा है"</string> + <string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> बड़ी संख्या में मैसेज (एसएमएस) भेज रहा है. क्या आप इस ऐप को मैसेज भेजना जारी रखने देना चाहते हैं?"</string> <string name="sms_control_yes" msgid="3663725993855816807">"अनुमति दें"</string> <string name="sms_control_no" msgid="625438561395534982">"अस्वीकार करें"</string> <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>, <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b> पर संदेश भेजना चाहता है."</string> <string name="sms_short_code_details" msgid="5873295990846059400">"इससे आपके मोबाइल खाते पर "<b>"शुल्क लग सकता है"</b>"."</string> <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"इससे आपके मोबाइल खाते पर शुल्क लगेगा."</b></string> <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"भेजें"</string> - <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"अभी नहीं"</string> + <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"रद्द करें"</string> <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"मेरी पसंद को याद रखें"</string> <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"आप इसे बाद में सेटिंग > ऐप्स में बदल सकते हैं"</string> <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"हमेशा अनुमति दें"</string> @@ -1164,15 +1164,15 @@ <string name="sim_removed_message" msgid="2333164559970958645">"मान्य सिम कार्ड डालकर पुन: प्रारंभ करने तक मोबाइल नेटवर्क अनुपलब्ध रहेगा."</string> <string name="sim_done_button" msgid="827949989369963775">"पूर्ण"</string> <string name="sim_added_title" msgid="3719670512889674693">"सिम कार्ड जोड़ा गया"</string> - <string name="sim_added_message" msgid="6599945301141050216">"मोबाइल नेटवर्क पर पहुंचने के लिए अपना डिवाइस पुन: प्रारंभ करें."</string> - <string name="sim_restart_button" msgid="4722407842815232347">"पुन: प्रारंभ करें"</string> + <string name="sim_added_message" msgid="6599945301141050216">"मोबाइल नेटवर्क की पहुंच पाने लिए अपना डिवाइस फिर से चालू करें."</string> + <string name="sim_restart_button" msgid="4722407842815232347">"फिर से शुरू करें"</string> <string name="carrier_app_dialog_message" msgid="7066156088266319533">"आपका नया SIM ठीक से काम करे, इसके लिए आपको अपनी मोबाइल और इंटरनेट सेवा देने वाली कंपनी से कोई ऐप इंस्टॉल करना होगा और उसे खोलना होगा."</string> <string name="carrier_app_dialog_button" msgid="7900235513678617329">"ऐप प्राप्त करें"</string> - <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"अभी नहीं"</string> + <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"रद्द करें"</string> <string name="carrier_app_notification_title" msgid="8921767385872554621">"नई SIM डाली गई"</string> <string name="carrier_app_notification_text" msgid="1132487343346050225">"इसे सेट करने के लिए टैप करें"</string> <string name="time_picker_dialog_title" msgid="8349362623068819295">"समय सेट करें"</string> - <string name="date_picker_dialog_title" msgid="5879450659453782278">"दिनांक सेट करें"</string> + <string name="date_picker_dialog_title" msgid="5879450659453782278">"तारीख सेट करें"</string> <string name="date_time_set" msgid="5777075614321087758">"सेट करें"</string> <string name="date_time_done" msgid="2507683751759308828">"पूर्ण"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"नया: "</font></string> @@ -1192,10 +1192,10 @@ <string name="adb_active_notification_title" msgid="6729044778949189918">"USB डीबग कनेक्ट किया गया"</string> <string name="adb_active_notification_message" msgid="4948470599328424059">"USB डीबग करना अक्षम करने के लिए टैप करें."</string> <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB डीबग करना अक्षम करने के लिए चुनें."</string> - <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"बग रिपोर्ट प्राप्त की जा रही है…"</string> - <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"बग रिपोर्ट साझा करें?"</string> - <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"बग रिपोर्ट साझा की जा रही है…"</string> - <string name="share_remote_bugreport_notification_message_finished" msgid="6029609949340992866">"आपके व्यवस्थापक ने इस डिवाइस के समस्या निवारण में सहायता के लिए एक बग रिपोर्ट का अनुरोध किया है. ऐप्लिकेशन और डेटा साझा किए जा सकते हैं."</string> + <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"गड़बड़ी की रिपोर्ट ली जा रही है…"</string> + <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"गड़बड़ी की रिपोर्ट शेयर करें?"</string> + <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"गड़बड़ी की रिपोर्ट शेयर की जा रही है…"</string> + <string name="share_remote_bugreport_notification_message_finished" msgid="6029609949340992866">"आपके एडमिन ने इस डिवाइस की समस्या को हल करने में सहायता के लिए एक गड़बड़ी की रिपोर्ट का अनुरोध किया है. ऐप्लिकेशन और डेटा शेयर किए जा सकते हैं."</string> <string name="share_remote_bugreport_action" msgid="6249476773913384948">"साझा करें"</string> <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"अस्वीकार करें"</string> <string name="select_input_method" msgid="8547250819326693584">"कीबोर्ड बदलें"</string> @@ -1262,7 +1262,7 @@ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ज़ूम नियंत्रण के लिए दो बार टैप करें"</string> <string name="gadget_host_error_inflating" msgid="4882004314906466162">"विजेट नहीं जोड़ा जा सका."</string> <string name="ime_action_go" msgid="8320845651737369027">"जाएं"</string> - <string name="ime_action_search" msgid="658110271822807811">"खोजें"</string> + <string name="ime_action_search" msgid="658110271822807811">"सर्च करें"</string> <string name="ime_action_send" msgid="2316166556349314424">"भेजें"</string> <string name="ime_action_next" msgid="3138843904009813834">"आगे"</string> <string name="ime_action_done" msgid="8971516117910934605">"पूर्ण"</string> @@ -1270,9 +1270,9 @@ <string name="ime_action_default" msgid="2840921885558045721">"निष्पादित करें"</string> <string name="dial_number_using" msgid="5789176425167573586">"<xliff:g id="NUMBER">%s</xliff:g> के उपयोग द्वारा \n नंबर डायल करें"</string> <string name="create_contact_using" msgid="4947405226788104538">"<xliff:g id="NUMBER">%s</xliff:g> का उपयोग करके\n संपर्क बनाएं"</string> - <string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"निम्न एक या अधिक ऐप्स अभी और भविष्य में आपके खाते में पहुंच की अनुमति का अनुरोध करते हैं."</string> - <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"क्या आप इस अनुरोध को अनुमति देना चाहते हैं?"</string> - <string name="grant_permissions_header_text" msgid="6874497408201826708">"पहुंच अनुरोध"</string> + <string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"इनमें से एक या अधिक ऐप, अभी और आने वाले समय में आपके खाते को एक्सेस करने की अनुमति चाहते हैं."</string> + <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"क्या आप इस अनुरोध की अनुमति देना चाहते हैं?"</string> + <string name="grant_permissions_header_text" msgid="6874497408201826708">"पहुंच पाने का अनुरोध"</string> <string name="allow" msgid="7225948811296386551">"अनुमति दें"</string> <string name="deny" msgid="2081879885755434506">"अस्वीकारें"</string> <string name="permission_request_notification_title" msgid="6486759795926237907">"अनुमति अनुरोधित"</string> @@ -1284,19 +1284,19 @@ <string name="accessibility_binding_label" msgid="4148120742096474641">"सरल उपयोग"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"वॉलपेपर"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"वॉलपेपर बदलें"</string> - <string name="notification_listener_binding_label" msgid="2014162835481906429">"नोटिफ़िकेशन श्रवणकर्ता"</string> + <string name="notification_listener_binding_label" msgid="2014162835481906429">"सूचना को सुनने की सुविधा"</string> <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR श्रोता"</string> <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"स्थिति प्रदाता"</string> - <string name="notification_ranker_binding_label" msgid="774540592299064747">"नोटिफ़िकेशन रैंकर सेवा"</string> + <string name="notification_ranker_binding_label" msgid="774540592299064747">"सूचना रैंकर सेवा"</string> <string name="vpn_title" msgid="19615213552042827">"VPN सक्रिय"</string> <string name="vpn_title_long" msgid="6400714798049252294">"VPN को <xliff:g id="APP">%s</xliff:g> द्वारा सक्रिय किया गया है"</string> <string name="vpn_text" msgid="1610714069627824309">"नेटवर्क प्रबंधित करने के लिए टैप करें."</string> <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> से कनेक्ट किया गया. नेटवर्क प्रबंधित करने के लिए टैप करें."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"हमेशा-चालू VPN कनेक्ट हो रहा है…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"हमेशा-चालू VPN कनेक्ट है"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"हमेशा-चालू VPN डिस्कनेक्ट है"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"हमेशा चालू रहने वाले VPN से डिसकनेक्ट किया गया"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"हमेशा-चालू VPN गड़बड़ी"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"सेट करने के लिए टैप करें"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"नेटवर्क या VPN सेटिंग बदलें"</string> <string name="upload_file" msgid="2897957172366730416">"फ़ाइल चुनें"</string> <string name="no_file_chosen" msgid="6363648562170759465">"कोई फ़ाइल चुनी नहीं गई"</string> <string name="reset" msgid="2448168080964209908">"रीसेट करें"</string> @@ -1306,10 +1306,10 @@ <string name="tethered_notification_title" msgid="3146694234398202601">"टेदरिंग या हॉटस्पॉट सक्रिय"</string> <string name="tethered_notification_message" msgid="2113628520792055377">"सेट करने के लिए टैप करें."</string> <string name="disable_tether_notification_title" msgid="7526977944111313195">"टेदरिंग अक्षम है"</string> - <string name="disable_tether_notification_message" msgid="2913366428516852495">"जानकारी के लिए अपने व्यवस्थापक से संपर्क करें"</string> + <string name="disable_tether_notification_message" msgid="2913366428516852495">"जानकारी के लिए अपने एडमिन से संपर्क करें"</string> <string name="back_button_label" msgid="2300470004503343439">"वापस जाएं"</string> <string name="next_button_label" msgid="1080555104677992408">"आगे"</string> - <string name="skip_button_label" msgid="1275362299471631819">"अभी नहीं"</string> + <string name="skip_button_label" msgid="1275362299471631819">"रद्द करें"</string> <string name="no_matches" msgid="8129421908915840737">"कोई मिलान नहीं"</string> <string name="find_on_page" msgid="1946799233822820384">"पेज पर ढूंढें"</string> <plurals name="matches_found" formatted="false" msgid="1210884353962081884"> @@ -1321,11 +1321,11 @@ <string name="progress_erasing" product="default" msgid="6596988875507043042">"SD कार्ड मिटाया जा रहा है…"</string> <string name="share" msgid="1778686618230011964">"साझा करें"</string> <string name="find" msgid="4808270900322985960">"ढूंढें"</string> - <string name="websearch" msgid="4337157977400211589">"वेब खोज"</string> + <string name="websearch" msgid="4337157977400211589">"वेब सर्च"</string> <string name="find_next" msgid="5742124618942193978">"आगे ढूंढें"</string> <string name="find_previous" msgid="2196723669388360506">"पिछला ढूंढें"</string> - <string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g> की ओर से स्थान अनुरोध"</string> - <string name="gpsNotifTitle" msgid="5446858717157416839">"स्थान अनुरोध"</string> + <string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g> ने स्थान (लोकेशन) का अनुरोध किया गया है"</string> + <string name="gpsNotifTitle" msgid="5446858717157416839">"स्थान (लोकेशन) का अनुरोध किया जा रहा है"</string> <string name="gpsNotifMessage" msgid="1374718023224000702">"<xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>) द्वारा अनुरोधित"</string> <string name="gpsVerifYes" msgid="2346566072867213563">"हां"</string> <string name="gpsVerifNo" msgid="1146564937346454865">"नहीं"</string> @@ -1356,7 +1356,7 @@ <string name="date_picker_prev_month_button" msgid="2858244643992056505">"पिछला महीना"</string> <string name="date_picker_next_month_button" msgid="5559507736887605055">"अगला महीना"</string> <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string> - <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"अभी नहीं"</string> + <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"रद्द करें"</string> <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"हटाएं"</string> <string name="keyboardview_keycode_done" msgid="1992571118466679775">"पूर्ण"</string> <string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"Mode change"</string> @@ -1368,9 +1368,9 @@ <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> के साथ साझा करें"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"स्लाइडिंग हैंडल. दबाकर रखें."</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"अनलॉक करने के लिए स्वाइप करें."</string> - <string name="action_bar_home_description" msgid="5293600496601490216">"होम पर नेविगेट करें"</string> - <string name="action_bar_up_description" msgid="2237496562952152589">"ऊपर नेविगेट करें"</string> - <string name="action_menu_overflow_description" msgid="2295659037509008453">"अधिक विकल्प"</string> + <string name="action_bar_home_description" msgid="5293600496601490216">"होम पेज पर जाएं"</string> + <string name="action_bar_up_description" msgid="2237496562952152589">"ऊपर जाएं"</string> + <string name="action_menu_overflow_description" msgid="2295659037509008453">"ज़्यादा विकल्प"</string> <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string> <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string> <string name="storage_internal" msgid="3570990907910199483">"आंतरिक साझा मेमोरी"</string> @@ -1417,7 +1417,7 @@ <string name="activity_resolver_use_always" msgid="8017770747801494933">"हमेशा"</string> <string name="activity_resolver_use_once" msgid="2404644797149173758">"केवल एक बार"</string> <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s कार्य प्रोफ़ाइल का समर्थन नहीं करता"</string> - <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"टेबलेट"</string> + <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"टैबलेट"</string> <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"टीवी"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"फ़ोन"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"हेडफ़ोन"</string> @@ -1425,7 +1425,7 @@ <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"सिस्टम"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"ब्लूटूथ ऑडियो"</string> - <string name="wireless_display_route_description" msgid="9070346425023979651">"वायरलेस प्रदर्शन"</string> + <string name="wireless_display_route_description" msgid="9070346425023979651">"वायरलेस डिसप्ले"</string> <string name="media_route_button_content_description" msgid="591703006349356016">"कास्ट करें"</string> <string name="media_route_chooser_title" msgid="1751618554539087622">"डिवाइस से कनेक्ट करें"</string> <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"स्क्रीन को डिवाइस में कास्ट करें"</string> @@ -1465,19 +1465,19 @@ <string name="kg_login_username_hint" msgid="5718534272070920364">"उपयोगकर्ता नाम (ईमेल)"</string> <string name="kg_login_password_hint" msgid="9057289103827298549">"पासवर्ड"</string> <string name="kg_login_submit_button" msgid="5355904582674054702">"प्रवेश करें"</string> - <string name="kg_login_invalid_input" msgid="5754664119319872197">"अमान्य उपयोगकर्ता नाम या पासवर्ड."</string> + <string name="kg_login_invalid_input" msgid="5754664119319872197">"उपयोगकर्ता नाम या पासवर्ड गलत है"</string> <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"अपना उपयोगकर्ता नाम या पासवर्ड भूल गए?\n "<b>"google.com/accounts/recovery"</b>" पर जाएं."</string> <string name="kg_login_checking_password" msgid="1052685197710252395">"खाते की जांच की जा रही है…"</string> <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"आप अपना PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से लिख चुके हैं. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंड में पुन: प्रयास करें."</string> <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"आप अपना पासवर्ड <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से लिख चुके हैं. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंड में पुन: प्रयास करें."</string> <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"आपने अपना अनलॉक आकार <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से आरेखित किया है. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंड में पुन: प्रयास करें."</string> - <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"आप टेबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से प्रयास कर चुके हैं. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल प्रयासों के बाद, टेबलेट फ़ैक्टरी डिफ़ॉल्ट पर रीसेट हो जाएगा और सभी उपयोगकर्ता डेटा खो जाएगा."</string> - <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="5621231220154419413">"आपने टीवी को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से प्रयास किया है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल प्रयासों के बाद, टीवी को फ़ैक्टरी डिफ़ॉल्ट पर रीसेट कर दिया जाएगा और सभी उपयोगकर्ता डेटा खो जाएगा."</string> - <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"आप फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से प्रयास कर चुके हैं. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल प्रयासों के बाद, फ़ोन फ़ैक्टरी डिफ़ॉल्ट पर रीसेट हो जाएगा और सभी उपयोगकर्ता डेटा खो जाएगा."</string> - <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"आप टेबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से प्रयास कर चुके हैं. टेबलेट अब फ़ैक्टरी डिफ़ॉल्ट पर रीसेट हो जाएगा."</string> + <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"आप टैबलेट का लॉक खोलने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश कर चुके हैं. <xliff:g id="NUMBER_1">%2$d</xliff:g> बार और गलत कोशिश करने पर, टैबलेट फ़ैक्ट्री डिफ़ॉल्ट पर रीसेट हो जाएगा और सभी उपयोगकर्ता डेटा खो जाएगा."</string> + <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="5621231220154419413">"आप टीवी का लॉक खोलने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश कर चुके हैं. <xliff:g id="NUMBER_1">%2$d</xliff:g> बार और गलत कोशिश करने पर टीवी को फ़ैक्ट्री डिफ़ॉल्ट पर रीसेट कर दिया जाएगा और सभी उपयोगकर्ता डेटा खो जाएगा."</string> + <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"आप फ़ोन का लॉक खोलने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश कर चुके हैं. <xliff:g id="NUMBER_1">%2$d</xliff:g> बार और गलत कोशिश करने पर फ़ोन फ़ैक्ट्री डिफ़ॉल्ट पर रीसेट हो जाएगा और सभी उपयोगकर्ता डेटा खो जाएगा."</string> + <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"आप टैबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से प्रयास कर चुके हैं. टैबलेट अब फ़ैक्टरी डिफ़ॉल्ट पर रीसेट हो जाएगा."</string> <string name="kg_failed_attempts_now_wiping" product="tv" msgid="4987878286750741463">"आपने टीवी को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से प्रयास किया है. अब टीवी को फ़ैक्टरी डिफ़ॉल्ट पर रीसेट कर दिया जाएगा."</string> <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"आप फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से प्रयास कर चुके हैं. फ़ोन अब फ़ैक्टरी डिफ़ॉल्ट पर रीसेट हो जाएगा."</string> - <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"आपने अपने अनलॉक आकार को <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से आरेखित किया है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने टेबलेट को किसी ईमेल खाते के उपयोग से अनलॉक करने के लिए कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड में पुन: प्रयास करें."</string> + <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"आपने अपने अनलॉक आकार को <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से आरेखित किया है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने टैबलेट को किसी ईमेल खाते के उपयोग से अनलॉक करने के लिए कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड में पुन: प्रयास करें."</string> <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"आपने अपने लॉक खोलने के पैटर्न को <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से ड्रॉ किया है. अगर आपने <xliff:g id="NUMBER_1">%2$d</xliff:g> बार और गलत ड्रॉ किया, तो आपको किसी ईमेल खाते के ज़रिये अपने टीवी को अनलॉक करने को कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड में फिर से कोशिश करें."</string> <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"आपने अपने अनलॉक आकार को <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से आरेखित किया है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने फ़ोन को किसी ईमेल खाते का उपयोग करके अनलॉक करने के लिए कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड में पुन: प्रयास करें."</string> <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string> @@ -1492,14 +1492,14 @@ <string name="accessibility_button_prompt_text" msgid="4234556536456854251">"एक्सेस-योग्यता बटन पर टैप करते समय उपयोग की जाने वाली सुविधा चुनें:"</string> <string name="accessibility_button_instructional_text" msgid="6942300463612999993">"सुविधाओं में बदलाव करने के लिए, सुलभता बटन को दबाकर रखें."</string> <string name="accessibility_magnification_chooser_text" msgid="1227146738764986237">"आवर्धन"</string> - <string name="user_switched" msgid="3768006783166984410">"वर्तमान उपयोगकर्ता <xliff:g id="NAME">%1$s</xliff:g>."</string> + <string name="user_switched" msgid="3768006783166984410">"मौजूदा उपयोगकर्ता <xliff:g id="NAME">%1$s</xliff:g>."</string> <string name="user_switching_message" msgid="2871009331809089783">"<xliff:g id="NAME">%1$s</xliff:g> पर स्विच किया जा रहा है…"</string> <string name="user_logging_out_message" msgid="8939524935808875155">"<xliff:g id="NAME">%1$s</xliff:g> द्वारा प्रस्थान किया जा रहा है…"</string> <string name="owner_name" msgid="2716755460376028154">"स्वामी"</string> <string name="error_message_title" msgid="4510373083082500195">"गड़बड़ी"</string> <string name="error_message_change_not_allowed" msgid="1238035947357923497">"आपका व्यवस्थापक इस बदलाव की अनुमति नहीं देता"</string> <string name="app_not_found" msgid="3429141853498927379">"इस कार्यवाही को प्रबंधित करने के लिए कोई ऐप्स नहीं मिला"</string> - <string name="revoke" msgid="5404479185228271586">"निरस्त करें"</string> + <string name="revoke" msgid="5404479185228271586">"रद्द करें"</string> <string name="mediasize_iso_a0" msgid="1994474252931294172">"ISO A0"</string> <string name="mediasize_iso_a1" msgid="3333060421529791786">"ISO A1"</string> <string name="mediasize_iso_a2" msgid="3097535991925798280">"ISO A2"</string> @@ -1596,7 +1596,7 @@ <string name="restr_pin_enter_new_pin" msgid="5959606691619959184">"नया पिन"</string> <string name="restr_pin_confirm_pin" msgid="8501523829633146239">"नए पिन की दुबारा पूछें"</string> <string name="restr_pin_create_pin" msgid="8017600000263450337">"प्रतिबंधों को बदलने के लिए PIN बनाएं"</string> - <string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN मिलान नहीं करते हैं. फिर से प्रयास करें."</string> + <string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN मेल नहीं खाते हैं. फिर से कोशिश करें."</string> <string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN बहुत छोटा है. कम से कम 4 अंकों का होना चाहिए."</string> <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688"> <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> सेकंड में पुन: प्रयास करें</item> @@ -1627,7 +1627,7 @@ <string name="package_installed_device_owner" msgid="6875717669960212648">"आपके व्यवस्थापक ने इंस्टॉल किया है"</string> <string name="package_updated_device_owner" msgid="1847154566357862089">"आपके व्यवस्थापक ने अपडेट किया है"</string> <string name="package_deleted_device_owner" msgid="2307122077550236438">"आपके व्यवस्थापक ने हटा दिया है"</string> - <string name="battery_saver_description" msgid="1960431123816253034">"बैटरी लाइफ़ बेहतर बनाने में सहायता के लिए, बैटरी सेवर आपके डिवाइस के प्रदर्शन को कम कर देता है और कंपन, स्थान सेवाओं और अधिकांश पृष्ठभूमि डेटा को सीमित कर देता है. हो सकता है कि ईमेल, संदेश सेवा और सिंक पर आधारित अन्य ऐप्स तब तक ना खुलें जब तक कि आप उन्हें नहीं खोलते.\n\nजब आपका डिवाइस चार्ज हो रहा होता है तो बैटरी सेवर अपने आप बंद हो जाता है."</string> + <string name="battery_saver_description" msgid="1960431123816253034">"बैटरी लाइफ़ को बेहतर बनाने में मदद करने के लिए, बैटरी सेवर आपके डिवाइस के प्रदर्शन को कम कर देता है और कंपन (वाइब्रेशन), स्थान सेवाओं और ज़्यादातर बैकग्राउंड डेटा को सीमित कर देता है. हो सकता है कि ईमेल, मैसेज सेवा और सिंक पर आधारित अन्य ऐप तब तक ना खुलें जब तक कि आप उन्हें नहीं खोलते.\n\nजब आपका डिवाइस चार्ज हो रहा होता है तो बैटरी सेवर अपने आप बंद हो जाता है."</string> <string name="data_saver_description" msgid="6015391409098303235">"डेटा खर्च, कम करने के लिए डेटा सेवर कुछ ऐप को बैकग्राउंड में डेटा भेजने या पाने से रोकता है. आप फ़िलहाल जिस एेप का इस्तेमाल कर रहे हैं वह डेटा एक्सेस कर सकता है, लेकिन ऐसा कभी-कभी ही हो पाएगा. उदाहरण के लिए, इसका मतलब है कि इमेज तब तक दिखाई नहीं देंगी जब तक कि आप उन्हें टैप नहीं करते."</string> <string name="data_saver_enable_title" msgid="4674073932722787417">"डेटा बचाने की सेटिंग चालू करें?"</string> <string name="data_saver_enable_button" msgid="7147735965247211818">"चालू करें"</string> @@ -1690,7 +1690,7 @@ <string name="usb_midi_peripheral_name" msgid="7221113987741003817">"Android USB पेरिफ़ेरल पोर्ट"</string> <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string> <string name="usb_midi_peripheral_product_name" msgid="4971827859165280403">"USB पेरिफ़ेरल पोर्ट"</string> - <string name="floating_toolbar_open_overflow_description" msgid="4797287862999444631">"अधिक विकल्प"</string> + <string name="floating_toolbar_open_overflow_description" msgid="4797287862999444631">"ज़्यादा विकल्प"</string> <string name="floating_toolbar_close_overflow_description" msgid="559796923090723804">"ओवरफ़्लो बंद करें"</string> <string name="maximize_button_text" msgid="7543285286182446254">"बड़ा करें"</string> <string name="close_button_text" msgid="3937902162644062866">"बंद करें"</string> @@ -1700,22 +1700,22 @@ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> चयनित</item> </plurals> <string name="default_notification_channel_label" msgid="5929663562028088222">"अवर्गीकृत"</string> - <string name="importance_from_user" msgid="7318955817386549931">"आपने इन नोटिफ़िकेशन का महत्व सेट किया है."</string> + <string name="importance_from_user" msgid="7318955817386549931">"आपने इन सूचनाओं की अहमियत सेट की है."</string> <string name="importance_from_person" msgid="9160133597262938296">"यह मौजूद व्यक्तियों के कारण महत्वपूर्ण है."</string> - <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> को <xliff:g id="ACCOUNT">%2$s</xliff:g> के द्वारा एक नया उपयोगकर्ता बनाने दें?"</string> - <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> को <xliff:g id="ACCOUNT">%2$s</xliff:g> के द्वारा एक नया उपयोगकर्ता बनाने दें (इस खाते वाला एक उपयोगकर्ता पहले से मौजूद है) ?"</string> + <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> को <xliff:g id="ACCOUNT">%2$s</xliff:g> के ज़रिये एक नया उपयोगकर्ता बनाने दें?"</string> + <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> को <xliff:g id="ACCOUNT">%2$s</xliff:g> के ज़रिये एक नया उपयोगकर्ता बनाने दें (इस खाते वाले एक उपयोगकर्ता पहले से मौजूद हैं)?"</string> <string name="language_selection_title" msgid="2680677278159281088">"भाषा जोड़ें"</string> <string name="country_selection_title" msgid="2954859441620215513">"क्षेत्र प्राथमिकता"</string> <string name="search_language_hint" msgid="7042102592055108574">"भाषा का नाम लिखें"</string> <string name="language_picker_section_suggested" msgid="8414489646861640885">"सुझाए गए"</string> <string name="language_picker_section_all" msgid="3097279199511617537">"सभी भाषाएं"</string> <string name="region_picker_section_all" msgid="8966316787153001779">"सभी क्षेत्र"</string> - <string name="locale_search_menu" msgid="2560710726687249178">"खोजें"</string> + <string name="locale_search_menu" msgid="2560710726687249178">"सर्च करें"</string> <string name="work_mode_off_title" msgid="2615362773958585967">"कार्य मोड चालू करें?"</string> <string name="work_mode_off_message" msgid="2961559609199223594">"इससे आपकी कार्य प्रोफ़ाइल चालू हो जाएगी, जिसमें ऐप्लिकेशन, बैकग्राउंड सिंक और संबंधित सुविधाएं शामिल हैं"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"चालू करें"</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"आपके पास नए संदेश हैं"</string> - <string name="new_sms_notification_content" msgid="7002938807812083463">"देखने के लिए SMS ऐप खोलें"</string> + <string name="new_sms_notification_content" msgid="7002938807812083463">"देखने के लिए मैसेज (एसएमएस) ऐप खोलें"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"कुछ कार्य क्षमताएं सीमित हो सकती हैं"</string> <string name="user_encrypted_message" msgid="4923292604515744267">"अनलॉक करने के लिए टैप करें"</string> <string name="user_encrypted_detail" msgid="5708447464349420392">"उपयोगकर्ता डेटा लॉक किया गया"</string> @@ -1766,11 +1766,11 @@ <string name="autofill_save_type_password" msgid="5288448918465971568">"पासवर्ड"</string> <string name="autofill_save_type_address" msgid="4936707762193009542">"पता"</string> <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"क्रेडिट कार्ड"</string> - <string name="autofill_save_type_username" msgid="239040540379769562">"उपयोगकर्ता नाम"</string> + <string name="autofill_save_type_username" msgid="239040540379769562">"उपयोगकर्ता का नाम"</string> <string name="autofill_save_type_email_address" msgid="5752949432129262174">"ईमेल पता"</string> - <string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"शांत रहें और आस-पास शरण स्थल खोजें."</string> + <string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"शांत रहें और आस-पास शरण लेने की जगह तलाशें."</string> <string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"तटीय क्षेत्रों और नदी के किनारे वाले क्षेत्रों को जल्द से जल्द खाली करके किसी सुरक्षित ऊंची जगह पर चले जाएं."</string> - <string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"शांत रहें और आस-पास आश्रय खोजें."</string> + <string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"शांत रहें और आस-पास शरण लेने की जगह तलाशें."</string> <string name="etws_primary_default_message_test" msgid="2709597093560037455">"आपातकालीन संदेश परीक्षण"</string> <string name="notification_reply_button_accessibility" msgid="3621714652387814344">"जवाब दें"</string> <string name="etws_primary_default_message_others" msgid="6293148756130398971"></string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index 9dee459182a5..dea21f0c8700 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -251,9 +251,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozorenja"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Prodajni demo-način"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB veza"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Izvođenje aplikacija u pozadini"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> izvodi se u pozadini"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"Aplikacije koje se izvode u pozadini: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Aplikacije troše bateriju"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> koristi bateriju"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"Broj aplikacija koje koriste bateriju: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Dodirnite da biste vidjeli pojedinosti o potrošnji baterije i podatkovnom prometu"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Siguran način rada"</string> @@ -264,7 +264,7 @@ <string name="permgroupdesc_contacts" msgid="6951499528303668046">"pristupati vašim kontaktima"</string> <string name="permgrouprequest_contacts" msgid="1601591667800538208">"Dopustite aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> da pristupa vašim kontaktima"</string> <string name="permgrouplab_location" msgid="7275582855722310164">"Lokacija"</string> - <string name="permgroupdesc_location" msgid="1346617465127855033">"pristup lokaciji ovog uređaja"</string> + <string name="permgroupdesc_location" msgid="1346617465127855033">"pristupiti lokaciji ovog uređaja"</string> <string name="permgrouprequest_location" msgid="8903573681261610809">"Dopustite aplikaciji <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> da pristupa lokaciji ovog uređaja"</string> <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalendar"</string> <string name="permgroupdesc_calendar" msgid="3889615280211184106">"pristupati kalendaru"</string> @@ -1316,9 +1316,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Povezan sa sesijom <xliff:g id="SESSION">%s</xliff:g>. Dotaknite za upravljanje mrežom."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Povezivanje s uvijek uključenom VPN mrežom…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Povezan s uvijek uključenom VPN mrežom"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Prekinuta je veza s uvijek uključenom VPN mrežom"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Prekinuta je veza s uvijek uključenim VPN-om"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Pogreška uvijek uključene VPN mreže"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Dodirnite za postavljanje"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Promijenite mrežu ili postavke VPN-a"</string> <string name="upload_file" msgid="2897957172366730416">"Odaberite datoteku"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Nema odabranih datoteka"</string> <string name="reset" msgid="2448168080964209908">"Ponovo postavi"</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index 425d2a182878..d4be9b5cda1d 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Értesítések"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Kiskereskedelmi bemutató"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB-kapcsolat"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"A háttérben még futnak alkalmazások"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> a háttérben fut"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> alkalmazás még fut a háttérben"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Akkumulátort használó alkalmazások"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás használja az akkumulátort"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> alkalmazás használja az akkumulátort"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Koppintson az akkumulátor- és adathasználat részleteinek megtekintéséhez"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Biztonsági üzemmód"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Csatlakozva ide: <xliff:g id="SESSION">%s</xliff:g>. Érintse meg a hálózat kezeléséhez."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Csatlakozás a mindig bekapcsolt VPN-hez..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Csatlakozva a mindig bekapcsolt VPN-hez"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Kapcsolat bontva a mindig bekapcsolt VPN-nel"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Mindig bekapcsolt állapotú VPN-ről leválasztva"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Hiba a mindig bekapcsolt VPN-nel"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Koppintson ide a beállításhoz"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Hálózati vagy VPN-beállítások módosítása"</string> <string name="upload_file" msgid="2897957172366730416">"Fájl kiválasztása"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Nincs fájl kiválasztva"</string> <string name="reset" msgid="2448168080964209908">"Alaphelyzet"</string> diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml index 7f70b3044555..7e3721f27073 100644 --- a/core/res/res/values-hy/strings.xml +++ b/core/res/res/values-hy/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Ծանուցումներ"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Խանութի ցուցադրական ռեժիմ"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB կապակցում"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Ֆոնային ռեժիմում աշխատող հավելվածներ"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ն աշխատում է ֆոնային ռեժիմում"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> հավելված աշխատում են ֆոնում"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Մարտկոցի լիցքը ծախսող հավելվածներ"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"«<xliff:g id="APP_NAME">%1$s</xliff:g>» հավելվածը ծախսում է մարտկոցի լիցքը"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> հավելված ծախսում է մարտկոցի լիցքը"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Հպեք՝ մարտկոցի և թրաֆիկի մանրամասները տեսնելու համար"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Անվտանգ ռեժիմ"</string> @@ -1205,7 +1205,7 @@ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Հպեք՝ լեզուն և դասավորությունն ընտրելու համար"</string> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՈՒՓՔԵւՕՖ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> - <string name="alert_windows_notification_channel_group_name" msgid="1463953341148606396">"Ցույց տալ այլ հավելվածների վրա"</string> + <string name="alert_windows_notification_channel_group_name" msgid="1463953341148606396">"Ցույց տալ այլ հավելվածների վրայից"</string> <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> հավելվածը ցուցադրվում է այլ հավելվածների վերևում"</string> <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> հավելվածը ցուցադրվում է այլ հավելվածների վերևում"</string> <string name="alert_windows_notification_message" msgid="8917232109522912560">"Եթե չեք ցանկանում, որ <xliff:g id="NAME">%s</xliff:g>-ն օգտագործի այս գործառույթը, հպեք՝ կարգավորումները բացելու և այն անջատելու համար։"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Կապակացված է <xliff:g id="SESSION">%s</xliff:g>-ին: Սեղմեք` ցանցը կառավարելու համար:"</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Միշտ-միացված VPN-ը կապվում է..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Միշտ-առցանց VPN-ը կապակցված է"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"«Միշտ միացված VPN»-ն անջատված է"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Անջատված է միշտ միացված VPN ցանցից"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"VPN սխալը միշտ միացված"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Հպեք՝ կարգավորելու համար"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Փոխել ցանցը կամ VPN-ի կարգավորումները"</string> <string name="upload_file" msgid="2897957172366730416">"Ընտրել ֆայլը"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Ոչ մի ֆայլ չի ընտրված"</string> <string name="reset" msgid="2448168080964209908">"Վերակայել"</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 1ea312b9651a..e90cce101586 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Notifikasi"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demo promo"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Sambungan USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Aplikasi yang sedang berjalan di latar belakang"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang berjalan di latar belakang"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikasi sedang berjalan di latar belakang"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Aplikasi yang menggunakan baterai"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang menggunakan baterai"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikasi sedang meggunakan baterai"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Tap untuk melihat detail penggunaan baterai dan data"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Mode aman"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Tersambung ke <xliff:g id="SESSION">%s</xliff:g>. Ketuk untuk mengelola jaringan."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Menyambungkan VPN selalu aktif..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN selalu aktif tersambung"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"VPN selalu aktif terputus"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Terputus dari VPN yang selalu aktif"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Kesalahan VPN selalu aktif"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Ketuk untuk menyiapkan"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Ubah setelan jaringan atau VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Pilih file"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Tidak ada file yang dipilih"</string> <string name="reset" msgid="2448168080964209908">"Setel ulang"</string> diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml index faf1d2e251e3..bb067b1b09d9 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Tilkynningar"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Kynningarútgáfa fyrir verslanir"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB-tenging"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Forrit sem keyra í bakgrunni"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> keyrir í bakgrunni"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> forrit keyra í bakgrunni"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Forrit sem nota rafhlöðuorku"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> notar rafhlöðuorku"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> forrit nota rafhlöðuorku"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Ýttu til að fá upplýsingar um rafhlöðu- og gagnanotkun"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Örugg stilling"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Tengt við <xliff:g id="SESSION">%s</xliff:g>. Ýttu til að hafa umsjón með netinu."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Sívirkt VPN tengist…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Sívirkt VPN tengt"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Sívirkt VPN aftengt"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Aftengt frá sívirku VPN"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Villa í sívirku VPN"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Ýttu til að setja upp"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Breyta stillingum netkerfis eða VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Velja skrá"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Engin skrá valin"</string> <string name="reset" msgid="2448168080964209908">"Endurstilla"</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 23162a61b826..8fa140e7f04f 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Avvisi"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demo retail"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Connessione USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"App in esecuzione in background"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> è in esecuzione in background"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> app sono in esecuzione in background"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"App che consumano la batteria"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"L\'app <xliff:g id="APP_NAME">%1$s</xliff:g> sta consumando la batteria"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> app stanno consumando la batteria"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Tocca per conoscere i dettagli sull\'utilizzo dei dati e della batteria"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Modalità provvisoria"</string> @@ -260,7 +260,7 @@ <string name="permgrouplab_contacts" msgid="3657758145679177612">"Contatti"</string> <string name="permgroupdesc_contacts" msgid="6951499528303668046">"accedere ai contatti"</string> <string name="permgrouprequest_contacts" msgid="1601591667800538208">"Consenti a <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di accedere ai tuoi contatti"</string> - <string name="permgrouplab_location" msgid="7275582855722310164">"Posizione"</string> + <string name="permgrouplab_location" msgid="7275582855722310164">"Geolocalizzazione"</string> <string name="permgroupdesc_location" msgid="1346617465127855033">"accedere alla posizione di questo dispositivo"</string> <string name="permgrouprequest_location" msgid="8903573681261610809">"Consenti a <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> di accedere alla posizione di questo dispositivo"</string> <string name="permgrouplab_calendar" msgid="5863508437783683902">"Calendario"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Collegata a <xliff:g id="SESSION">%s</xliff:g>. Tocca per gestire la rete."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Connessione a VPN sempre attiva…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN sempre attiva connessa"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"VPN sempre attiva disconnessa"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Disconnesso da VPN sempre attiva"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Errore VPN sempre attiva"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tocca per configurare"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Cambia le impostazioni VPN o di rete"</string> <string name="upload_file" msgid="2897957172366730416">"Scegli file"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Nessun file è stato scelto"</string> <string name="reset" msgid="2448168080964209908">"Reimposta"</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 4a0531e334e4..e86d1141ad28 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -254,9 +254,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"התראות"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"הדגמה לקמעונאים"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"חיבור USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"אפליקציות שפועלות ברקע"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> פועלת ברקע"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> אפליקציות פועלות ברקע"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"אפליקציות שמרוקנות את הסוללה"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> משתמשת בסוללה"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> אפליקציות משתמשות בסוללה"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"הקש לקבלת פרטים על צריכה של נתונים וסוללה"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="RIGHT_SIDE">%2$s</xliff:g>, <xliff:g id="LEFT_SIDE">%1$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"מצב בטוח"</string> @@ -855,8 +855,8 @@ <string name="menu_space_shortcut_label" msgid="2410328639272162537">"רווח"</string> <string name="menu_enter_shortcut_label" msgid="2743362785111309668">"Enter"</string> <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"מחק"</string> - <string name="search_go" msgid="8298016669822141719">"חפש"</string> - <string name="search_hint" msgid="1733947260773056054">"חפש…"</string> + <string name="search_go" msgid="8298016669822141719">"חיפוש"</string> + <string name="search_hint" msgid="1733947260773056054">"חיפוש…"</string> <string name="searchview_description_search" msgid="6749826639098512120">"חיפוש"</string> <string name="searchview_description_query" msgid="5911778593125355124">"שאילתת חיפוש"</string> <string name="searchview_description_clear" msgid="1330281990951833033">"נקה שאילתה"</string> @@ -1243,7 +1243,7 @@ <string name="share_remote_bugreport_action" msgid="6249476773913384948">"שתף"</string> <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"לא, אין מצב"</string> <string name="select_input_method" msgid="8547250819326693584">"שינוי מקלדת"</string> - <string name="show_ime" msgid="2506087537466597099">"תישאר במסך בזמן שהמקלדת הפיזית פעילה"</string> + <string name="show_ime" msgid="2506087537466597099">"להשאיר במסך בזמן שהמקלדת הפיזית פעילה"</string> <string name="hardware" msgid="194658061510127999">"הצג מקלדת וירטואלית"</string> <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"הגדרת מקלדת פיזית"</string> <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"הקש כדי לבחור שפה ופריסה"</string> @@ -1306,7 +1306,7 @@ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"הקש פעמיים לבקרת מרחק מתצוגה"</string> <string name="gadget_host_error_inflating" msgid="4882004314906466162">"לא ניתן להוסיף widget."</string> <string name="ime_action_go" msgid="8320845651737369027">"התחל"</string> - <string name="ime_action_search" msgid="658110271822807811">"חפש"</string> + <string name="ime_action_search" msgid="658110271822807811">"חיפוש"</string> <string name="ime_action_send" msgid="2316166556349314424">"שלח"</string> <string name="ime_action_next" msgid="3138843904009813834">"הבא"</string> <string name="ime_action_done" msgid="8971516117910934605">"סיום"</string> @@ -1338,9 +1338,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"מחובר אל <xliff:g id="SESSION">%s</xliff:g>. הקש כדי לנהל את הרשת."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"ה-VPN שמופעל תמיד, מתחבר..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"ה-VPN שפועל תמיד, מחובר"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"חיבור תמידי ל-VPN מנותק"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"אין חיבור ל-VPN שפועל כל הזמן"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"שגיאת VPN שמופעל תמיד"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"הקש כדי להגדיר"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"רוצה לשנות את הגדרות הרשת או הגדרות ה-VPN?"</string> <string name="upload_file" msgid="2897957172366730416">"בחר קובץ"</string> <string name="no_file_chosen" msgid="6363648562170759465">"לא נבחר קובץ"</string> <string name="reset" msgid="2448168080964209908">"איפוס"</string> @@ -1545,7 +1545,7 @@ <string name="error_message_title" msgid="4510373083082500195">"שגיאה"</string> <string name="error_message_change_not_allowed" msgid="1238035947357923497">"מנהל המערכת שלך אינו מתיר שינוי זה"</string> <string name="app_not_found" msgid="3429141853498927379">"לא נמצאה אפליקציה שתומכת בפעולה זו"</string> - <string name="revoke" msgid="5404479185228271586">"בטל"</string> + <string name="revoke" msgid="5404479185228271586">"ביטול"</string> <string name="mediasize_iso_a0" msgid="1994474252931294172">"ISO A0"</string> <string name="mediasize_iso_a1" msgid="3333060421529791786">"ISO A1"</string> <string name="mediasize_iso_a2" msgid="3097535991925798280">"ISO A2"</string> @@ -1652,7 +1652,7 @@ </plurals> <string name="restr_pin_try_later" msgid="973144472490532377">"נסה שוב מאוחר יותר"</string> <string name="immersive_cling_title" msgid="8394201622932303336">"צפייה במסך מלא"</string> - <string name="immersive_cling_description" msgid="3482371193207536040">"כדי לצאת, החלק מלמעלה למטה."</string> + <string name="immersive_cling_description" msgid="3482371193207536040">"כדי לצאת, פשוט מחליקים אצבע מלמעלה למטה."</string> <string name="immersive_cling_positive" msgid="5016839404568297683">"הבנתי"</string> <string name="done_label" msgid="2093726099505892398">"בוצע"</string> <string name="hour_picker_description" msgid="6698199186859736512">"מחוון שעות מעגלי"</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 7faa416ed4c2..010351a9cb96 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"通知"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"販売店デモ"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB 接続"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"バックグラウンドで実行中のアプリ"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」がバックグラウンドで実行中です"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> 個のアプリがバックグラウンドで実行中です"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"アプリが電池を消費しています"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」が電池を使用しています"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> 個のアプリが電池を使用しています"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"タップして電池やデータの使用量を確認"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>、<xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"セーフモード"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g>に接続しました。ネットワークを管理するにはタップしてください。"</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPNに常時接続しています…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPNに常時接続しました"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"常時接続 VPN の接続を解除しました"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"常時接続 VPN から切断されました"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"常時接続VPNのエラー"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"設定するにはタップします"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"ネットワークまたは VPN の設定を変更できます"</string> <string name="upload_file" msgid="2897957172366730416">"ファイルを選択"</string> <string name="no_file_chosen" msgid="6363648562170759465">"ファイルが選択されていません"</string> <string name="reset" msgid="2448168080964209908">"リセット"</string> @@ -1433,7 +1433,7 @@ <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"設定"</string> <string name="media_route_controller_disconnect" msgid="8966120286374158649">"接続を解除"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"スキャン中..."</string> - <string name="media_route_status_connecting" msgid="6422571716007825440">"接続中..."</string> + <string name="media_route_status_connecting" msgid="6422571716007825440">"接続処理中..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"利用できます"</string> <string name="media_route_status_not_available" msgid="6739899962681886401">"利用できません"</string> <string name="media_route_status_in_use" msgid="4533786031090198063">"使用中"</string> @@ -1604,7 +1604,7 @@ </plurals> <string name="restr_pin_try_later" msgid="973144472490532377">"しばらくしてから再試行"</string> <string name="immersive_cling_title" msgid="8394201622932303336">"全画面表示"</string> - <string name="immersive_cling_description" msgid="3482371193207536040">"終了するには、上部から下にスワイプします。"</string> + <string name="immersive_cling_description" msgid="3482371193207536040">"終了するには、上から下にスワイプします。"</string> <string name="immersive_cling_positive" msgid="5016839404568297683">"OK"</string> <string name="done_label" msgid="2093726099505892398">"完了"</string> <string name="hour_picker_description" msgid="6698199186859736512">"円形スライダー(時)"</string> diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml index fc108b4d3e77..3250d4ad13de 100644 --- a/core/res/res/values-ka/strings.xml +++ b/core/res/res/values-ka/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"გაფრთხილებები"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"დემო-რეჟიმი საცალო მოვაჭრეებისთვის"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB კავშირი"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"ფონურ რეჟიმში გაშვებული აპები"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> გაშვებულია ფონურ რეჟიმში"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"ფონურ რეჟიმში გაშვებულია <xliff:g id="NUMBER">%1$d</xliff:g> აპი"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"ბატარეის მხარჯავი აპები"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> იყენებს ბატარეას"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"ბატარეას <xliff:g id="NUMBER">%1$d</xliff:g> აპი იყენებს"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"შეეხეთ ბატარეისა და მონაცემების მოხმარების შესახებ დეტალური ინფორმაციისთვის"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"უსაფრთხო რეჟიმი"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"მიერთებულია <xliff:g id="SESSION">%s</xliff:g>-ზე. შეეხეთ ქსელის სამართავად."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"მიმდინარეობს მუდმივად ჩართული VPN-ის მიერთება…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"მუდმივად ჩართული VPN-ის მიერთებულია"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"მუდმივად ჩართული VPN გათიშულია"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"გათიშულია მუდმივად ჩართული VPN-იდან"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"შეცდომა მუდამ VPN-ზე"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"შეეხეთ დასაყენებლად"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"შეცვალეთ ქსელი ან VPN-ის პარამეტრები"</string> <string name="upload_file" msgid="2897957172366730416">"ფაილის არჩევა"</string> <string name="no_file_chosen" msgid="6363648562170759465">"ფაილი არჩეული არ არის"</string> <string name="reset" msgid="2448168080964209908">"საწყისზე დაბრუნება"</string> @@ -1627,7 +1627,7 @@ <string name="package_installed_device_owner" msgid="6875717669960212648">"დაინსტალირებულია თქვენი ადმინისტრატორის მიერ"</string> <string name="package_updated_device_owner" msgid="1847154566357862089">"განახლებულია თქვენი ადმინისტრატორის მიერ"</string> <string name="package_deleted_device_owner" msgid="2307122077550236438">"წაიშალა თქვენი ადმინისტრატორის მიერ"</string> - <string name="battery_saver_description" msgid="1960431123816253034">"ელემენტის მოქმედების ვადის გაუმჯობესებისათვის, ელემენტის დამზოგი ამცირებს თქვენი მოწყობილობის ფუნქციონალობას და ზღუდავს ვიბრაციას, ადგილმდებარეობის სერვისებს და ძირითად ფონურ მონაცემებს. ელფოსტა, შეტყობინებები და სხვა სინქრონიზაციაზე დაყრდნობილი აპების განახლება არ მოხდება მათ გახსნამდე.\n\nელემენტის დამზოგველი ავტომატურად გამოირთვება, როდესაც თქვენს მოწყობილობას დამტენთან შეაერთებთ."</string> + <string name="battery_saver_description" msgid="1960431123816253034">"ბატარეის მოქმედების ვადის გაუმჯობესებისათვის, ბატარეის დამზოგი ამცირებს თქვენი მოწყობილობის ფუნქციონალობას და ზღუდავს ვიბრაციას, ადგილმდებარეობის სერვისებს და ძირითად ფონურ მონაცემებს. ელფოსტა, შეტყობინებები და სხვა სინქრონიზაციაზე დაყრდნობილი აპების განახლება არ მოხდება მათ გახსნამდე.\n\nბატარეის დამზოგველი ავტომატურად გამოირთვება, როდესაც თქვენს მოწყობილობას დამტენთან შეაერთებთ."</string> <string name="data_saver_description" msgid="6015391409098303235">"მობილური ინტერნეტის მოხმარების შემცირების მიზნით, მონაცემთა დამზოგველი ზოგიერთ აპს ფონურ რეჟიმში მონაცემთა გაგზავნასა და მიღებას შეუზღუდავს. თქვენ მიერ ამჟამად გამოყენებული აპი მაინც შეძლებს მობილურ ინტერნეტზე წვდომას, თუმცა ამას ნაკლები სიხშირით განახორციელებს. ეს ნიშნავს, რომ, მაგალითად, სურათები არ გამოჩნდება მანამ, სანამ მათ საგანგებოდ არ შეეხებით."</string> <string name="data_saver_enable_title" msgid="4674073932722787417">"ჩაირთოს მონაცემთა დამზოგველი?"</string> <string name="data_saver_enable_button" msgid="7147735965247211818">"ჩართვა"</string> diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml index 8825b7eb29d0..cf14d476cd46 100644 --- a/core/res/res/values-kk/strings.xml +++ b/core/res/res/values-kk/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Дабылдар"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Бөлшек саудаға арналған демо нұсқасы"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB байланысы"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Фонда жұмыс істеп тұрған қолданбалар"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> фонда жұмыс істеп тұр"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> қолданба фонда жұмыс істеп тұр"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Батареяны пайдаланып жатқан қолданбалар"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> батареяны пайдалануда"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> қолданба батареяны пайдалануда"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Батарея мен деректер трафигі туралы білу үшін түртіңіз"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Қауіпсіз режим"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> жүйесіне жалғанған. Желіні басқару үшін түріңіз."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Әрқашан қосылған ВЖЖ жалғануда…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Әрқашан қосылған ВЖЖ жалғанған"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Әрқашан қосулы VPN желісі ажыратылды"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Әрқашан қосулы VPN желісінен ажырады"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Әрқашан қосылған ВЖЖ қателігі"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Реттеу үшін түртіңіз"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Желіні не VPN параметрлерін өзгерту"</string> <string name="upload_file" msgid="2897957172366730416">"Файлды таңдау"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Ешқандай файл таңдалмаған"</string> <string name="reset" msgid="2448168080964209908">"Қайта реттеу"</string> diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml index 256faa403b33..399b329ad0c2 100644 --- a/core/res/res/values-km/strings.xml +++ b/core/res/res/values-km/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"ការជូនដំណឹង"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"របៀបដាក់បង្ហាញក្នុងហាង"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"ការតភ្ជាប់ USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"កម្មវិធីដែលកំពុងដំណើរការនៅផ្ទៃខាងក្រោយ"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងដំណើរការនៅផ្ទៃខាងក្រោយ"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"កម្មវិធី <xliff:g id="NUMBER">%1$d</xliff:g> កំពុងដំណើរការនៅផ្ទៃខាងក្រោយ"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"កម្មវិធីដែលកំពុងប្រើថ្ម"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងប្រើថ្ម"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"កម្មវិធីចំនួន <xliff:g id="NUMBER">%1$d</xliff:g> កំពុងប្រើថ្ម"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"ចុចដើម្បីមើលព័ត៌មានលម្អិតអំពីការប្រើប្រាស់ទិន្នន័យ និងថ្ម"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"របៀបសុវត្ថិភាព"</string> @@ -1296,9 +1296,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"បានភ្ជាប់ទៅ <xliff:g id="SESSION">%s</xliff:g> ។ ប៉ះ ដើម្បីគ្រប់គ្រងបណ្ដាញ។"</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"បើកការតភ្ជាប់ VPN ជានិច្ច..។"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"ភ្ជាប់ VPN ជានិច្ច"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"បានផ្តាច់ VPN ដែលបើកជានិច្ច"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"បានផ្ដាច់ពី VPN បើកជានិច្ច"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"បើកកំហុស VPN ជានិច្ច"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"ប៉ះដើម្បីដំឡើង"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"ប្ដូរការកំណត់បណ្ដាញ ឬការកំណត់ VPN"</string> <string name="upload_file" msgid="2897957172366730416">"ជ្រើសឯកសារ"</string> <string name="no_file_chosen" msgid="6363648562170759465">"គ្មានឯកសារបានជ្រើស"</string> <string name="reset" msgid="2448168080964209908">"កំណត់ឡើងវិញ"</string> diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index 86f547ce4cda..bacf7317e04b 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"ಎಚ್ಚರಿಕೆಗಳು"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"ರಿಟೇಲ್ ಡೆಮೋ"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB ಸಂಪರ್ಕ"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"ಅಪ್ಲಿಕೇಶನ್ಗಳು ಹಿನ್ನೆಲೆಯಲ್ಲಿ ರನ್ ಆಗುತ್ತಿವೆ"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"ಹಿನ್ನೆಲೆಯಲ್ಲಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ರನ್ ಆಗುತ್ತಿದೆ"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> ಅಪ್ಲಿಕೇಶನ್ಗಳು ಹಿನ್ನೆಲೆಯಲ್ಲಿ ರನ್ ಆಗುತ್ತಿವೆ"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"ಅಪ್ಲಿಕೇಶನ್ಗಳು ಬ್ಯಾಟರಿಯನ್ನು ಉಪಯೋಗಿಸುತ್ತಿವೆ"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಬಳಸುತ್ತಿದೆ"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> ಅಪ್ಲಿಕೇಶನ್ಗಳು ಬ್ಯಾಟರಿ ಬಳಸುತ್ತಿವೆ"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"ಬ್ಯಾಟರಿ,ಡೇಟಾ ಬಳಕೆಯ ವಿವರಗಳಿಗಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"ಸುರಕ್ಷಿತ ಮೋಡ್"</string> @@ -261,7 +261,7 @@ <string name="permgroupdesc_contacts" msgid="6951499528303668046">"ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ಪ್ರವೇಶಿಸಲು"</string> <string name="permgrouprequest_contacts" msgid="1601591667800538208">"ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ಪ್ರವೇಶಿಸಲು <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ಗೆ ಅನುಮತಿಸಿ"</string> <string name="permgrouplab_location" msgid="7275582855722310164">"ಸ್ಥಳ"</string> - <string name="permgroupdesc_location" msgid="1346617465127855033">"ಈ ಸಾಧನದ ಸ್ಥಳ ಪ್ರವೇಶಿಸಲು"</string> + <string name="permgroupdesc_location" msgid="1346617465127855033">"ಈ ಸಾಧನದ ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಿ"</string> <string name="permgrouprequest_location" msgid="8903573681261610809">"ಈ ಸಾಧನದ ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಲು <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ಗೆ ಅನುಮತಿಸಿ"</string> <string name="permgrouplab_calendar" msgid="5863508437783683902">"ಕ್ಯಾಲೆಂಡರ್"</string> <string name="permgroupdesc_calendar" msgid="3889615280211184106">"ನಿಮ್ಮ ಕ್ಯಾಲೆಂಡರ್ ಪ್ರವೇಶಿಸಲು"</string> @@ -291,7 +291,7 @@ <string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"ನೀವು ಟೈಪ್ ಮಾಡುವ ಪಠ್ಯವನ್ನು ಗಮನಿಸುತ್ತದೆ"</string> <string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"ಕ್ರೆಡಿಟ್ ಕಾರ್ಡ್ ಸಂಖ್ಯೆಗಳು ಮತ್ತು ಪಾಸ್ವರ್ಡ್ಗಳಂತಹ ವೈಯಕ್ತಿಕ ಡೇಟಾವನ್ನು ಒಳಗೊಂಡಿರುತ್ತದೆ."</string> <string name="capability_title_canControlMagnification" msgid="3593493281059424855">"ಡಿಸ್ಪ್ಲೇ ವರ್ಧಕ ನಿಯಂತ್ರಿಸುತ್ತದೆ"</string> - <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ಪ್ರದರ್ಶನದ ಝೂಮ್ ಮಟ್ಟ ಮತ್ತು ಸ್ಥಳ ನಿರ್ಧಾರವನ್ನು ನಿಯಂತ್ರಿಸಿ."</string> + <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ಪ್ರದರ್ಶನದ ಝೂಮ್ ಮಟ್ಟ ಮತ್ತು ಸ್ಥಾನ ನಿರ್ಧಾರವನ್ನು ನಿಯಂತ್ರಿಸಿ."</string> <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ಗೆಸ್ಚರ್ಗಳನ್ನು ಮಾಡಿ"</string> <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ಟ್ಯಾಪ್ ಮಾಡಬಹುದು, ಸ್ವೈಪ್ ಮಾಡಬಹುದು, ಪಿಂಚ್ ಮಾಡಬಹುದು ಮತ್ತು ಇತರ ಗೆಸ್ಚರ್ಗಳನ್ನು ಮಾಡಬಹುದು."</string> <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೂಚಕಗಳು"</string> @@ -304,7 +304,7 @@ <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ವಿಸ್ತರಿಸಲು ಅಥವಾ ಸಂಕುಚಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string> <string name="permlab_install_shortcut" msgid="4279070216371564234">"ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ಸ್ಥಾಪಿಸಿ"</string> <string name="permdesc_install_shortcut" msgid="8341295916286736996">"ಬಳಕೆದಾರರ ಮಧ್ಯಸ್ಥಿಕೆ ಇಲ್ಲದೆಯೇ ಹೋಮ್ಸ್ಕ್ರೀನ್ ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ಸೇರಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ."</string> - <string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ಅಸ್ಥಾಪಿಸಿ"</string> + <string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ಅನ್ಇನ್ಸ್ಟಾಲ್ ಮಾಡಿ"</string> <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"ಬಳಕೆದಾರರ ಮಧ್ಯಸ್ಥಿಕೆ ಇಲ್ಲದೆಯೇ ಹೋಮ್ಸ್ಕ್ರೀನ್ ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string> <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"ಹೊರಹೋಗುವ ಕರೆಗಳ ಮಾರ್ಗ ಬದಲಿಸಿ"</string> <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"ಬೇರೊಂದು ಸಂಖ್ಯೆಗೆ ಕರೆಯನ್ನು ಮರುನಿರ್ದೇಶಿಸಲು ಆಯ್ಕೆಯ ಜೊತೆಗೆ ಹೊರ ಹೋಗುವ ಕರೆಯ ಸಮಯದಲ್ಲಿ ಡಯಲ್ ಮಾಡಿದ ಸಂಖ್ಯೆಯನ್ನು ನೋಡಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ."</string> @@ -753,11 +753,11 @@ <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"ಖಾತೆ ಅನ್ಲಾಕ್"</string> <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"ಹಲವಾರು ಪ್ಯಾಟರ್ನ್ ಪ್ರಯತ್ನಗಳು"</string> <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"ಅನ್ಲಾಕ್ ಮಾಡಲು, ನಿಮ್ಮ Google ಖಾತೆ ಬಳಸಿಕೊಂಡು ಸೈನ್ ಇನ್ ಮಾಡಿ."</string> - <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"ಬಳಕೆದಾರಹೆಸರು (ಇಮೇಲ್)"</string> + <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"ಬಳಕೆದಾರರಹೆಸರು (ಇಮೇಲ್)"</string> <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"ಪಾಸ್ವರ್ಡ್"</string> <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"ಸೈನ್ ಇನ್"</string> - <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"ಅಮಾನ್ಯ ಬಳಕೆದಾರಹೆಸರು ಅಥವಾ ಪಾಸ್ವರ್ಡ್."</string> - <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"ನಿಮ್ಮ ಬಳಕೆದಾರಹೆಸರು ಅಥವಾ ಪಾಸ್ವರ್ಡ್ ಮರೆತಿರುವಿರಾ?\n"<b>"google.com/accounts/recovery"</b>" ಗೆ ಭೇಟಿ ನೀಡಿ."</string> + <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"ಅಮಾನ್ಯ ಬಳಕೆದಾರರಹೆಸರು ಅಥವಾ ಪಾಸ್ವರ್ಡ್."</string> + <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"ನಿಮ್ಮ ಬಳಕೆದಾರರಹೆಸರು ಅಥವಾ ಪಾಸ್ವರ್ಡ್ ಮರೆತಿರುವಿರಾ?\n"<b>"google.com/accounts/recovery"</b>" ಗೆ ಭೇಟಿ ನೀಡಿ."</string> <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"ಪರಿಶೀಲಿಸಲಾಗುತ್ತಿದೆ..."</string> <string name="lockscreen_unlock_label" msgid="737440483220667054">"ಅನ್ಲಾಕ್"</string> <string name="lockscreen_sound_on_label" msgid="9068877576513425970">"ಧ್ವನಿ ಆನ್ ಮಾಡಿ"</string> @@ -1008,7 +1008,7 @@ <string name="whichSendToApplication" msgid="8272422260066642057">"ಇದನ್ನು ಬಳಸಿಕೊಂಡು ಕಳುಹಿಸಿ"</string> <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"%1$s ಬಳಸಿಕೊಂಡು ಕಳುಹಿಸಿ"</string> <string name="whichSendToApplicationLabel" msgid="8878962419005813500">"ಕಳುಹಿಸು"</string> - <string name="whichHomeApplication" msgid="4307587691506919691">"ಮುಖಪುಟ ಅಪ್ಲಿಕೇಶನ್ ಆಯ್ಕೆಮಾಡಿ"</string> + <string name="whichHomeApplication" msgid="4307587691506919691">"ಮುಖಪುಟ ಅಪ್ಲಿಕೇಶನ್ ಆಯ್ಕೆಮಾಡಿ"</string> <string name="whichHomeApplicationNamed" msgid="4493438593214760979">"ಮುಖಪುಟ ಎಂಬಂತೆ %1$s ಅನ್ನು ಬಳಸಿ"</string> <string name="whichHomeApplicationLabel" msgid="809529747002918649">"ಚಿತ್ರ ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿ"</string> <string name="whichImageCaptureApplication" msgid="3680261417470652882">"ಇದರ ಜೊತೆಗೆ ಚಿತ್ರ ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿ"</string> @@ -1224,10 +1224,10 @@ <string name="ext_media_badremoval_notification_message" msgid="380176703346946313">"ಡೇಟಾ ನಷ್ಟವನ್ನು ತಪ್ಪಿಸಲು ತೆಗೆದುಹಾಕುವುದಕ್ಕೂ ಮುನ್ನ <xliff:g id="NAME">%s</xliff:g> ಅಳವಡಿಕೆಯನ್ನು ತೆಗೆದುಹಾಕಿ"</string> <string name="ext_media_nomedia_notification_title" msgid="1704840188641749091">"<xliff:g id="NAME">%s</xliff:g> ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string> <string name="ext_media_nomedia_notification_message" msgid="6471542972147056586">"<xliff:g id="NAME">%s</xliff:g> ತೆಗೆದುಹಾಕಲಾಗಿದೆ; ಹೊಸದನ್ನು ಸೇರಿಸಿ"</string> - <string name="ext_media_unmounting_notification_title" msgid="640674168454809372">"<xliff:g id="NAME">%s</xliff:g> ಇನ್ನೂ ಎಜೆಕ್ಟ್ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string> + <string name="ext_media_unmounting_notification_title" msgid="640674168454809372">"<xliff:g id="NAME">%s</xliff:g> ಇನ್ನೂ ಇಜೆಕ್ಟ್ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string> <string name="ext_media_unmounting_notification_message" msgid="4182843895023357756">"ತೆಗೆದುಹಾಕಬೇಡಿ"</string> <string name="ext_media_init_action" msgid="7952885510091978278">"ಹೊಂದಿಸು"</string> - <string name="ext_media_unmount_action" msgid="1121883233103278199">"ಎಜೆಕ್ಟ್"</string> + <string name="ext_media_unmount_action" msgid="1121883233103278199">"ಇಜೆಕ್ಟ್"</string> <string name="ext_media_browse_action" msgid="8322172381028546087">"ಎಕ್ಸ್ಪ್ಲೋರ್"</string> <string name="ext_media_missing_title" msgid="620980315821543904">"<xliff:g id="NAME">%s</xliff:g> ಕಾಣೆಯಾಗಿದೆ"</string> <string name="ext_media_missing_message" msgid="5761133583368750174">"ಈ ಸಾಧನವನ್ನು ಮರುಸೇರಿಸಿ"</string> @@ -1238,14 +1238,14 @@ <string name="ext_media_move_failure_title" msgid="7613189040358789908">"ಡೇಟಾ ಸರಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string> <string name="ext_media_move_failure_message" msgid="1978096440816403360">"ಮೂಲ ಸ್ಥಳದಲ್ಲಿ ಡೇಟಾ ಉಳಿದಿದೆ"</string> <string name="ext_media_status_removed" msgid="6576172423185918739">"ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string> - <string name="ext_media_status_unmounted" msgid="2551560878416417752">"ಎಜೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string> + <string name="ext_media_status_unmounted" msgid="2551560878416417752">"ಇಜೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string> <string name="ext_media_status_checking" msgid="6193921557423194949">"ಪರಿಶೀಲಿಸಲಾಗುತ್ತಿದೆ..."</string> <string name="ext_media_status_mounted" msgid="7253821726503179202">"ಸಿದ್ಧವಾಗಿದೆ"</string> <string name="ext_media_status_mounted_ro" msgid="8020978752406021015">"ಓದಲು ಮಾತ್ರ"</string> <string name="ext_media_status_bad_removal" msgid="8395398567890329422">"ಅಪಾಯಕರವಾಗಿ ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string> <string name="ext_media_status_unmountable" msgid="805594039236667894">"ದೋಷಪೂರಿತವಾಗಿದೆ"</string> <string name="ext_media_status_unsupported" msgid="4691436711745681828">"ಬೆಂಬಲಿತವಾಗಿಲ್ಲ"</string> - <string name="ext_media_status_ejecting" msgid="5463887263101234174">"ಎಜೆಕ್ಟ್ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string> + <string name="ext_media_status_ejecting" msgid="5463887263101234174">"ಇಜೆಕ್ಟ್ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string> <string name="ext_media_status_formatting" msgid="1085079556538644861">"ಸ್ವರೂಪಗೊಳಿಸುವಿಕೆ..."</string> <string name="ext_media_status_missing" msgid="5638633895221670766">"ಸೇರಿಸಲಾಗಿಲ್ಲ"</string> <string name="activity_list_empty" msgid="1675388330786841066">"ಯಾವುದೇ ಹೊಂದಾಣಿಕೆಯ ಚಟುವಟಿಕೆಗಳು ಕಂಡುಬಂದಿಲ್ಲ."</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> ಗೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ. ನೆಟ್ವರ್ಕ್ ನಿರ್ವಹಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"ಯಾವಾಗಲೂ-ಆನ್ VPN ಸಂಪರ್ಕಗೊಳ್ಳುತ್ತಿದೆ…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"ಯಾವಾಗಲೂ-ಆನ್ VPN ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"ಯಾವಾಗಲೂ-ಆನ್ VPN ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"ಯಾವಾಗಲೂ ಆನ್ ಆಗಿರುವ VPN ನಿಂದ ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"ಯಾವಾಗಲೂ-ಆನ್ VPN ದೋಷ"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"ಹೊಂದಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"ನೆಟ್ವರ್ಕ್ ಅಥವಾ VPN ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಬದಲಾಯಿಸಿ"</string> <string name="upload_file" msgid="2897957172366730416">"ಫೈಲ್ ಆಯ್ಕೆಮಾಡು"</string> <string name="no_file_chosen" msgid="6363648562170759465">"ಯಾವುದೇ ಫೈಲ್ ಆಯ್ಕೆ ಮಾಡಿಲ್ಲ"</string> <string name="reset" msgid="2448168080964209908">"ಮರುಹೊಂದಿಸು"</string> @@ -1462,11 +1462,11 @@ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"ಪಿನ್ ಕೋಡ್ಗಳು ಹೊಂದಾಣಿಕೆಯಾಗುತ್ತಿಲ್ಲ"</string> <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"ಹಲವಾರು ಪ್ಯಾಟರ್ನ್ ಪ್ರಯತ್ನಗಳು"</string> <string name="kg_login_instructions" msgid="1100551261265506448">"ಅನ್ಲಾಕ್ ಮಾಡಲು, ನಿಮ್ಮ Google ಖಾತೆ ಬಳಸಿಕೊಂಡು ಸೈನ್ ಇನ್ ಮಾಡಿ."</string> - <string name="kg_login_username_hint" msgid="5718534272070920364">"ಬಳಕೆದಾರಹೆಸರು (ಇಮೇಲ್)"</string> + <string name="kg_login_username_hint" msgid="5718534272070920364">"ಬಳಕೆದಾರರಹೆಸರು (ಇಮೇಲ್)"</string> <string name="kg_login_password_hint" msgid="9057289103827298549">"ಪಾಸ್ವರ್ಡ್"</string> <string name="kg_login_submit_button" msgid="5355904582674054702">"ಸೈನ್ ಇನ್ ಮಾಡಿ"</string> - <string name="kg_login_invalid_input" msgid="5754664119319872197">"ಅಮಾನ್ಯ ಬಳಕೆದಾರಹೆಸರು ಅಥವಾ ಪಾಸ್ವರ್ಡ್."</string> - <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"ನಿಮ್ಮ ಬಳಕೆದಾರಹೆಸರು ಅಥವಾ ಪಾಸ್ವರ್ಡ್ ಮರೆತಿರುವಿರಾ?\n"<b>"google.com/accounts/recovery"</b>" ಗೆ ಭೇಟಿ ನೀಡಿ."</string> + <string name="kg_login_invalid_input" msgid="5754664119319872197">"ಅಮಾನ್ಯ ಬಳಕೆದಾರರಹೆಸರು ಅಥವಾ ಪಾಸ್ವರ್ಡ್."</string> + <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"ನಿಮ್ಮ ಬಳಕೆದಾರರಹೆಸರು ಅಥವಾ ಪಾಸ್ವರ್ಡ್ ಮರೆತಿರುವಿರಾ?\n"<b>"google.com/accounts/recovery"</b>" ಗೆ ಭೇಟಿ ನೀಡಿ."</string> <string name="kg_login_checking_password" msgid="1052685197710252395">"ಖಾತೆಯನ್ನು ಪರಿಶೀಲಿಸಲಾಗುತ್ತಿದೆ…"</string> <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"ನಿಮ್ಮ ಪಿನ್ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಟೈಪ್ ಮಾಡಿರುವಿರಿ. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string> <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"ನಿಮ್ಮ ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಟೈಪ್ ಮಾಡಿರುವಿರಿ. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string> @@ -1581,7 +1581,7 @@ <string name="mediasize_japanese_kahu" msgid="6872696027560065173">"Kahu"</string> <string name="mediasize_japanese_kaku2" msgid="2359077233775455405">"Kaku2"</string> <string name="mediasize_japanese_you4" msgid="2091777168747058008">"You4"</string> - <string name="mediasize_unknown_portrait" msgid="3088043641616409762">"ಅಪರಿಚಿತ ಪೋಟ್ರೇಟ್"</string> + <string name="mediasize_unknown_portrait" msgid="3088043641616409762">"ಅಪರಿಚಿತ ಪೋರ್ಟ್ರೇಟ್"</string> <string name="mediasize_unknown_landscape" msgid="4876995327029361552">"ಅಪರಿಚಿತ ಲ್ಯಾಂಡ್ಸ್ಕೇಪ್"</string> <string name="write_fail_reason_cancelled" msgid="7091258378121627624">"ರದ್ದುಮಾಡಲಾಗಿದೆ"</string> <string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"ವಿಷಯವನ್ನು ಬರೆಯುವಲ್ಲಿ ದೋಷ ಎದುರಾಗಿದೆ"</string> @@ -1625,7 +1625,7 @@ <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ಅನ್ಪಿನ್ ಮಾಡಲು ಅನ್ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಕೇಳಿ"</string> <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ಅನ್ಪಿನ್ ಮಾಡಲು ಪಾಸ್ವರ್ಡ್ ಕೇಳು"</string> <string name="package_installed_device_owner" msgid="6875717669960212648">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ಸ್ಥಾಪಿಸಿದ್ದಾರೆ"</string> - <string name="package_updated_device_owner" msgid="1847154566357862089">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ಅಪ್ಡೇಟ್ ಮಾಡಿದ್ದಾರೆ"</string> + <string name="package_updated_device_owner" msgid="1847154566357862089">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರಿಂದ ಅಪ್ಡೇಟ್ ಮಾಡಲ್ಪಟ್ಟಿದೆ"</string> <string name="package_deleted_device_owner" msgid="2307122077550236438">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ಅಳಿಸಿದ್ದಾರೆ"</string> <string name="battery_saver_description" msgid="1960431123816253034">"ಬ್ಯಾಟರಿಯ ಬಾಳಿಕೆಯನ್ನು ಸುಧಾರಿಸುವ ನಿಟ್ಟಿನಲ್ಲಿ, ಬ್ಯಾಟರಿ ಉಳಿಕೆಯು ನಿಮ್ಮ ಸಾಧನದ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಕಡಿಮೆ ಮಾಡುತ್ತದೆ ಮತ್ತು ವೈಬ್ರೇಷನ್, ಸ್ಥಳ ಸೇವೆಗಳು ಹಾಗೂ ಹೆಚ್ಚಿನ ಹಿನ್ನೆಲೆ ಡೇಟಾವನ್ನು ಮಿತಿಗೊಳಿಸುತ್ತದೆ. ಸಿಂಕ್ ಮಾಡುವಿಕೆಯನ್ನು ಅವಲಂಬಿಸಿರುವ ಇಮೇಲ್, ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆ ಮತ್ತು ಇತರ ಅಪ್ಲಿಕೇಶನ್ಗಳು ನೀವು ತೆರೆಯದ ಹೊರತು ಅಪ್ಡೇಟ್ ಆಗುವುದಿಲ್ಲ.\n\nನಿಮ್ಮ ಸಾಧನವು ಚಾರ್ಜ್ ಆಗುತ್ತಿರುವಾಗ ಬ್ಯಾಟರಿ ಉಳಿಕೆಯು ಆಫ್ ಆಗುತ್ತದೆ."</string> <string name="data_saver_description" msgid="6015391409098303235">"ಡೇಟಾ ಬಳಕೆ ಕಡಿಮೆ ಮಾಡುವ ನಿಟ್ಟಿನಲ್ಲಿ, ಡೇಟಾ ಸೇವರ್ ಕೆಲವು ಅಪ್ಲಿಕೇಶನ್ಗಳು ಹಿನ್ನೆಲೆಯಲ್ಲಿ ಡೇಟಾ ಕಳುಹಿಸುವುದನ್ನು ಅಥವಾ ಸ್ವೀಕರಿಸುವುದನ್ನು ತಡೆಯುತ್ತದೆ. ನೀವು ಪ್ರಸ್ತುತ ಬಳಸುತ್ತಿರುವ ಅಪ್ಲಿಕೇಶನ್ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಬಹುದು ಆದರೆ ಪದೇ ಪದೇ ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ. ಇದರರ್ಥ, ಉದಾಹರಣೆಗೆ, ನೀವು ಅವುಗಳನ್ನು ಟ್ಯಾಪ್ ಮಾಡುವವರೆಗೆ ಆ ಚಿತ್ರಗಳು ಕಾಣಿಸಿಕೊಳ್ಳುವುದಿಲ್ಲ."</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 5129433837f4..1ecfd043be07 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"알림"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"소매 데모"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB 연결"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"백그라운드에서 실행 중인 앱"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱이 백그라운드에서 실행 중"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g>개의 앱이 백그라운드에서 실행 중"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"배터리를 소모하는 앱"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 배터리 사용 중"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"앱 <xliff:g id="NUMBER">%1$d</xliff:g>개에서 배터리 사용 중"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"탭하여 배터리 및 데이터 사용량 확인"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"안전 모드"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g>에 연결되어 있습니다. 네트워크를 관리하려면 누르세요."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"연결 유지 VPN에 연결하는 중…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"연결 유지 VPN에 연결됨"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"연결 유지 VPN 연결 해제됨"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"연결 유지 VPN 연결이 해제됨"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"연결 유지 VPN 오류"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"탭하여 설정"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"네트워크 또는 VPN 설정 변경"</string> <string name="upload_file" msgid="2897957172366730416">"파일 선택"</string> <string name="no_file_chosen" msgid="6363648562170759465">"파일을 선택하지 않았습니다."</string> <string name="reset" msgid="2448168080964209908">"초기화"</string> @@ -1603,7 +1603,7 @@ <item quantity="one">1초 후에 다시 시도하세요.</item> </plurals> <string name="restr_pin_try_later" msgid="973144472490532377">"나중에 다시 시도"</string> - <string name="immersive_cling_title" msgid="8394201622932303336">"전체 화면 보기"</string> + <string name="immersive_cling_title" msgid="8394201622932303336">"전체 화면 보기 중"</string> <string name="immersive_cling_description" msgid="3482371193207536040">"종료하려면 위에서 아래로 스와이프합니다."</string> <string name="immersive_cling_positive" msgid="5016839404568297683">"확인"</string> <string name="done_label" msgid="2093726099505892398">"완료"</string> diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml index ae2eb34618b9..0063809b8a67 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Эскертүүлөр"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Чекене соода дүкөнү үчүн демо режим"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB аркылуу туташуу"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Фондо иштеп жаткан колдонмолор"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу фондо иштеп жатат"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> колдонмо фондо иштөөдө"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Колдонмолор батареяңызды коротууда"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу батареяны пайдаланып жатат"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> колдонмо батареяны пайдаланып жатат"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Батареянын кубаты жана трафиктин көлөмү жөнүндө билүү үчүн таптап коюңуз"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Коопсуз режим"</string> @@ -1073,18 +1073,18 @@ <string name="dump_heap_text" msgid="4809417337240334941">"<xliff:g id="PROC">%1$s</xliff:g> процесси өзүнүн <xliff:g id="SIZE">%2$s</xliff:g> процесс чегинен ашып кетти. Үймө дамп сиз үчүн иштеп чыгуучу менен бөлүшүүгө даяр. Абайлаңыз: бул үймө дампта колдонмонун уруксаты бар жеке маалыматыңыз камтылышы мүмкүн."</string> <string name="sendText" msgid="5209874571959469142">"Текст үчүн аракет тандаңыз"</string> <string name="volume_ringtone" msgid="6885421406845734650">"Коңгуроонун үн көлөмү"</string> - <string name="volume_music" msgid="5421651157138628171">"Медианын үн көлөмү"</string> + <string name="volume_music" msgid="5421651157138628171">"Мультимедианын үнү"</string> <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"Bluetooth аркылуу ойнотулууда"</string> <string name="volume_music_hint_silent_ringtone_selected" msgid="8310739960973156272">"Үнсүз рингтон орнотулду"</string> <string name="volume_call" msgid="3941680041282788711">"Чалуудагы үн көлөмү"</string> <string name="volume_bluetooth_call" msgid="2002891926351151534">"Bluetooth чалуудагы үн көлөмү"</string> - <string name="volume_alarm" msgid="1985191616042689100">"Ойготкучтун үн көлөмү"</string> + <string name="volume_alarm" msgid="1985191616042689100">"Ойготкучтун үнү"</string> <string name="volume_notification" msgid="2422265656744276715">"Эскертме үн көлөмү"</string> <string name="volume_unknown" msgid="1400219669770445902">"Үн көлөмү"</string> <string name="volume_icon_description_bluetooth" msgid="6538894177255964340">"Bluetooth үнүнүн деңгээли"</string> <string name="volume_icon_description_ringer" msgid="3326003847006162496">"Коңгуроо үнүнүн деңгээли"</string> <string name="volume_icon_description_incall" msgid="8890073218154543397">"Чалуунун үн деңгээли"</string> - <string name="volume_icon_description_media" msgid="4217311719665194215">"Медиа үнүнүн деңгээли"</string> + <string name="volume_icon_description_media" msgid="4217311719665194215">"Мультимедианын үнү"</string> <string name="volume_icon_description_notification" msgid="7044986546477282274">"Эскертме үнүнүн деңгээли"</string> <string name="ringtone_default" msgid="3789758980357696936">"Демейки шыңгыр"</string> <string name="ringtone_default_with_actual" msgid="1767304850491060581">"Демейки шыңгыр (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string> @@ -1295,9 +1295,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> сеансына туташуу ишке ашты. Желенин параметрлерин өзгөртүү үчүн бул жерди басыңыз."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Дайым иштеген VPN туташууда…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Дайым иштеген VPN туташтырылды"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Дайым иштеген VPN ажыратылды"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Ар дайым иштеген VPN\'ден ажыратуу"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Дайым иштеген VPN\'де ката кетти"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Жөндөө үчүн таптаңыз"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Тармакты же VPN жөндөөлөрүн өзгөртүү"</string> <string name="upload_file" msgid="2897957172366730416">"Файл тандоо"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Эч файл тандалган жок"</string> <string name="reset" msgid="2448168080964209908">"Баштапкы абалга келтирүү"</string> @@ -1605,7 +1605,7 @@ </plurals> <string name="restr_pin_try_later" msgid="973144472490532377">"Кийинчерээк кайталаңыз"</string> <string name="immersive_cling_title" msgid="8394201622932303336">"Толук экран режими"</string> - <string name="immersive_cling_description" msgid="3482371193207536040">"Чыгуу үчүн, жогурдан төмөн сүрүңүз."</string> + <string name="immersive_cling_description" msgid="3482371193207536040">"Чыгуу үчүн экранды ылдый сүрүп коюңуз."</string> <string name="immersive_cling_positive" msgid="5016839404568297683">"Түшүндүм"</string> <string name="done_label" msgid="2093726099505892398">"Даяр"</string> <string name="hour_picker_description" msgid="6698199186859736512">"Саат жебеси"</string> diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml index e13bb3f2b059..96eaf8ccf1cb 100644 --- a/core/res/res/values-lo/strings.xml +++ b/core/res/res/values-lo/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"ການເຕືອນ"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"ເດໂມສຳລັບຮ້ານຂາຍ"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"ການເຊື່ອມຕໍ່ USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"ແອັບທີ່ກຳລັງເຮັດວຽກໃນພື້ນຫຼັງ"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງເຮັດວຽກໃນພື້ນຫຼັງ"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"ແອັບ <xliff:g id="NUMBER">%1$d</xliff:g> ແອັບກຳລັງເຮັດວຽກໃນພື້ນຫຼັງ"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"ແອັບທີ່ກຳລັງໃຊ້ແບັດເຕີຣີ"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງໃຊ້ແບັດເຕີຣີຢູ່"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> ແອັບກຳລັງໃຊ້ແບັດເຕີຣີຢູ່"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"ແຕະເພື່ອເບິ່ງລາຍລະອຽດການນຳໃຊ້ແບັດເຕີຣີ ແລະ ອິນເຕີເນັດ"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"ເຊື່ອມຕໍ່ກັບ <xliff:g id="SESSION">%s</xliff:g> ແລ້ວ. ແຕະເພື່ອຈັດການເຄືອຂ່າຍ."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"ກຳລັງເຊື່ອມຕໍ່ Always-on VPN…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"ເຊື່ອມຕໍ່ VPN ແບບເປີດຕະຫຼອດເວລາແລ້ວ"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"ຕັດການເຊື່ອມຕໍ່ VPN ແບບເປີດໃຊ້ຕະຫຼອດເວລາແລ້ວ"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"ຕັດການເຊື່ອມຕໍ່ຈາກ VPN ແບບເປີດຕະຫຼອດແລ້ວ"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"VPN ແບບເປີດຕະຫຼອດເກີດຄວາມຜິດພາດ"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"ແຕະເພື່ອຕັ້ງຄ່າ"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"ປ່ຽນການຕັ້ງຄ່າເຄືອຂ່າຍ ຫຼື ການຕັ້ງຄ່າ VPN"</string> <string name="upload_file" msgid="2897957172366730416">"ເລືອກໄຟລ໌"</string> <string name="no_file_chosen" msgid="6363648562170759465">"ບໍ່ໄດ້ເລືອກໄຟລ໌ເທື່ອ"</string> <string name="reset" msgid="2448168080964209908">"ຣີເຊັດ"</string> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index bc8a01ac825d..fa4e13bc3736 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -254,9 +254,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Įspėjimai"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demonstracinė versija mažmenininkams"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB jungtis"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Programos, veikiančios fone"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ veikia fone"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"Programos (<xliff:g id="NUMBER">%1$d</xliff:g>) veikia fone"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Programos, naudojančios akumuliatoriaus energiją"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ naudoja akumuliatoriaus energiją"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"Programų, naudojančių akumuliatoriaus energiją: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Palieskite ir sužinokite išsamios informacijos apie akumuliatoriaus bei duomenų naudojimą"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Saugos režimas"</string> @@ -1338,9 +1338,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Prisijungta prie <xliff:g id="SESSION">%s</xliff:g>. Jei norite valdyti tinklą, palieskite."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Prisijungiama prie visada įjungto VPN…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Prisijungta prie visada įjungto VPN"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Visada įjungtas VPN atjungtas"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Atsijungta nuo visada įjungto VPN"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Visada įjungto VPN klaida"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Palieskite, kad nustatytumėte"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Keiskite tinklo arba VPN nustatymus"</string> <string name="upload_file" msgid="2897957172366730416">"Pasirinkti failą"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Nepasirinktas joks failas"</string> <string name="reset" msgid="2448168080964209908">"Atstatyti"</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index 9a8a9d8221f7..58757ee93a69 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -251,9 +251,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Brīdinājumi"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demonstrācijas versija veikaliem"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB savienojums"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Lietotnes, kas darbojas fonā"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> darbojas fonā"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> lietotnes darbojas fonā"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Lietotnes, kas patērē akumulatora jaudu"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> izmanto akumulatoru"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> lietotne(-es) izmanto akumulatoru"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Pieskarieties, lai skatītu detalizētu informāciju par akumulatora un datu lietojumu"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Drošais režīms"</string> @@ -1316,9 +1316,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Ir izveidots savienojums ar: <xliff:g id="SESSION">%s</xliff:g>. Pieskarieties, lai pārvaldītu tīklu."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Notiek savienojuma izveide ar vienmēr ieslēgtu VPN…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Izveidots savienojums ar vienmēr ieslēgtu VPN."</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Vienmēr ieslēgts VPN ir atvienots"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Pārtraukts savienojums ar vienmēr ieslēgtu VPN"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Kļūda saistībā ar vienmēr ieslēgtu VPN"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Pieskarieties, lai iestatītu."</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Mainiet tīkla vai VPN iestatījumus"</string> <string name="upload_file" msgid="2897957172366730416">"Izvēlēties failu"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Neviens fails nav izvēlēts"</string> <string name="reset" msgid="2448168080964209908">"Atiestatīt"</string> diff --git a/core/res/res/values-mcc302-mnc370-gu/strings.xml b/core/res/res/values-mcc302-mnc370-gu/strings.xml index b93949e190c7..d869bcba5bdc 100644 --- a/core/res/res/values-mcc302-mnc370-gu/strings.xml +++ b/core/res/res/values-mcc302-mnc370-gu/strings.xml @@ -21,6 +21,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string-array name="wfcSpnFormats"> <item msgid="5022384999749536798">"%s"</item> - <item msgid="8117276330682171665">"%s Wi-Fi"</item> + <item msgid="8117276330682171665">"%s વાઇ-ફાઇ"</item> </string-array> </resources> diff --git a/core/res/res/values-mcc302-mnc370-pa/strings.xml b/core/res/res/values-mcc302-mnc370-pa/strings.xml index b93949e190c7..5d3f7aed6181 100644 --- a/core/res/res/values-mcc302-mnc370-pa/strings.xml +++ b/core/res/res/values-mcc302-mnc370-pa/strings.xml @@ -21,6 +21,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string-array name="wfcSpnFormats"> <item msgid="5022384999749536798">"%s"</item> - <item msgid="8117276330682171665">"%s Wi-Fi"</item> + <item msgid="8117276330682171665">"%s ਵਾਈ-ਫਾਈ"</item> </string-array> </resources> diff --git a/core/res/res/values-mcc302-mnc720-gu/strings.xml b/core/res/res/values-mcc302-mnc720-gu/strings.xml index 9b2336d8006d..a64474c91497 100644 --- a/core/res/res/values-mcc302-mnc720-gu/strings.xml +++ b/core/res/res/values-mcc302-mnc720-gu/strings.xml @@ -21,6 +21,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string-array name="wfcSpnFormats"> <item msgid="2776657861851140021">"%s"</item> - <item msgid="5094669985484060934">"%s Wi-Fi"</item> + <item msgid="5094669985484060934">"%s વાઇ-ફાઇ"</item> </string-array> </resources> diff --git a/core/res/res/values-mcc302-mnc720-pa/strings.xml b/core/res/res/values-mcc302-mnc720-pa/strings.xml index 9b2336d8006d..acf26555cbc8 100644 --- a/core/res/res/values-mcc302-mnc720-pa/strings.xml +++ b/core/res/res/values-mcc302-mnc720-pa/strings.xml @@ -21,6 +21,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string-array name="wfcSpnFormats"> <item msgid="2776657861851140021">"%s"</item> - <item msgid="5094669985484060934">"%s Wi-Fi"</item> + <item msgid="5094669985484060934">"%s ਵਾਈ-ਫਾਈ"</item> </string-array> </resources> diff --git a/core/res/res/values-mcc310-mnc030-af/strings.xml b/core/res/res/values-mcc310-mnc030-af/strings.xml new file mode 100644 index 000000000000..0b666c28ba4f --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-af/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM is nie opgestel nie MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM word nie toegelaat nie MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-am/strings.xml b/core/res/res/values-mcc310-mnc030-am/strings.xml new file mode 100644 index 000000000000..08c5e3294ddb --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-am/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"ሲም አልቀረበም MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"ሲም አይፈቀድም MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-ar/strings.xml b/core/res/res/values-mcc310-mnc030-ar/strings.xml new file mode 100644 index 000000000000..5d6a53d71d91 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-ar/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"لم يتم توفير SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"غير مسموح باستخدام SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-az/strings.xml b/core/res/res/values-mcc310-mnc030-az/strings.xml new file mode 100644 index 000000000000..194d1892336f --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-az/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM MM#2 təmin etmir"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM MM#3 dəstəkləmir"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-b+sr+Latn/strings.xml b/core/res/res/values-mcc310-mnc030-b+sr+Latn/strings.xml new file mode 100644 index 000000000000..d3068939aa24 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-b+sr+Latn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM kartica nije podešena MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM kartica nije dozvoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-be/strings.xml b/core/res/res/values-mcc310-mnc030-be/strings.xml new file mode 100644 index 000000000000..12fef7a40315 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-be/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM-карты няма MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM-карта не дапускаецца MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-bg/strings.xml b/core/res/res/values-mcc310-mnc030-bg/strings.xml new file mode 100644 index 000000000000..a7c014a496c0 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-bg/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM картата не е обезпечена MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM картата не е разрешена MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-bn/strings.xml b/core/res/res/values-mcc310-mnc030-bn/strings.xml new file mode 100644 index 000000000000..f07a3d647093 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-bn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"সিমের জন্য প্রস্তুত নয় MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"সিমের অনুমতি নেই MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-bs/strings.xml b/core/res/res/values-mcc310-mnc030-bs/strings.xml new file mode 100644 index 000000000000..1e6c7db2b069 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-bs/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM kartica nije dodijeljena MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM kartica nije dozvoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-ca/strings.xml b/core/res/res/values-mcc310-mnc030-ca/strings.xml new file mode 100644 index 000000000000..af25f9b192f4 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-ca/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"La SIM no està proporcionada a MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"La SIM no és compatible a MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-cs/strings.xml b/core/res/res/values-mcc310-mnc030-cs/strings.xml new file mode 100644 index 000000000000..ee0f90c247dd --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-cs/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM karta není poskytována (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM karta není povolena (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-da/strings.xml b/core/res/res/values-mcc310-mnc030-da/strings.xml new file mode 100644 index 000000000000..8539f7a8c8ab --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-da/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM-kort leveres ikke MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM-kort er ikke tilladt MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-de/strings.xml b/core/res/res/values-mcc310-mnc030-de/strings.xml new file mode 100644 index 000000000000..ad797b53a64c --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-de/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM-Karte nicht eingerichtet MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM-Karte nicht zulässig MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-el/strings.xml b/core/res/res/values-mcc310-mnc030-el/strings.xml new file mode 100644 index 000000000000..62aa97f5f852 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-el/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"Δεν παρέχεται κάρτα SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"Η κάρτα SIM δεν επιτρέπεται MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-en-rAU/strings.xml b/core/res/res/values-mcc310-mnc030-en-rAU/strings.xml new file mode 100644 index 000000000000..1a50ac6c1382 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-en-rAU/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-en-rCA/strings.xml b/core/res/res/values-mcc310-mnc030-en-rCA/strings.xml new file mode 100644 index 000000000000..1a50ac6c1382 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-en-rCA/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-en-rGB/strings.xml b/core/res/res/values-mcc310-mnc030-en-rGB/strings.xml new file mode 100644 index 000000000000..1a50ac6c1382 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-en-rGB/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-en-rIN/strings.xml b/core/res/res/values-mcc310-mnc030-en-rIN/strings.xml new file mode 100644 index 000000000000..1a50ac6c1382 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-en-rIN/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-en-rXC/strings.xml b/core/res/res/values-mcc310-mnc030-en-rXC/strings.xml new file mode 100644 index 000000000000..5eb9cba69893 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-en-rXC/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-es-rUS/strings.xml b/core/res/res/values-mcc310-mnc030-es-rUS/strings.xml new file mode 100644 index 000000000000..87226ac52e46 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-es-rUS/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM no provista MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM no permitida MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-es/strings.xml b/core/res/res/values-mcc310-mnc030-es/strings.xml new file mode 100644 index 000000000000..c13f5f8eee1c --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-es/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM no proporcionada (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM no admitida (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-et/strings.xml b/core/res/res/values-mcc310-mnc030-et/strings.xml new file mode 100644 index 000000000000..07229ab97af2 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-et/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM-kaart on ette valmistamata MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM-kaart pole lubatud MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-eu/strings.xml b/core/res/res/values-mcc310-mnc030-eu/strings.xml new file mode 100644 index 000000000000..024fbab5757f --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-eu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"Ez dago SIM txartelik MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"Ez da onartzen SIM txartela MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-fa/strings.xml b/core/res/res/values-mcc310-mnc030-fa/strings.xml new file mode 100644 index 000000000000..e75403279b55 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-fa/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"سیمکارت مجوز لازم را ندارد MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"سیمکارت مجاز نیست MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-fi/strings.xml b/core/res/res/values-mcc310-mnc030-fi/strings.xml new file mode 100644 index 000000000000..3b9c2ab0876d --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-fi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM-kortti ei käyttäjien hallinnassa MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM-kortti estetty MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-fr-rCA/strings.xml b/core/res/res/values-mcc310-mnc030-fr-rCA/strings.xml new file mode 100644 index 000000000000..31644b7f801a --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-fr-rCA/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"Carte SIM non configurée, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"Carte SIM non autorisée, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-fr/strings.xml b/core/res/res/values-mcc310-mnc030-fr/strings.xml new file mode 100644 index 000000000000..9c690e73819b --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-fr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"Carte SIM non provisionnée MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"Carte SIM non autorisée MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-gl/strings.xml b/core/res/res/values-mcc310-mnc030-gl/strings.xml new file mode 100644 index 000000000000..59be216ab47e --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-gl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"Non se introduciu ningunha tarxeta SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"Non se admite a tarxeta SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-gu/strings.xml b/core/res/res/values-mcc310-mnc030-gu/strings.xml new file mode 100644 index 000000000000..ac57a85c8121 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-gu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIMને MM#2ની જોગવાઈ નથી"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIMને MM#3 કરવાની મંજૂરી નથી"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-hi/strings.xml b/core/res/res/values-mcc310-mnc030-hi/strings.xml new file mode 100644 index 000000000000..244d17527d64 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-hi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM काम नहीं कर रहा है MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM की अनुमति नहीं है MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-hr/strings.xml b/core/res/res/values-mcc310-mnc030-hr/strings.xml new file mode 100644 index 000000000000..a37043cbbd98 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-hr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"Ne pruža se usluga za SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM nije dopušten MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-hu/strings.xml b/core/res/res/values-mcc310-mnc030-hu/strings.xml new file mode 100644 index 000000000000..b26b2b2e3f33 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-hu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"Nem engedélyezett SIM-kártya (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"A SIM-kártya nem engedélyezett (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-hy/strings.xml b/core/res/res/values-mcc310-mnc030-hy/strings.xml new file mode 100644 index 000000000000..0d052f31770c --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-hy/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM քարտը նախապատրաստված չէ (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM քարտի օգտագործումն արգելված է (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-in/strings.xml b/core/res/res/values-mcc310-mnc030-in/strings.xml new file mode 100644 index 000000000000..f8f661362703 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-in/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM tidak di-provisioning MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM tidak diizinkan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-is/strings.xml b/core/res/res/values-mcc310-mnc030-is/strings.xml new file mode 100644 index 000000000000..1033965f2ef3 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-is/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM-korti ekki úthlutað MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM-kort ekki leyft MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-it/strings.xml b/core/res/res/values-mcc310-mnc030-it/strings.xml new file mode 100644 index 000000000000..fb74a978722e --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-it/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"Scheda SIM non predisposta MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"Scheda SIM non consentita MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-iw/strings.xml b/core/res/res/values-mcc310-mnc030-iw/strings.xml new file mode 100644 index 000000000000..50bd517003d4 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-iw/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"כרטיס ה-SIM לא הופעל MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"כרטיס ה-SIM לא מורשה לשימוש ברשת הסלולרית MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-ja/strings.xml b/core/res/res/values-mcc310-mnc030-ja/strings.xml new file mode 100644 index 000000000000..78cd78cbba5b --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-ja/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM には対応していません(MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM は許可されていません(MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-ka/strings.xml b/core/res/res/values-mcc310-mnc030-ka/strings.xml new file mode 100644 index 000000000000..04d6a7dcd78e --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-ka/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM ბარათი უზრუნველყოფილი არ არის (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM ბარათი დაუშვებელია (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-kk/strings.xml b/core/res/res/values-mcc310-mnc030-kk/strings.xml new file mode 100644 index 000000000000..aad588c271e8 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-kk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM картасы қарастырылмаған MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM картасына рұқсат етілмеген MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-km/strings.xml b/core/res/res/values-mcc310-mnc030-km/strings.xml new file mode 100644 index 000000000000..bd999274664f --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-km/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"ស៊ីមកាតមិនត្រូវបានផ្ដល់ជូនទេ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"មិនអនុញ្ញាតចំពោះស៊ីមកាតទេ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-kn/strings.xml b/core/res/res/values-mcc310-mnc030-kn/strings.xml new file mode 100644 index 000000000000..39e9b0705838 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-kn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"MM#2 ಗೆ ಸಿಮ್ ಸಿದ್ಧವಾಗಿಲ್ಲ"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"ಸಿಮ್ MM#3 ಅನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-ko/strings.xml b/core/res/res/values-mcc310-mnc030-ko/strings.xml new file mode 100644 index 000000000000..67e45b03874c --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-ko/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM이 프로비저닝되지 않음 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM이 허용되지 않음 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-ky/strings.xml b/core/res/res/values-mcc310-mnc030-ky/strings.xml new file mode 100644 index 000000000000..02ac153694b6 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-ky/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM карта таанылган жок (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM картаны колдонууга тыюу салынган (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-lo/strings.xml b/core/res/res/values-mcc310-mnc030-lo/strings.xml new file mode 100644 index 000000000000..b41bf9163709 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-lo/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM ບໍ່ໄດ້ເປີດໃຊ້ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM ບໍ່ອະນຸຍາດ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-lt/strings.xml b/core/res/res/values-mcc310-mnc030-lt/strings.xml new file mode 100644 index 000000000000..59c66be56169 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-lt/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM kortelė neteikiama (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM kortelė neleidžiama (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-lv/strings.xml b/core/res/res/values-mcc310-mnc030-lv/strings.xml new file mode 100644 index 000000000000..685c9b825d5b --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-lv/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM karte netiek nodrošināta: MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM karti nav atļauts izmantot: MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-mk/strings.xml b/core/res/res/values-mcc310-mnc030-mk/strings.xml new file mode 100644 index 000000000000..ce24e25f12ca --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-mk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"Не е обезбедена SIM-картичка, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"Не е дозволена SIM-картичка, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-ml/strings.xml b/core/res/res/values-mcc310-mnc030-ml/strings.xml new file mode 100644 index 000000000000..9adfd9c0892a --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-ml/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"സിം MM#2 പ്രൊവിഷൻ ചെയ്തിട്ടില്ല"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"സിം MM#3 അനുവദിച്ചിട്ടില്ല"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-mn/strings.xml b/core/res/res/values-mcc310-mnc030-mn/strings.xml new file mode 100644 index 000000000000..6ff2d5e33780 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-mn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM-г идэвхжүүлээгүй байна MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM-г зөвшөөрөөгүй байна MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-mr/strings.xml b/core/res/res/values-mcc310-mnc030-mr/strings.xml new file mode 100644 index 000000000000..afc40a134c65 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-mr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM ने MM#2 ची तरतूद केलेली नाही"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM ने MM#3 ला परवानगी दिली नाही"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-ms/strings.xml b/core/res/res/values-mcc310-mnc030-ms/strings.xml new file mode 100644 index 000000000000..9a54b04bec27 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-ms/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM tidak diperuntukkan MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM tidak dibenarkan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-my/strings.xml b/core/res/res/values-mcc310-mnc030-my/strings.xml new file mode 100644 index 000000000000..79a0791b25f7 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-my/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"ဆင်းမ်ကို ထောက်ပံ့မထားပါ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"ဆင်းမ်ကို ခွင့်မပြုပါ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-nb/strings.xml b/core/res/res/values-mcc310-mnc030-nb/strings.xml new file mode 100644 index 000000000000..7c06dba3beaf --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-nb/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM-kortet er ikke klargjort, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM-kortet er ikke tillatt, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-ne/strings.xml b/core/res/res/values-mcc310-mnc030-ne/strings.xml new file mode 100644 index 000000000000..3ef06ab00731 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-ne/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM को प्रावधान छैन MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM लाई अनुमति छैन MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-nl/strings.xml b/core/res/res/values-mcc310-mnc030-nl/strings.xml new file mode 100644 index 000000000000..861385d138fd --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-nl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"Simkaart niet geregistreerd MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"Simkaart niet toegestaan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-pa/strings.xml b/core/res/res/values-mcc310-mnc030-pa/strings.xml new file mode 100644 index 000000000000..ba7b6140f2b5 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-pa/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"ਸਿਮ ਦੀ ਵਿਵਸਥਾ ਨਹੀਂ ਹੈ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"ਸਿਮ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-pl/strings.xml b/core/res/res/values-mcc310-mnc030-pl/strings.xml new file mode 100644 index 000000000000..84ff351f2af4 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-pl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"MM#2 – karta SIM nieobsługiwana"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"MM#3 – niedozwolona karta SIM"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-pt-rBR/strings.xml b/core/res/res/values-mcc310-mnc030-pt-rBR/strings.xml new file mode 100644 index 000000000000..2679f93f30e7 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-pt-rBR/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-pt-rPT/strings.xml b/core/res/res/values-mcc310-mnc030-pt-rPT/strings.xml new file mode 100644 index 000000000000..2679f93f30e7 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-pt-rPT/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-pt/strings.xml b/core/res/res/values-mcc310-mnc030-pt/strings.xml new file mode 100644 index 000000000000..2679f93f30e7 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-pt/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-ro/strings.xml b/core/res/res/values-mcc310-mnc030-ro/strings.xml new file mode 100644 index 000000000000..5bae0c0f9f72 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-ro/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"Cardul SIM nu este activat MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"Cardul SIM nu este permis MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-ru/strings.xml b/core/res/res/values-mcc310-mnc030-ru/strings.xml new file mode 100644 index 000000000000..658badf6670f --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-ru/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM-карта не активирована (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"Использование SIM-карты запрещено (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-si/strings.xml b/core/res/res/values-mcc310-mnc030-si/strings.xml new file mode 100644 index 000000000000..635ffa474d38 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-si/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM MM#2 ප්රතිපාදනය නොකරයි"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM MM#3 ඉඩ නොදේ"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-sk/strings.xml b/core/res/res/values-mcc310-mnc030-sk/strings.xml new file mode 100644 index 000000000000..2a046b651a36 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-sk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM karta nie je k dispozícii – MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM karta je zakázaná – MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-sl/strings.xml b/core/res/res/values-mcc310-mnc030-sl/strings.xml new file mode 100644 index 000000000000..7321e4d41a49 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-sl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"Kartica SIM ni omogočena za uporabo MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"Kartica SIM ni dovoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-sq/strings.xml b/core/res/res/values-mcc310-mnc030-sq/strings.xml new file mode 100644 index 000000000000..e553f01528e2 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-sq/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"Karta SIM nuk është dhënë MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"Karta SIM nuk lejohet MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-sr/strings.xml b/core/res/res/values-mcc310-mnc030-sr/strings.xml new file mode 100644 index 000000000000..945e2fcfc9a0 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-sr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM картица није подешена MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM картица није дозвољена MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-sv/strings.xml b/core/res/res/values-mcc310-mnc030-sv/strings.xml new file mode 100644 index 000000000000..5f0cc4691656 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-sv/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM-kort tillhandahålls inte MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM-kort tillåts inte MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-sw/strings.xml b/core/res/res/values-mcc310-mnc030-sw/strings.xml new file mode 100644 index 000000000000..fbd20767b397 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-sw/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM haitumiki MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM hairuhusiwi MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-ta/strings.xml b/core/res/res/values-mcc310-mnc030-ta/strings.xml new file mode 100644 index 000000000000..6fc3df698311 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-ta/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"சிம் அமைக்கப்படவில்லை MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"சிம் அனுமதிக்கப்படவில்லை MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-te/strings.xml b/core/res/res/values-mcc310-mnc030-te/strings.xml new file mode 100644 index 000000000000..4c617910eed5 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-te/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM MM#2ని సక్రియం చేయలేదు"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM MM#3ని అనుమతించలేదు"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-th/strings.xml b/core/res/res/values-mcc310-mnc030-th/strings.xml new file mode 100644 index 000000000000..9a8ee7453881 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-th/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"ไม่มีการจัดสรรซิม MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"ไม่อนุญาตให้ใช้ซิม MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-tl/strings.xml b/core/res/res/values-mcc310-mnc030-tl/strings.xml new file mode 100644 index 000000000000..6408f4ef93f8 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-tl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"Hindi na-provision ang SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"Hindi pinapahintulutan ang SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-tr/strings.xml b/core/res/res/values-mcc310-mnc030-tr/strings.xml new file mode 100644 index 000000000000..361ee9ca9796 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-tr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM, MM#2\'nin temel hazırlığını yapamadı"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM MM#3\'e izin vermiyor"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-uk/strings.xml b/core/res/res/values-mcc310-mnc030-uk/strings.xml new file mode 100644 index 000000000000..efee94e70b3b --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-uk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM-карту не надано (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM-карта заборонена (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-ur/strings.xml b/core/res/res/values-mcc310-mnc030-ur/strings.xml new file mode 100644 index 000000000000..a0e5fd617820 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-ur/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM فراہم کردہ نہیں ہے MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM کی اجازت نہیں ہے MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-uz/strings.xml b/core/res/res/values-mcc310-mnc030-uz/strings.xml new file mode 100644 index 000000000000..7eb641a7ed04 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-uz/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM karta ishlatish taqiqlangan (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM karta ishlatish taqiqlangan (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-vi/strings.xml b/core/res/res/values-mcc310-mnc030-vi/strings.xml new file mode 100644 index 000000000000..362ee6ab3310 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-vi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"SIM không được cấp phép MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"SIM không được phép MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-zh-rCN/strings.xml b/core/res/res/values-mcc310-mnc030-zh-rCN/strings.xml new file mode 100644 index 000000000000..efa43f570b5e --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-zh-rCN/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"未配置的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"不被允许的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-zh-rHK/strings.xml b/core/res/res/values-mcc310-mnc030-zh-rHK/strings.xml new file mode 100644 index 000000000000..c163544cf979 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-zh-rHK/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"未佈建的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"不支援的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-zh-rTW/strings.xml b/core/res/res/values-mcc310-mnc030-zh-rTW/strings.xml new file mode 100644 index 000000000000..c163544cf979 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-zh-rTW/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"未佈建的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"不支援的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc030-zu/strings.xml b/core/res/res/values-mcc310-mnc030-zu/strings.xml new file mode 100644 index 000000000000..720fa827bdc8 --- /dev/null +++ b/core/res/res/values-mcc310-mnc030-zu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6575159319460304530">"I-SIM ayinikezelwe MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1930079814544869756">"I-SIM ayivunyelwe MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-af/strings.xml b/core/res/res/values-mcc310-mnc170-af/strings.xml new file mode 100644 index 000000000000..4256d3a8d756 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-af/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM is nie opgestel nie MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM word nie toegelaat nie MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-am/strings.xml b/core/res/res/values-mcc310-mnc170-am/strings.xml new file mode 100644 index 000000000000..311d9e1a6f28 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-am/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"ሲም አልቀረበም MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"ሲም አይፈቀድም MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-ar/strings.xml b/core/res/res/values-mcc310-mnc170-ar/strings.xml new file mode 100644 index 000000000000..a80ff2e27b73 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-ar/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"لم يتم توفير SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"غير مسموح باستخدام SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-az/strings.xml b/core/res/res/values-mcc310-mnc170-az/strings.xml new file mode 100644 index 000000000000..a690668496e7 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-az/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM MM#2 təmin etmir"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM MM#3 dəstəkləmir"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-b+sr+Latn/strings.xml b/core/res/res/values-mcc310-mnc170-b+sr+Latn/strings.xml new file mode 100644 index 000000000000..b2da8a7a35b9 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-b+sr+Latn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM kartica nije podešena MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM kartica nije dozvoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-be/strings.xml b/core/res/res/values-mcc310-mnc170-be/strings.xml new file mode 100644 index 000000000000..fb7f5565cd67 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-be/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM-карты няма MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM-карта не дапускаецца MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-bg/strings.xml b/core/res/res/values-mcc310-mnc170-bg/strings.xml new file mode 100644 index 000000000000..1158b3bade7d --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-bg/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM картата не е обезпечена MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM картата не е разрешена MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-bn/strings.xml b/core/res/res/values-mcc310-mnc170-bn/strings.xml new file mode 100644 index 000000000000..4e6d41b17727 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-bn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"সিমের জন্য প্রস্তুত নয় MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"সিমের অনুমতি নেই MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-bs/strings.xml b/core/res/res/values-mcc310-mnc170-bs/strings.xml new file mode 100644 index 000000000000..d3f3e3b1bd56 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-bs/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM kartica nije dodijeljena MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM kartica nije dozvoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-ca/strings.xml b/core/res/res/values-mcc310-mnc170-ca/strings.xml new file mode 100644 index 000000000000..9abeeb7f40a3 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-ca/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"La SIM no està proporcionada a MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"La SIM no és compatible a MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-cs/strings.xml b/core/res/res/values-mcc310-mnc170-cs/strings.xml new file mode 100644 index 000000000000..2d4d2fb0c690 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-cs/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM karta není poskytována (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM karta není povolena (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-da/strings.xml b/core/res/res/values-mcc310-mnc170-da/strings.xml new file mode 100644 index 000000000000..ae2155fa9a7a --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-da/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM-kort leveres ikke MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM-kort er ikke tilladt MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-de/strings.xml b/core/res/res/values-mcc310-mnc170-de/strings.xml new file mode 100644 index 000000000000..f7c5eec3c49f --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-de/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM-Karte nicht eingerichtet MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM-Karte nicht zulässig MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-el/strings.xml b/core/res/res/values-mcc310-mnc170-el/strings.xml new file mode 100644 index 000000000000..68b7008abc17 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-el/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"Δεν παρέχεται κάρτα SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"Η κάρτα SIM δεν επιτρέπεται MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-en-rAU/strings.xml b/core/res/res/values-mcc310-mnc170-en-rAU/strings.xml new file mode 100644 index 000000000000..fd166206c744 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-en-rAU/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-en-rCA/strings.xml b/core/res/res/values-mcc310-mnc170-en-rCA/strings.xml new file mode 100644 index 000000000000..fd166206c744 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-en-rCA/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-en-rGB/strings.xml b/core/res/res/values-mcc310-mnc170-en-rGB/strings.xml new file mode 100644 index 000000000000..fd166206c744 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-en-rGB/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-en-rIN/strings.xml b/core/res/res/values-mcc310-mnc170-en-rIN/strings.xml new file mode 100644 index 000000000000..fd166206c744 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-en-rIN/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-en-rXC/strings.xml b/core/res/res/values-mcc310-mnc170-en-rXC/strings.xml new file mode 100644 index 000000000000..71d087ead2eb --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-en-rXC/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-es-rUS/strings.xml b/core/res/res/values-mcc310-mnc170-es-rUS/strings.xml new file mode 100644 index 000000000000..50d3c12fb19d --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-es-rUS/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM no provista MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM no permitida MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-es/strings.xml b/core/res/res/values-mcc310-mnc170-es/strings.xml new file mode 100644 index 000000000000..7191d04b3c10 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-es/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM no proporcionada (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM no admitida (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-et/strings.xml b/core/res/res/values-mcc310-mnc170-et/strings.xml new file mode 100644 index 000000000000..7159bf94eccb --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-et/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM-kaart on ette valmistamata MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM-kaart pole lubatud MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-eu/strings.xml b/core/res/res/values-mcc310-mnc170-eu/strings.xml new file mode 100644 index 000000000000..797f9883ea91 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-eu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"Ez dago SIM txartelik MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"Ez da onartzen SIM txartela MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-fa/strings.xml b/core/res/res/values-mcc310-mnc170-fa/strings.xml new file mode 100644 index 000000000000..968f952bce76 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-fa/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"سیمکارت مجوز لازم را ندارد MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"سیمکارت مجاز نیست MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-fi/strings.xml b/core/res/res/values-mcc310-mnc170-fi/strings.xml new file mode 100644 index 000000000000..c0523f4517bf --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-fi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM-kortti ei käyttäjien hallinnassa MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM-kortti estetty MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-fr-rCA/strings.xml b/core/res/res/values-mcc310-mnc170-fr-rCA/strings.xml new file mode 100644 index 000000000000..5600fa454c1b --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-fr-rCA/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"Carte SIM non configurée, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"Carte SIM non autorisée, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-fr/strings.xml b/core/res/res/values-mcc310-mnc170-fr/strings.xml new file mode 100644 index 000000000000..73b4f0e397e3 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-fr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"Carte SIM non provisionnée MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"Carte SIM non autorisée MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-gl/strings.xml b/core/res/res/values-mcc310-mnc170-gl/strings.xml new file mode 100644 index 000000000000..fe1321186d91 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-gl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"Non se introduciu ningunha tarxeta SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"Non se admite a tarxeta SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-gu/strings.xml b/core/res/res/values-mcc310-mnc170-gu/strings.xml new file mode 100644 index 000000000000..60eba5b7ebb8 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-gu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIMને MM#2ની જોગવાઈ નથી"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIMને MM#3 કરવાની મંજૂરી નથી"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-hi/strings.xml b/core/res/res/values-mcc310-mnc170-hi/strings.xml new file mode 100644 index 000000000000..eb350b060cd0 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-hi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM काम नहीं कर रहा है MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM की अनुमति नहीं है MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-hr/strings.xml b/core/res/res/values-mcc310-mnc170-hr/strings.xml new file mode 100644 index 000000000000..d5cf0254f39b --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-hr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"Ne pruža se usluga za SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM nije dopušten MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-hu/strings.xml b/core/res/res/values-mcc310-mnc170-hu/strings.xml new file mode 100644 index 000000000000..e05e7005174f --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-hu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"Nem engedélyezett SIM-kártya (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"A SIM-kártya nem engedélyezett (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-hy/strings.xml b/core/res/res/values-mcc310-mnc170-hy/strings.xml new file mode 100644 index 000000000000..90a5f6d83e96 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-hy/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM քարտը նախապատրաստված չէ (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM քարտի օգտագործումն արգելված է (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-in/strings.xml b/core/res/res/values-mcc310-mnc170-in/strings.xml new file mode 100644 index 000000000000..fc1bd0a9723c --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-in/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM tidak di-provisioning MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM tidak diizinkan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-is/strings.xml b/core/res/res/values-mcc310-mnc170-is/strings.xml new file mode 100644 index 000000000000..eef786c683de --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-is/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM-korti ekki úthlutað MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM-kort ekki leyft MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-it/strings.xml b/core/res/res/values-mcc310-mnc170-it/strings.xml new file mode 100644 index 000000000000..eaf0abc7625b --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-it/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"Scheda SIM non predisposta MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"Scheda SIM non consentita MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-iw/strings.xml b/core/res/res/values-mcc310-mnc170-iw/strings.xml new file mode 100644 index 000000000000..edee703a8006 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-iw/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"כרטיס ה-SIM לא הופעל MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"כרטיס ה-SIM לא מורשה לשימוש ברשת הסלולרית MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-ja/strings.xml b/core/res/res/values-mcc310-mnc170-ja/strings.xml new file mode 100644 index 000000000000..6942641e63fd --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-ja/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM には対応していません(MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM は許可されていません(MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-ka/strings.xml b/core/res/res/values-mcc310-mnc170-ka/strings.xml new file mode 100644 index 000000000000..6f6c4aa6ef31 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-ka/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM ბარათი უზრუნველყოფილი არ არის (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM ბარათი დაუშვებელია (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-kk/strings.xml b/core/res/res/values-mcc310-mnc170-kk/strings.xml new file mode 100644 index 000000000000..210fb31d3c33 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-kk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM картасы қарастырылмаған MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM картасына рұқсат етілмеген MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-km/strings.xml b/core/res/res/values-mcc310-mnc170-km/strings.xml new file mode 100644 index 000000000000..79acf4840456 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-km/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"ស៊ីមកាតមិនត្រូវបានផ្ដល់ជូនទេ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"មិនអនុញ្ញាតចំពោះស៊ីមកាតទេ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-kn/strings.xml b/core/res/res/values-mcc310-mnc170-kn/strings.xml new file mode 100644 index 000000000000..e11523b9cedd --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-kn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"MM#2 ಗೆ ಸಿಮ್ ಸಿದ್ಧವಾಗಿಲ್ಲ"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"ಸಿಮ್ MM#3 ಅನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-ko/strings.xml b/core/res/res/values-mcc310-mnc170-ko/strings.xml new file mode 100644 index 000000000000..22d7e35d3450 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-ko/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM이 프로비저닝되지 않음 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM이 허용되지 않음 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-ky/strings.xml b/core/res/res/values-mcc310-mnc170-ky/strings.xml new file mode 100644 index 000000000000..1f07c68cd1c5 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-ky/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM карта таанылган жок (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM картаны колдонууга тыюу салынган (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-lo/strings.xml b/core/res/res/values-mcc310-mnc170-lo/strings.xml new file mode 100644 index 000000000000..3073000ac74d --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-lo/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM ບໍ່ໄດ້ເປີດໃຊ້ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM ບໍ່ອະນຸຍາດ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-lt/strings.xml b/core/res/res/values-mcc310-mnc170-lt/strings.xml new file mode 100644 index 000000000000..127e69fc2057 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-lt/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM kortelė neteikiama (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM kortelė neleidžiama (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-lv/strings.xml b/core/res/res/values-mcc310-mnc170-lv/strings.xml new file mode 100644 index 000000000000..da2ff7cc6b0c --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-lv/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM karte netiek nodrošināta: MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM karti nav atļauts izmantot: MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-mk/strings.xml b/core/res/res/values-mcc310-mnc170-mk/strings.xml new file mode 100644 index 000000000000..3bc8194157bd --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-mk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"Не е обезбедена SIM-картичка, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"Не е дозволена SIM-картичка, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-ml/strings.xml b/core/res/res/values-mcc310-mnc170-ml/strings.xml new file mode 100644 index 000000000000..0479aefb4795 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-ml/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"സിം MM#2 പ്രൊവിഷൻ ചെയ്തിട്ടില്ല"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"സിം MM#3 അനുവദിച്ചിട്ടില്ല"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-mn/strings.xml b/core/res/res/values-mcc310-mnc170-mn/strings.xml new file mode 100644 index 000000000000..59f24ec6a212 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-mn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM-г идэвхжүүлээгүй байна MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM-г зөвшөөрөөгүй байна MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-mr/strings.xml b/core/res/res/values-mcc310-mnc170-mr/strings.xml new file mode 100644 index 000000000000..938207c6d6db --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-mr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM ने MM#2 ची तरतूद केलेली नाही"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM ने MM#3 ला परवानगी दिली नाही"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-ms/strings.xml b/core/res/res/values-mcc310-mnc170-ms/strings.xml new file mode 100644 index 000000000000..36be774cd404 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-ms/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM tidak diperuntukkan MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM tidak dibenarkan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-my/strings.xml b/core/res/res/values-mcc310-mnc170-my/strings.xml new file mode 100644 index 000000000000..61f1a67a06d6 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-my/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"ဆင်းမ်ကို ထောက်ပံ့မထားပါ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"ဆင်းမ်ကို ခွင့်မပြုပါ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-nb/strings.xml b/core/res/res/values-mcc310-mnc170-nb/strings.xml new file mode 100644 index 000000000000..3f213dad4dee --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-nb/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM-kortet er ikke klargjort, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM-kortet er ikke tillatt, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-ne/strings.xml b/core/res/res/values-mcc310-mnc170-ne/strings.xml new file mode 100644 index 000000000000..d7febc4606c1 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-ne/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM को प्रावधान छैन MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM लाई अनुमति छैन MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-nl/strings.xml b/core/res/res/values-mcc310-mnc170-nl/strings.xml new file mode 100644 index 000000000000..b1f9ba8f47db --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-nl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"Simkaart niet geregistreerd MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"Simkaart niet toegestaan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-pa/strings.xml b/core/res/res/values-mcc310-mnc170-pa/strings.xml new file mode 100644 index 000000000000..9e993e343e2e --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-pa/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"ਸਿਮ ਦੀ ਵਿਵਸਥਾ ਨਹੀਂ ਹੈ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"ਸਿਮ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-pl/strings.xml b/core/res/res/values-mcc310-mnc170-pl/strings.xml new file mode 100644 index 000000000000..d1ecd5d4fb9b --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-pl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"MM#2 – karta SIM nieobsługiwana"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"MM#3 – niedozwolona karta SIM"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-pt-rBR/strings.xml b/core/res/res/values-mcc310-mnc170-pt-rBR/strings.xml new file mode 100644 index 000000000000..fc31e9e27890 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-pt-rBR/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-pt-rPT/strings.xml b/core/res/res/values-mcc310-mnc170-pt-rPT/strings.xml new file mode 100644 index 000000000000..fc31e9e27890 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-pt-rPT/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-pt/strings.xml b/core/res/res/values-mcc310-mnc170-pt/strings.xml new file mode 100644 index 000000000000..fc31e9e27890 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-pt/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-ro/strings.xml b/core/res/res/values-mcc310-mnc170-ro/strings.xml new file mode 100644 index 000000000000..1ee50808c8ac --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-ro/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"Cardul SIM nu este activat MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"Cardul SIM nu este permis MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-ru/strings.xml b/core/res/res/values-mcc310-mnc170-ru/strings.xml new file mode 100644 index 000000000000..0e009097f7e6 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-ru/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM-карта не активирована (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"Использование SIM-карты запрещено (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-si/strings.xml b/core/res/res/values-mcc310-mnc170-si/strings.xml new file mode 100644 index 000000000000..bbd1e4c496f0 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-si/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM MM#2 ප්රතිපාදනය නොකරයි"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM MM#3 ඉඩ නොදේ"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-sk/strings.xml b/core/res/res/values-mcc310-mnc170-sk/strings.xml new file mode 100644 index 000000000000..e5f937628ae1 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-sk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM karta nie je k dispozícii – MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM karta je zakázaná – MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-sl/strings.xml b/core/res/res/values-mcc310-mnc170-sl/strings.xml new file mode 100644 index 000000000000..2d4c7dd28109 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-sl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"Kartica SIM ni omogočena za uporabo MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"Kartica SIM ni dovoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-sq/strings.xml b/core/res/res/values-mcc310-mnc170-sq/strings.xml new file mode 100644 index 000000000000..df5b53718f23 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-sq/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"Karta SIM nuk është dhënë MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"Karta SIM nuk lejohet MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-sr/strings.xml b/core/res/res/values-mcc310-mnc170-sr/strings.xml new file mode 100644 index 000000000000..6bfbbb2be7a6 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-sr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM картица није подешена MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM картица није дозвољена MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-sv/strings.xml b/core/res/res/values-mcc310-mnc170-sv/strings.xml new file mode 100644 index 000000000000..1a28db1d6196 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-sv/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM-kort tillhandahålls inte MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM-kort tillåts inte MM#3"</string> +</resources> diff --git a/packages/SystemUI/res-keyguard/values-sw380dp/dimens.xml b/core/res/res/values-mcc310-mnc170-sw/strings.xml index fc0e85d26bae..0852115fa401 100644 --- a/packages/SystemUI/res-keyguard/values-sw380dp/dimens.xml +++ b/core/res/res/values-mcc310-mnc170-sw/strings.xml @@ -1,9 +1,10 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml ** -** Copyright 2012, The Android Open Source Project +** Copyright 2006, The Android Open Source Project ** -** Licensed under the Apache License, Version 2.0 (the "License") +** 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 ** @@ -15,9 +16,10 @@ ** See the License for the specific language governing permissions and ** limitations under the License. */ ---> + --> -<resources> - <!-- Width of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) --> - <dimen name="keyguard_security_width">340dp</dimen> -</resources>
\ No newline at end of file +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM haitumiki MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM hairuhusiwi MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-ta/strings.xml b/core/res/res/values-mcc310-mnc170-ta/strings.xml new file mode 100644 index 000000000000..0277cc24fc81 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-ta/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"சிம் அமைக்கப்படவில்லை MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"சிம் அனுமதிக்கப்படவில்லை MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-te/strings.xml b/core/res/res/values-mcc310-mnc170-te/strings.xml new file mode 100644 index 000000000000..a208cd34787a --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-te/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM MM#2ని సక్రియం చేయలేదు"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM MM#3ని అనుమతించలేదు"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-th/strings.xml b/core/res/res/values-mcc310-mnc170-th/strings.xml new file mode 100644 index 000000000000..e5d02c86163e --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-th/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"ไม่มีการจัดสรรซิม MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"ไม่อนุญาตให้ใช้ซิม MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-tl/strings.xml b/core/res/res/values-mcc310-mnc170-tl/strings.xml new file mode 100644 index 000000000000..e2857596a692 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-tl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"Hindi na-provision ang SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"Hindi pinapahintulutan ang SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-tr/strings.xml b/core/res/res/values-mcc310-mnc170-tr/strings.xml new file mode 100644 index 000000000000..b5102efa530d --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-tr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM, MM#2\'nin temel hazırlığını yapamadı"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM MM#3\'e izin vermiyor"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-uk/strings.xml b/core/res/res/values-mcc310-mnc170-uk/strings.xml new file mode 100644 index 000000000000..37e311882a7d --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-uk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM-карту не надано (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM-карта заборонена (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-ur/strings.xml b/core/res/res/values-mcc310-mnc170-ur/strings.xml new file mode 100644 index 000000000000..ea8b93e83dca --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-ur/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM فراہم کردہ نہیں ہے MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM کی اجازت نہیں ہے MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-uz/strings.xml b/core/res/res/values-mcc310-mnc170-uz/strings.xml new file mode 100644 index 000000000000..0bb3f5263a2f --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-uz/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM karta ishlatish taqiqlangan (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM karta ishlatish taqiqlangan (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-vi/strings.xml b/core/res/res/values-mcc310-mnc170-vi/strings.xml new file mode 100644 index 000000000000..a37f48f1a03f --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-vi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"SIM không được cấp phép MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"SIM không được phép MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-zh-rCN/strings.xml b/core/res/res/values-mcc310-mnc170-zh-rCN/strings.xml new file mode 100644 index 000000000000..f072b28ec3ea --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-zh-rCN/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"未配置的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"不被允许的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-zh-rHK/strings.xml b/core/res/res/values-mcc310-mnc170-zh-rHK/strings.xml new file mode 100644 index 000000000000..db14b904968c --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-zh-rHK/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"未佈建的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"不支援的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-zh-rTW/strings.xml b/core/res/res/values-mcc310-mnc170-zh-rTW/strings.xml new file mode 100644 index 000000000000..db14b904968c --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-zh-rTW/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"未佈建的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"不支援的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc170-zu/strings.xml b/core/res/res/values-mcc310-mnc170-zu/strings.xml new file mode 100644 index 000000000000..282f403c8918 --- /dev/null +++ b/core/res/res/values-mcc310-mnc170-zu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="210168420192421012">"I-SIM ayinikezelwe MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1130721094178658338">"I-SIM ayivunyelwe MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-af/strings.xml b/core/res/res/values-mcc310-mnc280-af/strings.xml new file mode 100644 index 000000000000..a7618819ac6a --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-af/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM is nie opgestel nie MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM word nie toegelaat nie MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-am/strings.xml b/core/res/res/values-mcc310-mnc280-am/strings.xml new file mode 100644 index 000000000000..6750a710945e --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-am/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"ሲም አልቀረበም MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"ሲም አይፈቀድም MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-ar/strings.xml b/core/res/res/values-mcc310-mnc280-ar/strings.xml new file mode 100644 index 000000000000..a77d78e386b5 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-ar/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"لم يتم توفير SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"غير مسموح باستخدام SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-az/strings.xml b/core/res/res/values-mcc310-mnc280-az/strings.xml new file mode 100644 index 000000000000..b7ee114877c1 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-az/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM MM#2 təmin etmir"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM MM#3 dəstəkləmir"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-b+sr+Latn/strings.xml b/core/res/res/values-mcc310-mnc280-b+sr+Latn/strings.xml new file mode 100644 index 000000000000..0c78b5e7ac43 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-b+sr+Latn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM kartica nije podešena MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM kartica nije dozvoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-be/strings.xml b/core/res/res/values-mcc310-mnc280-be/strings.xml new file mode 100644 index 000000000000..3ee9ad9a9d07 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-be/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM-карты няма MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM-карта не дапускаецца MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-bg/strings.xml b/core/res/res/values-mcc310-mnc280-bg/strings.xml new file mode 100644 index 000000000000..a320898a3dbc --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-bg/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM картата не е обезпечена MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM картата не е разрешена MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-bn/strings.xml b/core/res/res/values-mcc310-mnc280-bn/strings.xml new file mode 100644 index 000000000000..dc950a7507e0 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-bn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"সিমের জন্য প্রস্তুত নয় MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"সিমের অনুমতি নেই MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-bs/strings.xml b/core/res/res/values-mcc310-mnc280-bs/strings.xml new file mode 100644 index 000000000000..d61fad8d2dff --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-bs/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM kartica nije dodijeljena MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM kartica nije dozvoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-ca/strings.xml b/core/res/res/values-mcc310-mnc280-ca/strings.xml new file mode 100644 index 000000000000..9a9e309cabf2 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-ca/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"La SIM no està proporcionada a MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"La SIM no és compatible a MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-cs/strings.xml b/core/res/res/values-mcc310-mnc280-cs/strings.xml new file mode 100644 index 000000000000..99e2bdbe3600 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-cs/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM karta není poskytována (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM karta není povolena (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-da/strings.xml b/core/res/res/values-mcc310-mnc280-da/strings.xml new file mode 100644 index 000000000000..4f444a1ecc85 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-da/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM-kort leveres ikke MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM-kort er ikke tilladt MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-de/strings.xml b/core/res/res/values-mcc310-mnc280-de/strings.xml new file mode 100644 index 000000000000..063c75ba3440 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-de/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM-Karte nicht eingerichtet MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM-Karte nicht zulässig MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-el/strings.xml b/core/res/res/values-mcc310-mnc280-el/strings.xml new file mode 100644 index 000000000000..1161a7de5496 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-el/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"Δεν παρέχεται κάρτα SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"Η κάρτα SIM δεν επιτρέπεται MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-en-rAU/strings.xml b/core/res/res/values-mcc310-mnc280-en-rAU/strings.xml new file mode 100644 index 000000000000..e9c9eba2c6ab --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-en-rAU/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-en-rCA/strings.xml b/core/res/res/values-mcc310-mnc280-en-rCA/strings.xml new file mode 100644 index 000000000000..e9c9eba2c6ab --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-en-rCA/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-en-rGB/strings.xml b/core/res/res/values-mcc310-mnc280-en-rGB/strings.xml new file mode 100644 index 000000000000..e9c9eba2c6ab --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-en-rGB/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-en-rIN/strings.xml b/core/res/res/values-mcc310-mnc280-en-rIN/strings.xml new file mode 100644 index 000000000000..e9c9eba2c6ab --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-en-rIN/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-en-rXC/strings.xml b/core/res/res/values-mcc310-mnc280-en-rXC/strings.xml new file mode 100644 index 000000000000..83640ae1e080 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-en-rXC/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-es-rUS/strings.xml b/core/res/res/values-mcc310-mnc280-es-rUS/strings.xml new file mode 100644 index 000000000000..86ad4fdda683 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-es-rUS/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM no provista MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM no permitida MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-es/strings.xml b/core/res/res/values-mcc310-mnc280-es/strings.xml new file mode 100644 index 000000000000..2c7aa938f255 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-es/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM no proporcionada (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM no admitida (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-et/strings.xml b/core/res/res/values-mcc310-mnc280-et/strings.xml new file mode 100644 index 000000000000..7305d1815d6e --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-et/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM-kaart on ette valmistamata MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM-kaart pole lubatud MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-eu/strings.xml b/core/res/res/values-mcc310-mnc280-eu/strings.xml new file mode 100644 index 000000000000..3c7296d62f83 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-eu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"Ez dago SIM txartelik MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"Ez da onartzen SIM txartela MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-fa/strings.xml b/core/res/res/values-mcc310-mnc280-fa/strings.xml new file mode 100644 index 000000000000..cd7ce85d87bf --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-fa/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"سیمکارت مجوز لازم را ندارد MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"سیمکارت مجاز نیست MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-fi/strings.xml b/core/res/res/values-mcc310-mnc280-fi/strings.xml new file mode 100644 index 000000000000..b2ccc50798dc --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-fi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM-kortti ei käyttäjien hallinnassa MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM-kortti estetty MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-fr-rCA/strings.xml b/core/res/res/values-mcc310-mnc280-fr-rCA/strings.xml new file mode 100644 index 000000000000..29bb9a01bdd9 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-fr-rCA/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"Carte SIM non configurée, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"Carte SIM non autorisée, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-fr/strings.xml b/core/res/res/values-mcc310-mnc280-fr/strings.xml new file mode 100644 index 000000000000..ce2f931e515f --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-fr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"Carte SIM non provisionnée MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"Carte SIM non autorisée MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-gl/strings.xml b/core/res/res/values-mcc310-mnc280-gl/strings.xml new file mode 100644 index 000000000000..e941341fe1ac --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-gl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"Non se introduciu ningunha tarxeta SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"Non se admite a tarxeta SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-gu/strings.xml b/core/res/res/values-mcc310-mnc280-gu/strings.xml new file mode 100644 index 000000000000..a3763be67d33 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-gu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIMને MM#2ની જોગવાઈ નથી"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIMને MM#3 કરવાની મંજૂરી નથી"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-hi/strings.xml b/core/res/res/values-mcc310-mnc280-hi/strings.xml new file mode 100644 index 000000000000..ce866affad5f --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-hi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM काम नहीं कर रहा है MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM की अनुमति नहीं है MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-hr/strings.xml b/core/res/res/values-mcc310-mnc280-hr/strings.xml new file mode 100644 index 000000000000..00214746628b --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-hr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"Ne pruža se usluga za SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM nije dopušten MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-hu/strings.xml b/core/res/res/values-mcc310-mnc280-hu/strings.xml new file mode 100644 index 000000000000..864faffe5699 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-hu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"Nem engedélyezett SIM-kártya (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"A SIM-kártya nem engedélyezett (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-hy/strings.xml b/core/res/res/values-mcc310-mnc280-hy/strings.xml new file mode 100644 index 000000000000..6d027c368f77 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-hy/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM քարտը նախապատրաստված չէ (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM քարտի օգտագործումն արգելված է (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-in/strings.xml b/core/res/res/values-mcc310-mnc280-in/strings.xml new file mode 100644 index 000000000000..a4f34862e130 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-in/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM tidak di-provisioning MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM tidak diizinkan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-is/strings.xml b/core/res/res/values-mcc310-mnc280-is/strings.xml new file mode 100644 index 000000000000..30bbea4648f6 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-is/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM-korti ekki úthlutað MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM-kort ekki leyft MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-it/strings.xml b/core/res/res/values-mcc310-mnc280-it/strings.xml new file mode 100644 index 000000000000..f83921bdc33c --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-it/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"Scheda SIM non predisposta MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"Scheda SIM non consentita MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-iw/strings.xml b/core/res/res/values-mcc310-mnc280-iw/strings.xml new file mode 100644 index 000000000000..f3f87ffa9f85 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-iw/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"כרטיס ה-SIM לא הופעל MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"כרטיס ה-SIM לא מורשה לשימוש ברשת הסלולרית MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-ja/strings.xml b/core/res/res/values-mcc310-mnc280-ja/strings.xml new file mode 100644 index 000000000000..a1cfd8ba030e --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-ja/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM には対応していません(MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM は許可されていません(MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-ka/strings.xml b/core/res/res/values-mcc310-mnc280-ka/strings.xml new file mode 100644 index 000000000000..91c434f2553b --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-ka/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM ბარათი უზრუნველყოფილი არ არის (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM ბარათი დაუშვებელია (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-kk/strings.xml b/core/res/res/values-mcc310-mnc280-kk/strings.xml new file mode 100644 index 000000000000..44440d3f9fee --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-kk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM картасы қарастырылмаған MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM картасына рұқсат етілмеген MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-km/strings.xml b/core/res/res/values-mcc310-mnc280-km/strings.xml new file mode 100644 index 000000000000..a016601920ec --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-km/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"ស៊ីមកាតមិនត្រូវបានផ្ដល់ជូនទេ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"មិនអនុញ្ញាតចំពោះស៊ីមកាតទេ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-kn/strings.xml b/core/res/res/values-mcc310-mnc280-kn/strings.xml new file mode 100644 index 000000000000..1d9e3536a734 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-kn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"MM#2 ಗೆ ಸಿಮ್ ಸಿದ್ಧವಾಗಿಲ್ಲ"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"ಸಿಮ್ MM#3 ಅನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-ko/strings.xml b/core/res/res/values-mcc310-mnc280-ko/strings.xml new file mode 100644 index 000000000000..e7bb9bbef75e --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-ko/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM이 프로비저닝되지 않음 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM이 허용되지 않음 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-ky/strings.xml b/core/res/res/values-mcc310-mnc280-ky/strings.xml new file mode 100644 index 000000000000..85483c705c1e --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-ky/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM карта таанылган жок (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM картаны колдонууга тыюу салынган (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-lo/strings.xml b/core/res/res/values-mcc310-mnc280-lo/strings.xml new file mode 100644 index 000000000000..9415089c6f80 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-lo/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM ບໍ່ໄດ້ເປີດໃຊ້ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM ບໍ່ອະນຸຍາດ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-lt/strings.xml b/core/res/res/values-mcc310-mnc280-lt/strings.xml new file mode 100644 index 000000000000..b5ff1b91a9a0 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-lt/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM kortelė neteikiama (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM kortelė neleidžiama (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-lv/strings.xml b/core/res/res/values-mcc310-mnc280-lv/strings.xml new file mode 100644 index 000000000000..4034bc194be4 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-lv/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM karte netiek nodrošināta: MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM karti nav atļauts izmantot: MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-mk/strings.xml b/core/res/res/values-mcc310-mnc280-mk/strings.xml new file mode 100644 index 000000000000..a93cb796720b --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-mk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"Не е обезбедена SIM-картичка, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"Не е дозволена SIM-картичка, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-ml/strings.xml b/core/res/res/values-mcc310-mnc280-ml/strings.xml new file mode 100644 index 000000000000..4aa7dec1601c --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-ml/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"സിം MM#2 പ്രൊവിഷൻ ചെയ്തിട്ടില്ല"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"സിം MM#3 അനുവദിച്ചിട്ടില്ല"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-mn/strings.xml b/core/res/res/values-mcc310-mnc280-mn/strings.xml new file mode 100644 index 000000000000..54b819089325 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-mn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM-г идэвхжүүлээгүй байна MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM-г зөвшөөрөөгүй байна MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-mr/strings.xml b/core/res/res/values-mcc310-mnc280-mr/strings.xml new file mode 100644 index 000000000000..cb343cb64d4a --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-mr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM ने MM#2 ची तरतूद केलेली नाही"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM ने MM#3 ला परवानगी दिली नाही"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-ms/strings.xml b/core/res/res/values-mcc310-mnc280-ms/strings.xml new file mode 100644 index 000000000000..27da7475f074 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-ms/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM tidak diperuntukkan MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM tidak dibenarkan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-my/strings.xml b/core/res/res/values-mcc310-mnc280-my/strings.xml new file mode 100644 index 000000000000..40cdc6385956 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-my/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"ဆင်းမ်ကို ထောက်ပံ့မထားပါ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"ဆင်းမ်ကို ခွင့်မပြုပါ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-nb/strings.xml b/core/res/res/values-mcc310-mnc280-nb/strings.xml new file mode 100644 index 000000000000..7666c3ead76f --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-nb/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM-kortet er ikke klargjort, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM-kortet er ikke tillatt, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-ne/strings.xml b/core/res/res/values-mcc310-mnc280-ne/strings.xml new file mode 100644 index 000000000000..87356059b5b5 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-ne/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM को प्रावधान छैन MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM लाई अनुमति छैन MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-nl/strings.xml b/core/res/res/values-mcc310-mnc280-nl/strings.xml new file mode 100644 index 000000000000..7d7bfa70e659 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-nl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"Simkaart niet geregistreerd MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"Simkaart niet toegestaan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-pa/strings.xml b/core/res/res/values-mcc310-mnc280-pa/strings.xml new file mode 100644 index 000000000000..3a658661e42d --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-pa/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"ਸਿਮ ਦੀ ਵਿਵਸਥਾ ਨਹੀਂ ਹੈ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"ਸਿਮ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-pl/strings.xml b/core/res/res/values-mcc310-mnc280-pl/strings.xml new file mode 100644 index 000000000000..52410f4a5f3f --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-pl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"MM#2 – karta SIM nieobsługiwana"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"MM#3 – niedozwolona karta SIM"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-pt-rBR/strings.xml b/core/res/res/values-mcc310-mnc280-pt-rBR/strings.xml new file mode 100644 index 000000000000..03d0efb156f9 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-pt-rBR/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-pt-rPT/strings.xml b/core/res/res/values-mcc310-mnc280-pt-rPT/strings.xml new file mode 100644 index 000000000000..03d0efb156f9 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-pt-rPT/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-pt/strings.xml b/core/res/res/values-mcc310-mnc280-pt/strings.xml new file mode 100644 index 000000000000..03d0efb156f9 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-pt/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-ro/strings.xml b/core/res/res/values-mcc310-mnc280-ro/strings.xml new file mode 100644 index 000000000000..d60ea0c7a2e4 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-ro/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"Cardul SIM nu este activat MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"Cardul SIM nu este permis MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-ru/strings.xml b/core/res/res/values-mcc310-mnc280-ru/strings.xml new file mode 100644 index 000000000000..308c353f763d --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-ru/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM-карта не активирована (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"Использование SIM-карты запрещено (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-si/strings.xml b/core/res/res/values-mcc310-mnc280-si/strings.xml new file mode 100644 index 000000000000..5bd6d1fa41df --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-si/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM MM#2 ප්රතිපාදනය නොකරයි"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM MM#3 ඉඩ නොදේ"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-sk/strings.xml b/core/res/res/values-mcc310-mnc280-sk/strings.xml new file mode 100644 index 000000000000..4098ac7b242d --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-sk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM karta nie je k dispozícii – MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM karta je zakázaná – MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-sl/strings.xml b/core/res/res/values-mcc310-mnc280-sl/strings.xml new file mode 100644 index 000000000000..faa78ad4c6d0 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-sl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"Kartica SIM ni omogočena za uporabo MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"Kartica SIM ni dovoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-sq/strings.xml b/core/res/res/values-mcc310-mnc280-sq/strings.xml new file mode 100644 index 000000000000..48fba2d21c97 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-sq/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"Karta SIM nuk është dhënë MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"Karta SIM nuk lejohet MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-sr/strings.xml b/core/res/res/values-mcc310-mnc280-sr/strings.xml new file mode 100644 index 000000000000..30c9df3f8ee4 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-sr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM картица није подешена MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM картица није дозвољена MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-sv/strings.xml b/core/res/res/values-mcc310-mnc280-sv/strings.xml new file mode 100644 index 000000000000..cb5b9f32ebaa --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-sv/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM-kort tillhandahålls inte MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM-kort tillåts inte MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-sw/strings.xml b/core/res/res/values-mcc310-mnc280-sw/strings.xml new file mode 100644 index 000000000000..15a1a365b2ca --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-sw/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM haitumiki MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM hairuhusiwi MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-ta/strings.xml b/core/res/res/values-mcc310-mnc280-ta/strings.xml new file mode 100644 index 000000000000..c3911d4a57eb --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-ta/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"சிம் அமைக்கப்படவில்லை MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"சிம் அனுமதிக்கப்படவில்லை MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-te/strings.xml b/core/res/res/values-mcc310-mnc280-te/strings.xml new file mode 100644 index 000000000000..f5cabaddfb40 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-te/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM MM#2ని సక్రియం చేయలేదు"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM MM#3ని అనుమతించలేదు"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-th/strings.xml b/core/res/res/values-mcc310-mnc280-th/strings.xml new file mode 100644 index 000000000000..9810ba653f02 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-th/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"ไม่มีการจัดสรรซิม MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"ไม่อนุญาตให้ใช้ซิม MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-tl/strings.xml b/core/res/res/values-mcc310-mnc280-tl/strings.xml new file mode 100644 index 000000000000..600ad05a915f --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-tl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"Hindi na-provision ang SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"Hindi pinapahintulutan ang SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-tr/strings.xml b/core/res/res/values-mcc310-mnc280-tr/strings.xml new file mode 100644 index 000000000000..ea90bdb86a1d --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-tr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM, MM#2\'nin temel hazırlığını yapamadı"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM MM#3\'e izin vermiyor"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-uk/strings.xml b/core/res/res/values-mcc310-mnc280-uk/strings.xml new file mode 100644 index 000000000000..68a34fde6d24 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-uk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM-карту не надано (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM-карта заборонена (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-ur/strings.xml b/core/res/res/values-mcc310-mnc280-ur/strings.xml new file mode 100644 index 000000000000..d61a5dcd1b7c --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-ur/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM فراہم کردہ نہیں ہے MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM کی اجازت نہیں ہے MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-uz/strings.xml b/core/res/res/values-mcc310-mnc280-uz/strings.xml new file mode 100644 index 000000000000..324d3647ee8b --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-uz/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM karta ishlatish taqiqlangan (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM karta ishlatish taqiqlangan (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-vi/strings.xml b/core/res/res/values-mcc310-mnc280-vi/strings.xml new file mode 100644 index 000000000000..6806e39d95d3 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-vi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM không được cấp phép MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM không được phép MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-zh-rCN/strings.xml b/core/res/res/values-mcc310-mnc280-zh-rCN/strings.xml new file mode 100644 index 000000000000..add3f9207fe6 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-zh-rCN/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"未配置的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"不被允许的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-zh-rHK/strings.xml b/core/res/res/values-mcc310-mnc280-zh-rHK/strings.xml new file mode 100644 index 000000000000..856297c6068a --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-zh-rHK/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"未佈建的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"不支援的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-zh-rTW/strings.xml b/core/res/res/values-mcc310-mnc280-zh-rTW/strings.xml new file mode 100644 index 000000000000..856297c6068a --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-zh-rTW/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"未佈建的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"不支援的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc280-zu/strings.xml b/core/res/res/values-mcc310-mnc280-zu/strings.xml new file mode 100644 index 000000000000..6c5147c9a140 --- /dev/null +++ b/core/res/res/values-mcc310-mnc280-zu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6638755728961013003">"I-SIM ayinikezelwe MM#2"</string> + <string name="mmcc_illegal_ms" msgid="5562215652599183258">"I-SIM ayivunyelwe MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-af/strings.xml b/core/res/res/values-mcc310-mnc380-af/strings.xml new file mode 100644 index 000000000000..7dfadad60447 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-af/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM is nie opgestel nie MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM word nie toegelaat nie MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-am/strings.xml b/core/res/res/values-mcc310-mnc380-am/strings.xml new file mode 100644 index 000000000000..dd9dbacd8735 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-am/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"ሲም አልቀረበም MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"ሲም አይፈቀድም MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-ar/strings.xml b/core/res/res/values-mcc310-mnc380-ar/strings.xml new file mode 100644 index 000000000000..381749e1043a --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-ar/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"لم يتم توفير SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"غير مسموح باستخدام SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-az/strings.xml b/core/res/res/values-mcc310-mnc380-az/strings.xml new file mode 100644 index 000000000000..aeb1c796a900 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-az/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM MM#2 təmin etmir"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM MM#3 dəstəkləmir"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-b+sr+Latn/strings.xml b/core/res/res/values-mcc310-mnc380-b+sr+Latn/strings.xml new file mode 100644 index 000000000000..acc1ff69b44d --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-b+sr+Latn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM kartica nije podešena MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM kartica nije dozvoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-be/strings.xml b/core/res/res/values-mcc310-mnc380-be/strings.xml new file mode 100644 index 000000000000..926d2ea83751 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-be/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM-карты няма MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM-карта не дапускаецца MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-bg/strings.xml b/core/res/res/values-mcc310-mnc380-bg/strings.xml new file mode 100644 index 000000000000..bdce855d14a9 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-bg/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM картата не е обезпечена MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM картата не е разрешена MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-bn/strings.xml b/core/res/res/values-mcc310-mnc380-bn/strings.xml new file mode 100644 index 000000000000..38ba93be3658 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-bn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"সিমের জন্য প্রস্তুত নয় MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"সিমের অনুমতি নেই MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-bs/strings.xml b/core/res/res/values-mcc310-mnc380-bs/strings.xml new file mode 100644 index 000000000000..ce14799bc5de --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-bs/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM kartica nije dodijeljena MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM kartica nije dozvoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-ca/strings.xml b/core/res/res/values-mcc310-mnc380-ca/strings.xml new file mode 100644 index 000000000000..e30fd81a63fe --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-ca/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"La SIM no està proporcionada a MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"La SIM no és compatible a MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-cs/strings.xml b/core/res/res/values-mcc310-mnc380-cs/strings.xml new file mode 100644 index 000000000000..62fe37ca84cb --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-cs/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM karta není poskytována (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM karta není povolena (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-da/strings.xml b/core/res/res/values-mcc310-mnc380-da/strings.xml new file mode 100644 index 000000000000..7dda72cf76ec --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-da/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM-kort leveres ikke MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM-kort er ikke tilladt MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-de/strings.xml b/core/res/res/values-mcc310-mnc380-de/strings.xml new file mode 100644 index 000000000000..ca039269ecb3 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-de/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM-Karte nicht eingerichtet MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM-Karte nicht zulässig MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-el/strings.xml b/core/res/res/values-mcc310-mnc380-el/strings.xml new file mode 100644 index 000000000000..07d0db4bbc2b --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-el/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"Δεν παρέχεται κάρτα SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"Η κάρτα SIM δεν επιτρέπεται MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-en-rAU/strings.xml b/core/res/res/values-mcc310-mnc380-en-rAU/strings.xml new file mode 100644 index 000000000000..faf6df8aa8ae --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-en-rAU/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-en-rCA/strings.xml b/core/res/res/values-mcc310-mnc380-en-rCA/strings.xml new file mode 100644 index 000000000000..faf6df8aa8ae --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-en-rCA/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-en-rGB/strings.xml b/core/res/res/values-mcc310-mnc380-en-rGB/strings.xml new file mode 100644 index 000000000000..faf6df8aa8ae --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-en-rGB/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-en-rIN/strings.xml b/core/res/res/values-mcc310-mnc380-en-rIN/strings.xml new file mode 100644 index 000000000000..faf6df8aa8ae --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-en-rIN/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-en-rXC/strings.xml b/core/res/res/values-mcc310-mnc380-en-rXC/strings.xml new file mode 100644 index 000000000000..a6ef732104dd --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-en-rXC/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-es-rUS/strings.xml b/core/res/res/values-mcc310-mnc380-es-rUS/strings.xml new file mode 100644 index 000000000000..233566158bae --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-es-rUS/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM no provista MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM no permitida MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-es/strings.xml b/core/res/res/values-mcc310-mnc380-es/strings.xml new file mode 100644 index 000000000000..028c2656d6cd --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-es/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM no proporcionada (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM no admitida (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-et/strings.xml b/core/res/res/values-mcc310-mnc380-et/strings.xml new file mode 100644 index 000000000000..c25b12860c8f --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-et/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM-kaart on ette valmistamata MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM-kaart pole lubatud MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-eu/strings.xml b/core/res/res/values-mcc310-mnc380-eu/strings.xml new file mode 100644 index 000000000000..73bcd354d787 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-eu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"Ez dago SIM txartelik MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"Ez da onartzen SIM txartela MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-fa/strings.xml b/core/res/res/values-mcc310-mnc380-fa/strings.xml new file mode 100644 index 000000000000..b2b1126270fa --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-fa/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"سیمکارت مجوز لازم را ندارد MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"سیمکارت مجاز نیست MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-fi/strings.xml b/core/res/res/values-mcc310-mnc380-fi/strings.xml new file mode 100644 index 000000000000..dfb9b5fcadce --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-fi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM-kortti ei käyttäjien hallinnassa MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM-kortti estetty MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-fr-rCA/strings.xml b/core/res/res/values-mcc310-mnc380-fr-rCA/strings.xml new file mode 100644 index 000000000000..432c7a38eea4 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-fr-rCA/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"Carte SIM non configurée, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"Carte SIM non autorisée, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-fr/strings.xml b/core/res/res/values-mcc310-mnc380-fr/strings.xml new file mode 100644 index 000000000000..2041d89b1857 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-fr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"Carte SIM non provisionnée MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"Carte SIM non autorisée MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-gl/strings.xml b/core/res/res/values-mcc310-mnc380-gl/strings.xml new file mode 100644 index 000000000000..f224b9214046 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-gl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"Non se introduciu ningunha tarxeta SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"Non se admite a tarxeta SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-gu/strings.xml b/core/res/res/values-mcc310-mnc380-gu/strings.xml new file mode 100644 index 000000000000..13df8d3656e3 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-gu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIMને MM#2ની જોગવાઈ નથી"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIMને MM#3 કરવાની મંજૂરી નથી"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-hi/strings.xml b/core/res/res/values-mcc310-mnc380-hi/strings.xml new file mode 100644 index 000000000000..76247afa8025 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-hi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM काम नहीं कर रहा है MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM की अनुमति नहीं है MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-hr/strings.xml b/core/res/res/values-mcc310-mnc380-hr/strings.xml new file mode 100644 index 000000000000..21263b224b4b --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-hr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"Ne pruža se usluga za SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM nije dopušten MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-hu/strings.xml b/core/res/res/values-mcc310-mnc380-hu/strings.xml new file mode 100644 index 000000000000..bf4a40ca3d4d --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-hu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"Nem engedélyezett SIM-kártya (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"A SIM-kártya nem engedélyezett (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-hy/strings.xml b/core/res/res/values-mcc310-mnc380-hy/strings.xml new file mode 100644 index 000000000000..1fbf283023c9 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-hy/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM քարտը նախապատրաստված չէ (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM քարտի օգտագործումն արգելված է (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-in/strings.xml b/core/res/res/values-mcc310-mnc380-in/strings.xml new file mode 100644 index 000000000000..0b0ad54d68ea --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-in/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM tidak di-provisioning MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM tidak diizinkan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-is/strings.xml b/core/res/res/values-mcc310-mnc380-is/strings.xml new file mode 100644 index 000000000000..9df10077dc86 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-is/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM-korti ekki úthlutað MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM-kort ekki leyft MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-it/strings.xml b/core/res/res/values-mcc310-mnc380-it/strings.xml new file mode 100644 index 000000000000..3800d8324fdd --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-it/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"Scheda SIM non predisposta MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"Scheda SIM non consentita MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-iw/strings.xml b/core/res/res/values-mcc310-mnc380-iw/strings.xml new file mode 100644 index 000000000000..0602cb33da5c --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-iw/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"כרטיס ה-SIM לא הופעל MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"כרטיס ה-SIM לא מורשה לשימוש ברשת הסלולרית MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-ja/strings.xml b/core/res/res/values-mcc310-mnc380-ja/strings.xml new file mode 100644 index 000000000000..93aeee02c4a6 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-ja/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM には対応していません(MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM は許可されていません(MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-ka/strings.xml b/core/res/res/values-mcc310-mnc380-ka/strings.xml new file mode 100644 index 000000000000..773f2abd8b4a --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-ka/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM ბარათი უზრუნველყოფილი არ არის (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM ბარათი დაუშვებელია (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-kk/strings.xml b/core/res/res/values-mcc310-mnc380-kk/strings.xml new file mode 100644 index 000000000000..8e003c257da6 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-kk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM картасы қарастырылмаған MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM картасына рұқсат етілмеген MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-km/strings.xml b/core/res/res/values-mcc310-mnc380-km/strings.xml new file mode 100644 index 000000000000..eaadc8b1bcb6 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-km/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"ស៊ីមកាតមិនត្រូវបានផ្ដល់ជូនទេ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"មិនអនុញ្ញាតចំពោះស៊ីមកាតទេ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-kn/strings.xml b/core/res/res/values-mcc310-mnc380-kn/strings.xml new file mode 100644 index 000000000000..3d43e9a4001c --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-kn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"MM#2 ಗೆ ಸಿಮ್ ಸಿದ್ಧವಾಗಿಲ್ಲ"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"ಸಿಮ್ MM#3 ಅನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-ko/strings.xml b/core/res/res/values-mcc310-mnc380-ko/strings.xml new file mode 100644 index 000000000000..be4f15d325e6 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-ko/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM이 프로비저닝되지 않음 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM이 허용되지 않음 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-ky/strings.xml b/core/res/res/values-mcc310-mnc380-ky/strings.xml new file mode 100644 index 000000000000..de6916f19d51 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-ky/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM карта таанылган жок (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM картаны колдонууга тыюу салынган (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-lo/strings.xml b/core/res/res/values-mcc310-mnc380-lo/strings.xml new file mode 100644 index 000000000000..01cd13c4e0b8 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-lo/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM ບໍ່ໄດ້ເປີດໃຊ້ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM ບໍ່ອະນຸຍາດ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-lt/strings.xml b/core/res/res/values-mcc310-mnc380-lt/strings.xml new file mode 100644 index 000000000000..e7198394e4f7 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-lt/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM kortelė neteikiama (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM kortelė neleidžiama (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-lv/strings.xml b/core/res/res/values-mcc310-mnc380-lv/strings.xml new file mode 100644 index 000000000000..ecbc5182d8dd --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-lv/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM karte netiek nodrošināta: MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM karti nav atļauts izmantot: MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-mk/strings.xml b/core/res/res/values-mcc310-mnc380-mk/strings.xml new file mode 100644 index 000000000000..0cec5ab1e578 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-mk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"Не е обезбедена SIM-картичка, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"Не е дозволена SIM-картичка, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-ml/strings.xml b/core/res/res/values-mcc310-mnc380-ml/strings.xml new file mode 100644 index 000000000000..f986a991876f --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-ml/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"സിം MM#2 പ്രൊവിഷൻ ചെയ്തിട്ടില്ല"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"സിം MM#3 അനുവദിച്ചിട്ടില്ല"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-mn/strings.xml b/core/res/res/values-mcc310-mnc380-mn/strings.xml new file mode 100644 index 000000000000..a0534cec261e --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-mn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM-г идэвхжүүлээгүй байна MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM-г зөвшөөрөөгүй байна MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-mr/strings.xml b/core/res/res/values-mcc310-mnc380-mr/strings.xml new file mode 100644 index 000000000000..0541893ec1db --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-mr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM ने MM#2 ची तरतूद केलेली नाही"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM ने MM#3 ला परवानगी दिली नाही"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-ms/strings.xml b/core/res/res/values-mcc310-mnc380-ms/strings.xml new file mode 100644 index 000000000000..545ff3f64285 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-ms/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM tidak diperuntukkan MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM tidak dibenarkan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-my/strings.xml b/core/res/res/values-mcc310-mnc380-my/strings.xml new file mode 100644 index 000000000000..a375b04a1b8f --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-my/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"ဆင်းမ်ကို ထောက်ပံ့မထားပါ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"ဆင်းမ်ကို ခွင့်မပြုပါ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-nb/strings.xml b/core/res/res/values-mcc310-mnc380-nb/strings.xml new file mode 100644 index 000000000000..7fc96f05be12 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-nb/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM-kortet er ikke klargjort, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM-kortet er ikke tillatt, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-ne/strings.xml b/core/res/res/values-mcc310-mnc380-ne/strings.xml new file mode 100644 index 000000000000..28cdcba93c54 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-ne/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM को प्रावधान छैन MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM लाई अनुमति छैन MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-nl/strings.xml b/core/res/res/values-mcc310-mnc380-nl/strings.xml new file mode 100644 index 000000000000..33bc4b6ec4b8 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-nl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"Simkaart niet geregistreerd MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"Simkaart niet toegestaan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-pa/strings.xml b/core/res/res/values-mcc310-mnc380-pa/strings.xml new file mode 100644 index 000000000000..342c08e04954 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-pa/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"ਸਿਮ ਦੀ ਵਿਵਸਥਾ ਨਹੀਂ ਹੈ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"ਸਿਮ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-pl/strings.xml b/core/res/res/values-mcc310-mnc380-pl/strings.xml new file mode 100644 index 000000000000..df5b5d2c6c60 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-pl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"MM#2 – karta SIM nieobsługiwana"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"MM#3 – niedozwolona karta SIM"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-pt-rBR/strings.xml b/core/res/res/values-mcc310-mnc380-pt-rBR/strings.xml new file mode 100644 index 000000000000..06bc55abdb31 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-pt-rBR/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-pt-rPT/strings.xml b/core/res/res/values-mcc310-mnc380-pt-rPT/strings.xml new file mode 100644 index 000000000000..06bc55abdb31 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-pt-rPT/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-pt/strings.xml b/core/res/res/values-mcc310-mnc380-pt/strings.xml new file mode 100644 index 000000000000..06bc55abdb31 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-pt/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-ro/strings.xml b/core/res/res/values-mcc310-mnc380-ro/strings.xml new file mode 100644 index 000000000000..218dec4f1d8a --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-ro/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"Cardul SIM nu este activat MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"Cardul SIM nu este permis MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-ru/strings.xml b/core/res/res/values-mcc310-mnc380-ru/strings.xml new file mode 100644 index 000000000000..ab3bb21b23d3 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-ru/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM-карта не активирована (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"Использование SIM-карты запрещено (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-si/strings.xml b/core/res/res/values-mcc310-mnc380-si/strings.xml new file mode 100644 index 000000000000..be471a36a622 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-si/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM MM#2 ප්රතිපාදනය නොකරයි"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM MM#3 ඉඩ නොදේ"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-sk/strings.xml b/core/res/res/values-mcc310-mnc380-sk/strings.xml new file mode 100644 index 000000000000..91454e637fb0 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-sk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM karta nie je k dispozícii – MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM karta je zakázaná – MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-sl/strings.xml b/core/res/res/values-mcc310-mnc380-sl/strings.xml new file mode 100644 index 000000000000..1d29a789c4c3 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-sl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"Kartica SIM ni omogočena za uporabo MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"Kartica SIM ni dovoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-sq/strings.xml b/core/res/res/values-mcc310-mnc380-sq/strings.xml new file mode 100644 index 000000000000..c50b1dc89054 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-sq/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"Karta SIM nuk është dhënë MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"Karta SIM nuk lejohet MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-sr/strings.xml b/core/res/res/values-mcc310-mnc380-sr/strings.xml new file mode 100644 index 000000000000..e43d25ffa4b8 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-sr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM картица није подешена MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM картица није дозвољена MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-sv/strings.xml b/core/res/res/values-mcc310-mnc380-sv/strings.xml new file mode 100644 index 000000000000..213d26e98c03 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-sv/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM-kort tillhandahålls inte MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM-kort tillåts inte MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-sw/strings.xml b/core/res/res/values-mcc310-mnc380-sw/strings.xml new file mode 100644 index 000000000000..249dcb39a135 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-sw/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM haitumiki MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM hairuhusiwi MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-ta/strings.xml b/core/res/res/values-mcc310-mnc380-ta/strings.xml new file mode 100644 index 000000000000..d673f226abd4 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-ta/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"சிம் அமைக்கப்படவில்லை MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"சிம் அனுமதிக்கப்படவில்லை MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-te/strings.xml b/core/res/res/values-mcc310-mnc380-te/strings.xml new file mode 100644 index 000000000000..cfc800e71ddd --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-te/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM MM#2ని సక్రియం చేయలేదు"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM MM#3ని అనుమతించలేదు"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-th/strings.xml b/core/res/res/values-mcc310-mnc380-th/strings.xml new file mode 100644 index 000000000000..06bfa56359d5 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-th/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"ไม่มีการจัดสรรซิม MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"ไม่อนุญาตให้ใช้ซิม MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-tl/strings.xml b/core/res/res/values-mcc310-mnc380-tl/strings.xml new file mode 100644 index 000000000000..52e6edbe203b --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-tl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"Hindi na-provision ang SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"Hindi pinapahintulutan ang SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-tr/strings.xml b/core/res/res/values-mcc310-mnc380-tr/strings.xml new file mode 100644 index 000000000000..c59a8b5d1dcf --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-tr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM, MM#2\'nin temel hazırlığını yapamadı"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM MM#3\'e izin vermiyor"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-uk/strings.xml b/core/res/res/values-mcc310-mnc380-uk/strings.xml new file mode 100644 index 000000000000..c1b5a0276e78 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-uk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM-карту не надано (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM-карта заборонена (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-ur/strings.xml b/core/res/res/values-mcc310-mnc380-ur/strings.xml new file mode 100644 index 000000000000..1e68214b6ab1 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-ur/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM فراہم کردہ نہیں ہے MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM کی اجازت نہیں ہے MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-uz/strings.xml b/core/res/res/values-mcc310-mnc380-uz/strings.xml new file mode 100644 index 000000000000..89de07c88e9b --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-uz/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM karta ishlatish taqiqlangan (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM karta ishlatish taqiqlangan (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-vi/strings.xml b/core/res/res/values-mcc310-mnc380-vi/strings.xml new file mode 100644 index 000000000000..200da730d272 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-vi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"SIM không được cấp phép MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"SIM không được phép MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-zh-rCN/strings.xml b/core/res/res/values-mcc310-mnc380-zh-rCN/strings.xml new file mode 100644 index 000000000000..b150645b79ea --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-zh-rCN/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"未配置的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"不被允许的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-zh-rHK/strings.xml b/core/res/res/values-mcc310-mnc380-zh-rHK/strings.xml new file mode 100644 index 000000000000..7a7f22534883 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-zh-rHK/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"未佈建的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"不支援的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-zh-rTW/strings.xml b/core/res/res/values-mcc310-mnc380-zh-rTW/strings.xml new file mode 100644 index 000000000000..7a7f22534883 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-zh-rTW/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"未佈建的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"不支援的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc380-zu/strings.xml b/core/res/res/values-mcc310-mnc380-zu/strings.xml new file mode 100644 index 000000000000..e795a4698d23 --- /dev/null +++ b/core/res/res/values-mcc310-mnc380-zu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="6933439408719203102">"I-SIM ayinikezelwe MM#2"</string> + <string name="mmcc_illegal_ms" msgid="6367773216941648568">"I-SIM ayivunyelwe MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-af/strings.xml b/core/res/res/values-mcc310-mnc410-af/strings.xml new file mode 100644 index 000000000000..81688f1499dd --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-af/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM is nie opgestel nie MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM word nie toegelaat nie MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-am/strings.xml b/core/res/res/values-mcc310-mnc410-am/strings.xml new file mode 100644 index 000000000000..176a628d8ffc --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-am/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"ሲም አልቀረበም MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"ሲም አይፈቀድም MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-ar/strings.xml b/core/res/res/values-mcc310-mnc410-ar/strings.xml new file mode 100644 index 000000000000..884e18e9f4b6 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-ar/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"لم يتم توفير SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"غير مسموح باستخدام SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-az/strings.xml b/core/res/res/values-mcc310-mnc410-az/strings.xml new file mode 100644 index 000000000000..178451c696d7 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-az/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM MM#2 təmin etmir"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM MM#3 dəstəkləmir"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-b+sr+Latn/strings.xml b/core/res/res/values-mcc310-mnc410-b+sr+Latn/strings.xml new file mode 100644 index 000000000000..8981a35f7a00 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-b+sr+Latn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM kartica nije podešena MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM kartica nije dozvoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-be/strings.xml b/core/res/res/values-mcc310-mnc410-be/strings.xml new file mode 100644 index 000000000000..8ae86394e230 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-be/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM-карты няма MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM-карта не дапускаецца MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-bg/strings.xml b/core/res/res/values-mcc310-mnc410-bg/strings.xml new file mode 100644 index 000000000000..fc6f3e54065f --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-bg/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM картата не е обезпечена MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM картата не е разрешена MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-bn/strings.xml b/core/res/res/values-mcc310-mnc410-bn/strings.xml new file mode 100644 index 000000000000..e42a37516bcb --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-bn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"সিমের জন্য প্রস্তুত নয় MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"সিমের অনুমতি নেই MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-bs/strings.xml b/core/res/res/values-mcc310-mnc410-bs/strings.xml new file mode 100644 index 000000000000..4d7da3adf2ea --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-bs/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM kartica nije dodijeljena MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM kartica nije dozvoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-ca/strings.xml b/core/res/res/values-mcc310-mnc410-ca/strings.xml new file mode 100644 index 000000000000..19ab945b72f3 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-ca/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"La SIM no està proporcionada a MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"La SIM no és compatible a MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-cs/strings.xml b/core/res/res/values-mcc310-mnc410-cs/strings.xml new file mode 100644 index 000000000000..3e3632599607 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-cs/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM karta není poskytována (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM karta není povolena (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-da/strings.xml b/core/res/res/values-mcc310-mnc410-da/strings.xml new file mode 100644 index 000000000000..e99ab57f0f60 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-da/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM-kort leveres ikke MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM-kort er ikke tilladt MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-de/strings.xml b/core/res/res/values-mcc310-mnc410-de/strings.xml new file mode 100644 index 000000000000..c5f64f4a794a --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-de/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM-Karte nicht eingerichtet MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM-Karte nicht zulässig MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-el/strings.xml b/core/res/res/values-mcc310-mnc410-el/strings.xml new file mode 100644 index 000000000000..128d1bf75758 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-el/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"Δεν παρέχεται κάρτα SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"Η κάρτα SIM δεν επιτρέπεται MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-en-rAU/strings.xml b/core/res/res/values-mcc310-mnc410-en-rAU/strings.xml new file mode 100644 index 000000000000..eb563515d761 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-en-rAU/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-en-rCA/strings.xml b/core/res/res/values-mcc310-mnc410-en-rCA/strings.xml new file mode 100644 index 000000000000..eb563515d761 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-en-rCA/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-en-rGB/strings.xml b/core/res/res/values-mcc310-mnc410-en-rGB/strings.xml new file mode 100644 index 000000000000..eb563515d761 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-en-rGB/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-en-rIN/strings.xml b/core/res/res/values-mcc310-mnc410-en-rIN/strings.xml new file mode 100644 index 000000000000..eb563515d761 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-en-rIN/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-en-rXC/strings.xml b/core/res/res/values-mcc310-mnc410-en-rXC/strings.xml new file mode 100644 index 000000000000..4799e380e59d --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-en-rXC/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-es-rUS/strings.xml b/core/res/res/values-mcc310-mnc410-es-rUS/strings.xml new file mode 100644 index 000000000000..85b0344f46f1 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-es-rUS/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM no provista MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM no permitida MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-es/strings.xml b/core/res/res/values-mcc310-mnc410-es/strings.xml new file mode 100644 index 000000000000..248069e75637 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-es/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM no proporcionada (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM no admitida (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-et/strings.xml b/core/res/res/values-mcc310-mnc410-et/strings.xml new file mode 100644 index 000000000000..6ef78024b108 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-et/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM-kaart on ette valmistamata MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM-kaart pole lubatud MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-eu/strings.xml b/core/res/res/values-mcc310-mnc410-eu/strings.xml new file mode 100644 index 000000000000..966511bf575f --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-eu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"Ez dago SIM txartelik MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"Ez da onartzen SIM txartela MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-fa/strings.xml b/core/res/res/values-mcc310-mnc410-fa/strings.xml new file mode 100644 index 000000000000..82f6272c28f5 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-fa/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"سیمکارت مجوز لازم را ندارد MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"سیمکارت مجاز نیست MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-fi/strings.xml b/core/res/res/values-mcc310-mnc410-fi/strings.xml new file mode 100644 index 000000000000..c5a4ef68dc37 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-fi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM-kortti ei käyttäjien hallinnassa MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM-kortti estetty MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-fr-rCA/strings.xml b/core/res/res/values-mcc310-mnc410-fr-rCA/strings.xml new file mode 100644 index 000000000000..cec249125c9b --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-fr-rCA/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"Carte SIM non configurée, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"Carte SIM non autorisée, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-fr/strings.xml b/core/res/res/values-mcc310-mnc410-fr/strings.xml new file mode 100644 index 000000000000..f715e7106fc4 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-fr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"Carte SIM non provisionnée MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"Carte SIM non autorisée MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-gl/strings.xml b/core/res/res/values-mcc310-mnc410-gl/strings.xml new file mode 100644 index 000000000000..c3aba8e5c7b4 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-gl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"Non se introduciu ningunha tarxeta SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"Non se admite a tarxeta SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-gu/strings.xml b/core/res/res/values-mcc310-mnc410-gu/strings.xml new file mode 100644 index 000000000000..26898f40c973 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-gu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIMને MM#2ની જોગવાઈ નથી"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIMને MM#3 કરવાની મંજૂરી નથી"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-hi/strings.xml b/core/res/res/values-mcc310-mnc410-hi/strings.xml new file mode 100644 index 000000000000..a01845a2a827 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-hi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM काम नहीं कर रहा है MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM की अनुमति नहीं है MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-hr/strings.xml b/core/res/res/values-mcc310-mnc410-hr/strings.xml new file mode 100644 index 000000000000..47062c4d1bcf --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-hr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"Ne pruža se usluga za SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM nije dopušten MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-hu/strings.xml b/core/res/res/values-mcc310-mnc410-hu/strings.xml new file mode 100644 index 000000000000..194d86527705 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-hu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"Nem engedélyezett SIM-kártya (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"A SIM-kártya nem engedélyezett (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-hy/strings.xml b/core/res/res/values-mcc310-mnc410-hy/strings.xml new file mode 100644 index 000000000000..85129ccf109a --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-hy/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM քարտը նախապատրաստված չէ (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM քարտի օգտագործումն արգելված է (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-in/strings.xml b/core/res/res/values-mcc310-mnc410-in/strings.xml new file mode 100644 index 000000000000..c06522101bb9 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-in/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM tidak di-provisioning MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM tidak diizinkan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-is/strings.xml b/core/res/res/values-mcc310-mnc410-is/strings.xml new file mode 100644 index 000000000000..a40a6436dcba --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-is/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM-korti ekki úthlutað MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM-kort ekki leyft MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-it/strings.xml b/core/res/res/values-mcc310-mnc410-it/strings.xml new file mode 100644 index 000000000000..ab5c731f5328 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-it/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"Scheda SIM non predisposta MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"Scheda SIM non consentita MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-iw/strings.xml b/core/res/res/values-mcc310-mnc410-iw/strings.xml new file mode 100644 index 000000000000..b675f641bfbe --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-iw/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"כרטיס ה-SIM לא הופעל MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"כרטיס ה-SIM לא מורשה לשימוש ברשת הסלולרית MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-ja/strings.xml b/core/res/res/values-mcc310-mnc410-ja/strings.xml new file mode 100644 index 000000000000..1961a75b8aaf --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-ja/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM には対応していません(MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM は許可されていません(MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-ka/strings.xml b/core/res/res/values-mcc310-mnc410-ka/strings.xml new file mode 100644 index 000000000000..5216e8fdf414 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-ka/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM ბარათი უზრუნველყოფილი არ არის (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM ბარათი დაუშვებელია (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-kk/strings.xml b/core/res/res/values-mcc310-mnc410-kk/strings.xml new file mode 100644 index 000000000000..137c73a035f0 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-kk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM картасы қарастырылмаған MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM картасына рұқсат етілмеген MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-km/strings.xml b/core/res/res/values-mcc310-mnc410-km/strings.xml new file mode 100644 index 000000000000..94babe1cf507 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-km/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"ស៊ីមកាតមិនត្រូវបានផ្ដល់ជូនទេ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"មិនអនុញ្ញាតចំពោះស៊ីមកាតទេ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-kn/strings.xml b/core/res/res/values-mcc310-mnc410-kn/strings.xml new file mode 100644 index 000000000000..b003dcc21610 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-kn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"MM#2 ಗೆ ಸಿಮ್ ಸಿದ್ಧವಾಗಿಲ್ಲ"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"ಸಿಮ್ MM#3 ಅನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-ko/strings.xml b/core/res/res/values-mcc310-mnc410-ko/strings.xml new file mode 100644 index 000000000000..7824d1e6f300 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-ko/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM이 프로비저닝되지 않음 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM이 허용되지 않음 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-ky/strings.xml b/core/res/res/values-mcc310-mnc410-ky/strings.xml new file mode 100644 index 000000000000..9e4f23e77682 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-ky/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM карта таанылган жок (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM картаны колдонууга тыюу салынган (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-lo/strings.xml b/core/res/res/values-mcc310-mnc410-lo/strings.xml new file mode 100644 index 000000000000..9684e7a7a4c0 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-lo/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM ບໍ່ໄດ້ເປີດໃຊ້ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM ບໍ່ອະນຸຍາດ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-lt/strings.xml b/core/res/res/values-mcc310-mnc410-lt/strings.xml new file mode 100644 index 000000000000..c4a646a464dc --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-lt/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM kortelė neteikiama (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM kortelė neleidžiama (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-lv/strings.xml b/core/res/res/values-mcc310-mnc410-lv/strings.xml new file mode 100644 index 000000000000..e95d62b6a19d --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-lv/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM karte netiek nodrošināta: MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM karti nav atļauts izmantot: MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-mk/strings.xml b/core/res/res/values-mcc310-mnc410-mk/strings.xml new file mode 100644 index 000000000000..76bba961dc8f --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-mk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"Не е обезбедена SIM-картичка, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"Не е дозволена SIM-картичка, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-ml/strings.xml b/core/res/res/values-mcc310-mnc410-ml/strings.xml new file mode 100644 index 000000000000..94436bdfbef6 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-ml/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"സിം MM#2 പ്രൊവിഷൻ ചെയ്തിട്ടില്ല"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"സിം MM#3 അനുവദിച്ചിട്ടില്ല"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-mn/strings.xml b/core/res/res/values-mcc310-mnc410-mn/strings.xml new file mode 100644 index 000000000000..2667aab2f4dc --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-mn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM-г идэвхжүүлээгүй байна MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM-г зөвшөөрөөгүй байна MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-mr/strings.xml b/core/res/res/values-mcc310-mnc410-mr/strings.xml new file mode 100644 index 000000000000..e7b064463fb9 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-mr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM ने MM#2 ची तरतूद केलेली नाही"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM ने MM#3 ला परवानगी दिली नाही"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-ms/strings.xml b/core/res/res/values-mcc310-mnc410-ms/strings.xml new file mode 100644 index 000000000000..85b8621fcdfb --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-ms/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM tidak diperuntukkan MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM tidak dibenarkan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-my/strings.xml b/core/res/res/values-mcc310-mnc410-my/strings.xml new file mode 100644 index 000000000000..faa80ec6eac1 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-my/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"ဆင်းမ်ကို ထောက်ပံ့မထားပါ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"ဆင်းမ်ကို ခွင့်မပြုပါ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-nb/strings.xml b/core/res/res/values-mcc310-mnc410-nb/strings.xml new file mode 100644 index 000000000000..79be7afe0243 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-nb/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM-kortet er ikke klargjort, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM-kortet er ikke tillatt, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-ne/strings.xml b/core/res/res/values-mcc310-mnc410-ne/strings.xml new file mode 100644 index 000000000000..e270c7cff260 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-ne/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM को प्रावधान छैन MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM लाई अनुमति छैन MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-nl/strings.xml b/core/res/res/values-mcc310-mnc410-nl/strings.xml new file mode 100644 index 000000000000..2995beb25d0f --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-nl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"Simkaart niet geregistreerd MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"Simkaart niet toegestaan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-pa/strings.xml b/core/res/res/values-mcc310-mnc410-pa/strings.xml new file mode 100644 index 000000000000..70195f1b37b0 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-pa/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"ਸਿਮ ਦੀ ਵਿਵਸਥਾ ਨਹੀਂ ਹੈ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"ਸਿਮ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-pl/strings.xml b/core/res/res/values-mcc310-mnc410-pl/strings.xml new file mode 100644 index 000000000000..8677ad696a36 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-pl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"MM#2 – karta SIM nieobsługiwana"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"MM#3 – niedozwolona karta SIM"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-pt-rBR/strings.xml b/core/res/res/values-mcc310-mnc410-pt-rBR/strings.xml new file mode 100644 index 000000000000..4f41e5ead892 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-pt-rBR/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-pt-rPT/strings.xml b/core/res/res/values-mcc310-mnc410-pt-rPT/strings.xml new file mode 100644 index 000000000000..4f41e5ead892 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-pt-rPT/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-pt/strings.xml b/core/res/res/values-mcc310-mnc410-pt/strings.xml new file mode 100644 index 000000000000..4f41e5ead892 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-pt/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-ro/strings.xml b/core/res/res/values-mcc310-mnc410-ro/strings.xml new file mode 100644 index 000000000000..fea0609a2404 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-ro/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"Cardul SIM nu este activat MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"Cardul SIM nu este permis MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-ru/strings.xml b/core/res/res/values-mcc310-mnc410-ru/strings.xml new file mode 100644 index 000000000000..a00e59c3d056 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-ru/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM-карта не активирована (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"Использование SIM-карты запрещено (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-si/strings.xml b/core/res/res/values-mcc310-mnc410-si/strings.xml new file mode 100644 index 000000000000..8f66f3d80b8a --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-si/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM MM#2 ප්රතිපාදනය නොකරයි"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM MM#3 ඉඩ නොදේ"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-sk/strings.xml b/core/res/res/values-mcc310-mnc410-sk/strings.xml new file mode 100644 index 000000000000..e4d4bc6c7a4b --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-sk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM karta nie je k dispozícii – MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM karta je zakázaná – MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-sl/strings.xml b/core/res/res/values-mcc310-mnc410-sl/strings.xml new file mode 100644 index 000000000000..2d03b043832d --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-sl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"Kartica SIM ni omogočena za uporabo MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"Kartica SIM ni dovoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-sq/strings.xml b/core/res/res/values-mcc310-mnc410-sq/strings.xml new file mode 100644 index 000000000000..51626d777c48 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-sq/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"Karta SIM nuk është dhënë MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"Karta SIM nuk lejohet MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-sr/strings.xml b/core/res/res/values-mcc310-mnc410-sr/strings.xml new file mode 100644 index 000000000000..b4a9006de156 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-sr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM картица није подешена MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM картица није дозвољена MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-sv/strings.xml b/core/res/res/values-mcc310-mnc410-sv/strings.xml new file mode 100644 index 000000000000..c270b040a65b --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-sv/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM-kort tillhandahålls inte MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM-kort tillåts inte MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-sw/strings.xml b/core/res/res/values-mcc310-mnc410-sw/strings.xml new file mode 100644 index 000000000000..a6e601865bb9 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-sw/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM haitumiki MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM hairuhusiwi MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-ta/strings.xml b/core/res/res/values-mcc310-mnc410-ta/strings.xml new file mode 100644 index 000000000000..4ac46ced4101 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-ta/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"சிம் அமைக்கப்படவில்லை MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"சிம் அனுமதிக்கப்படவில்லை MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-te/strings.xml b/core/res/res/values-mcc310-mnc410-te/strings.xml new file mode 100644 index 000000000000..5b5643523810 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-te/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM MM#2ని సక్రియం చేయలేదు"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM MM#3ని అనుమతించలేదు"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-th/strings.xml b/core/res/res/values-mcc310-mnc410-th/strings.xml new file mode 100644 index 000000000000..cf510294a9dc --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-th/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"ไม่มีการจัดสรรซิม MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"ไม่อนุญาตให้ใช้ซิม MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-tl/strings.xml b/core/res/res/values-mcc310-mnc410-tl/strings.xml new file mode 100644 index 000000000000..b2aa68aee400 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-tl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"Hindi na-provision ang SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"Hindi pinapahintulutan ang SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-tr/strings.xml b/core/res/res/values-mcc310-mnc410-tr/strings.xml new file mode 100644 index 000000000000..9e5c38e37306 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-tr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM, MM#2\'nin temel hazırlığını yapamadı"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM MM#3\'e izin vermiyor"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-uk/strings.xml b/core/res/res/values-mcc310-mnc410-uk/strings.xml new file mode 100644 index 000000000000..5d74f802cf0f --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-uk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM-карту не надано (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM-карта заборонена (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-ur/strings.xml b/core/res/res/values-mcc310-mnc410-ur/strings.xml new file mode 100644 index 000000000000..8cf16e499c40 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-ur/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM فراہم کردہ نہیں ہے MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM کی اجازت نہیں ہے MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-uz/strings.xml b/core/res/res/values-mcc310-mnc410-uz/strings.xml new file mode 100644 index 000000000000..46185253e1a3 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-uz/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM karta ishlatish taqiqlangan (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM karta ishlatish taqiqlangan (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-vi/strings.xml b/core/res/res/values-mcc310-mnc410-vi/strings.xml new file mode 100644 index 000000000000..e6fc334aed11 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-vi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"SIM không được cấp phép MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"SIM không được phép MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-zh-rCN/strings.xml b/core/res/res/values-mcc310-mnc410-zh-rCN/strings.xml new file mode 100644 index 000000000000..a00316ab2aae --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-zh-rCN/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"未配置的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"不被允许的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-zh-rHK/strings.xml b/core/res/res/values-mcc310-mnc410-zh-rHK/strings.xml new file mode 100644 index 000000000000..66a622e24219 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-zh-rHK/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"未佈建的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"不支援的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-zh-rTW/strings.xml b/core/res/res/values-mcc310-mnc410-zh-rTW/strings.xml new file mode 100644 index 000000000000..66a622e24219 --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-zh-rTW/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"未佈建的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"不支援的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc410-zu/strings.xml b/core/res/res/values-mcc310-mnc410-zu/strings.xml new file mode 100644 index 000000000000..a52049f8f3ee --- /dev/null +++ b/core/res/res/values-mcc310-mnc410-zu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="376893116792604964">"I-SIM ayinikezelwe MM#2"</string> + <string name="mmcc_illegal_ms" msgid="1593063035884873292">"I-SIM ayivunyelwe MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-af/strings.xml b/core/res/res/values-mcc310-mnc560-af/strings.xml new file mode 100644 index 000000000000..ecbb954f5e11 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-af/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM is nie opgestel nie MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM word nie toegelaat nie MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-am/strings.xml b/core/res/res/values-mcc310-mnc560-am/strings.xml new file mode 100644 index 000000000000..297c05955aff --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-am/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"ሲም አልቀረበም MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"ሲም አይፈቀድም MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-ar/strings.xml b/core/res/res/values-mcc310-mnc560-ar/strings.xml new file mode 100644 index 000000000000..12a06faef06e --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-ar/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"لم يتم توفير SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"غير مسموح باستخدام SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-az/strings.xml b/core/res/res/values-mcc310-mnc560-az/strings.xml new file mode 100644 index 000000000000..9acc2c117943 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-az/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM MM#2 təmin etmir"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM MM#3 dəstəkləmir"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-b+sr+Latn/strings.xml b/core/res/res/values-mcc310-mnc560-b+sr+Latn/strings.xml new file mode 100644 index 000000000000..616f87151dff --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-b+sr+Latn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM kartica nije podešena MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM kartica nije dozvoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-be/strings.xml b/core/res/res/values-mcc310-mnc560-be/strings.xml new file mode 100644 index 000000000000..0e70cf278ce1 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-be/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM-карты няма MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM-карта не дапускаецца MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-bg/strings.xml b/core/res/res/values-mcc310-mnc560-bg/strings.xml new file mode 100644 index 000000000000..49c2d2fcedd4 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-bg/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM картата не е обезпечена MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM картата не е разрешена MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-bn/strings.xml b/core/res/res/values-mcc310-mnc560-bn/strings.xml new file mode 100644 index 000000000000..438791d1e760 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-bn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"সিমের জন্য প্রস্তুত নয় MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"সিমের অনুমতি নেই MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-bs/strings.xml b/core/res/res/values-mcc310-mnc560-bs/strings.xml new file mode 100644 index 000000000000..82046a6633e7 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-bs/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM kartica nije dodijeljena MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM kartica nije dozvoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-ca/strings.xml b/core/res/res/values-mcc310-mnc560-ca/strings.xml new file mode 100644 index 000000000000..1eac589a8f36 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-ca/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"La SIM no està proporcionada a MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"La SIM no és compatible a MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-cs/strings.xml b/core/res/res/values-mcc310-mnc560-cs/strings.xml new file mode 100644 index 000000000000..4701f99349a8 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-cs/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM karta není poskytována (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM karta není povolena (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-da/strings.xml b/core/res/res/values-mcc310-mnc560-da/strings.xml new file mode 100644 index 000000000000..2c63d87af24f --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-da/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM-kort leveres ikke MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM-kort er ikke tilladt MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-de/strings.xml b/core/res/res/values-mcc310-mnc560-de/strings.xml new file mode 100644 index 000000000000..e8fec2cb68ba --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-de/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM-Karte nicht eingerichtet MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM-Karte nicht zulässig MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-el/strings.xml b/core/res/res/values-mcc310-mnc560-el/strings.xml new file mode 100644 index 000000000000..efd81f73c0e8 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-el/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"Δεν παρέχεται κάρτα SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"Η κάρτα SIM δεν επιτρέπεται MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-en-rAU/strings.xml b/core/res/res/values-mcc310-mnc560-en-rAU/strings.xml new file mode 100644 index 000000000000..c218c646f19c --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-en-rAU/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-en-rCA/strings.xml b/core/res/res/values-mcc310-mnc560-en-rCA/strings.xml new file mode 100644 index 000000000000..c218c646f19c --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-en-rCA/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-en-rGB/strings.xml b/core/res/res/values-mcc310-mnc560-en-rGB/strings.xml new file mode 100644 index 000000000000..c218c646f19c --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-en-rGB/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-en-rIN/strings.xml b/core/res/res/values-mcc310-mnc560-en-rIN/strings.xml new file mode 100644 index 000000000000..c218c646f19c --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-en-rIN/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-en-rXC/strings.xml b/core/res/res/values-mcc310-mnc560-en-rXC/strings.xml new file mode 100644 index 000000000000..67c05b2af25b --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-en-rXC/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-es-rUS/strings.xml b/core/res/res/values-mcc310-mnc560-es-rUS/strings.xml new file mode 100644 index 000000000000..62d61baac32d --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-es-rUS/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM no provista MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM no permitida MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-es/strings.xml b/core/res/res/values-mcc310-mnc560-es/strings.xml new file mode 100644 index 000000000000..dbd71d5c1099 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-es/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM no proporcionada (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM no admitida (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-et/strings.xml b/core/res/res/values-mcc310-mnc560-et/strings.xml new file mode 100644 index 000000000000..b269ace5c429 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-et/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM-kaart on ette valmistamata MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM-kaart pole lubatud MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-eu/strings.xml b/core/res/res/values-mcc310-mnc560-eu/strings.xml new file mode 100644 index 000000000000..cee010604499 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-eu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"Ez dago SIM txartelik MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"Ez da onartzen SIM txartela MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-fa/strings.xml b/core/res/res/values-mcc310-mnc560-fa/strings.xml new file mode 100644 index 000000000000..b4683c76f7bc --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-fa/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"سیمکارت مجوز لازم را ندارد MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"سیمکارت مجاز نیست MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-fi/strings.xml b/core/res/res/values-mcc310-mnc560-fi/strings.xml new file mode 100644 index 000000000000..54c80edea39a --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-fi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM-kortti ei käyttäjien hallinnassa MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM-kortti estetty MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-fr-rCA/strings.xml b/core/res/res/values-mcc310-mnc560-fr-rCA/strings.xml new file mode 100644 index 000000000000..8b6c4ec108ad --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-fr-rCA/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"Carte SIM non configurée, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"Carte SIM non autorisée, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-fr/strings.xml b/core/res/res/values-mcc310-mnc560-fr/strings.xml new file mode 100644 index 000000000000..b52eaf72b28d --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-fr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"Carte SIM non provisionnée MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"Carte SIM non autorisée MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-gl/strings.xml b/core/res/res/values-mcc310-mnc560-gl/strings.xml new file mode 100644 index 000000000000..a8c04d269f2a --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-gl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"Non se introduciu ningunha tarxeta SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"Non se admite a tarxeta SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-gu/strings.xml b/core/res/res/values-mcc310-mnc560-gu/strings.xml new file mode 100644 index 000000000000..c3892da4f02d --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-gu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIMને MM#2ની જોગવાઈ નથી"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIMને MM#3 કરવાની મંજૂરી નથી"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-hi/strings.xml b/core/res/res/values-mcc310-mnc560-hi/strings.xml new file mode 100644 index 000000000000..4e07e4f1c464 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-hi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM काम नहीं कर रहा है MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM की अनुमति नहीं है MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-hr/strings.xml b/core/res/res/values-mcc310-mnc560-hr/strings.xml new file mode 100644 index 000000000000..dc6653edcf04 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-hr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"Ne pruža se usluga za SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM nije dopušten MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-hu/strings.xml b/core/res/res/values-mcc310-mnc560-hu/strings.xml new file mode 100644 index 000000000000..1a7a6b3fb026 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-hu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"Nem engedélyezett SIM-kártya (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"A SIM-kártya nem engedélyezett (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-hy/strings.xml b/core/res/res/values-mcc310-mnc560-hy/strings.xml new file mode 100644 index 000000000000..c3988772f29b --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-hy/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM քարտը նախապատրաստված չէ (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM քարտի օգտագործումն արգելված է (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-in/strings.xml b/core/res/res/values-mcc310-mnc560-in/strings.xml new file mode 100644 index 000000000000..c3c7df38c413 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-in/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM tidak di-provisioning MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM tidak diizinkan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-is/strings.xml b/core/res/res/values-mcc310-mnc560-is/strings.xml new file mode 100644 index 000000000000..4a59abd5d9dd --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-is/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM-korti ekki úthlutað MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM-kort ekki leyft MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-it/strings.xml b/core/res/res/values-mcc310-mnc560-it/strings.xml new file mode 100644 index 000000000000..d2c966c17fc4 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-it/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"Scheda SIM non predisposta MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"Scheda SIM non consentita MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-iw/strings.xml b/core/res/res/values-mcc310-mnc560-iw/strings.xml new file mode 100644 index 000000000000..68f0aa92d055 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-iw/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"כרטיס ה-SIM לא הופעל MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"כרטיס ה-SIM לא מורשה לשימוש ברשת הסלולרית MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-ja/strings.xml b/core/res/res/values-mcc310-mnc560-ja/strings.xml new file mode 100644 index 000000000000..04299967e8e8 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-ja/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM には対応していません(MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM は許可されていません(MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-ka/strings.xml b/core/res/res/values-mcc310-mnc560-ka/strings.xml new file mode 100644 index 000000000000..b0371f015b5b --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-ka/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM ბარათი უზრუნველყოფილი არ არის (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM ბარათი დაუშვებელია (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-kk/strings.xml b/core/res/res/values-mcc310-mnc560-kk/strings.xml new file mode 100644 index 000000000000..2015f8cdfbea --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-kk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM картасы қарастырылмаған MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM картасына рұқсат етілмеген MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-km/strings.xml b/core/res/res/values-mcc310-mnc560-km/strings.xml new file mode 100644 index 000000000000..a13ca7d59f8b --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-km/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"ស៊ីមកាតមិនត្រូវបានផ្ដល់ជូនទេ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"មិនអនុញ្ញាតចំពោះស៊ីមកាតទេ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-kn/strings.xml b/core/res/res/values-mcc310-mnc560-kn/strings.xml new file mode 100644 index 000000000000..da759046c41e --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-kn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"MM#2 ಗೆ ಸಿಮ್ ಸಿದ್ಧವಾಗಿಲ್ಲ"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"ಸಿಮ್ MM#3 ಅನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-ko/strings.xml b/core/res/res/values-mcc310-mnc560-ko/strings.xml new file mode 100644 index 000000000000..ee71a09c9f56 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-ko/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM이 프로비저닝되지 않음 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM이 허용되지 않음 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-ky/strings.xml b/core/res/res/values-mcc310-mnc560-ky/strings.xml new file mode 100644 index 000000000000..856bebc839c6 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-ky/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM карта таанылган жок (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM картаны колдонууга тыюу салынган (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-lo/strings.xml b/core/res/res/values-mcc310-mnc560-lo/strings.xml new file mode 100644 index 000000000000..702470ee5040 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-lo/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM ບໍ່ໄດ້ເປີດໃຊ້ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM ບໍ່ອະນຸຍາດ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-lt/strings.xml b/core/res/res/values-mcc310-mnc560-lt/strings.xml new file mode 100644 index 000000000000..c3c5a9ea27cd --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-lt/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM kortelė neteikiama (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM kortelė neleidžiama (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-lv/strings.xml b/core/res/res/values-mcc310-mnc560-lv/strings.xml new file mode 100644 index 000000000000..dcf780569cb2 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-lv/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM karte netiek nodrošināta: MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM karti nav atļauts izmantot: MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-mk/strings.xml b/core/res/res/values-mcc310-mnc560-mk/strings.xml new file mode 100644 index 000000000000..cf0ae7e30c97 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-mk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"Не е обезбедена SIM-картичка, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"Не е дозволена SIM-картичка, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-ml/strings.xml b/core/res/res/values-mcc310-mnc560-ml/strings.xml new file mode 100644 index 000000000000..fb506bfd3ac1 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-ml/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"സിം MM#2 പ്രൊവിഷൻ ചെയ്തിട്ടില്ല"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"സിം MM#3 അനുവദിച്ചിട്ടില്ല"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-mn/strings.xml b/core/res/res/values-mcc310-mnc560-mn/strings.xml new file mode 100644 index 000000000000..0bf159954c5a --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-mn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM-г идэвхжүүлээгүй байна MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM-г зөвшөөрөөгүй байна MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-mr/strings.xml b/core/res/res/values-mcc310-mnc560-mr/strings.xml new file mode 100644 index 000000000000..69e81adbd83a --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-mr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM ने MM#2 ची तरतूद केलेली नाही"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM ने MM#3 ला परवानगी दिली नाही"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-ms/strings.xml b/core/res/res/values-mcc310-mnc560-ms/strings.xml new file mode 100644 index 000000000000..cd0aed706605 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-ms/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM tidak diperuntukkan MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM tidak dibenarkan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-my/strings.xml b/core/res/res/values-mcc310-mnc560-my/strings.xml new file mode 100644 index 000000000000..58fba8786060 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-my/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"ဆင်းမ်ကို ထောက်ပံ့မထားပါ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"ဆင်းမ်ကို ခွင့်မပြုပါ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-nb/strings.xml b/core/res/res/values-mcc310-mnc560-nb/strings.xml new file mode 100644 index 000000000000..bc90ae17751f --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-nb/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM-kortet er ikke klargjort, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM-kortet er ikke tillatt, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-ne/strings.xml b/core/res/res/values-mcc310-mnc560-ne/strings.xml new file mode 100644 index 000000000000..75c493dc80d7 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-ne/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM को प्रावधान छैन MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM लाई अनुमति छैन MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-nl/strings.xml b/core/res/res/values-mcc310-mnc560-nl/strings.xml new file mode 100644 index 000000000000..7241627c0f4b --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-nl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"Simkaart niet geregistreerd MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"Simkaart niet toegestaan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-pa/strings.xml b/core/res/res/values-mcc310-mnc560-pa/strings.xml new file mode 100644 index 000000000000..a2b76be1e7fe --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-pa/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"ਸਿਮ ਦੀ ਵਿਵਸਥਾ ਨਹੀਂ ਹੈ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"ਸਿਮ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-pl/strings.xml b/core/res/res/values-mcc310-mnc560-pl/strings.xml new file mode 100644 index 000000000000..f844db6f7688 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-pl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"MM#2 – karta SIM nieobsługiwana"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"MM#3 – niedozwolona karta SIM"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-pt-rBR/strings.xml b/core/res/res/values-mcc310-mnc560-pt-rBR/strings.xml new file mode 100644 index 000000000000..4c10ef9f552e --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-pt-rBR/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-pt-rPT/strings.xml b/core/res/res/values-mcc310-mnc560-pt-rPT/strings.xml new file mode 100644 index 000000000000..4c10ef9f552e --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-pt-rPT/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-pt/strings.xml b/core/res/res/values-mcc310-mnc560-pt/strings.xml new file mode 100644 index 000000000000..4c10ef9f552e --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-pt/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-ro/strings.xml b/core/res/res/values-mcc310-mnc560-ro/strings.xml new file mode 100644 index 000000000000..e24b74c0a024 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-ro/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"Cardul SIM nu este activat MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"Cardul SIM nu este permis MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-ru/strings.xml b/core/res/res/values-mcc310-mnc560-ru/strings.xml new file mode 100644 index 000000000000..35bf36f8b407 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-ru/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM-карта не активирована (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"Использование SIM-карты запрещено (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-si/strings.xml b/core/res/res/values-mcc310-mnc560-si/strings.xml new file mode 100644 index 000000000000..4c60ce49f6db --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-si/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM MM#2 ප්රතිපාදනය නොකරයි"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM MM#3 ඉඩ නොදේ"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-sk/strings.xml b/core/res/res/values-mcc310-mnc560-sk/strings.xml new file mode 100644 index 000000000000..ad4aba481525 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-sk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM karta nie je k dispozícii – MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM karta je zakázaná – MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-sl/strings.xml b/core/res/res/values-mcc310-mnc560-sl/strings.xml new file mode 100644 index 000000000000..78559875ac44 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-sl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"Kartica SIM ni omogočena za uporabo MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"Kartica SIM ni dovoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-sq/strings.xml b/core/res/res/values-mcc310-mnc560-sq/strings.xml new file mode 100644 index 000000000000..527430e155fe --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-sq/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"Karta SIM nuk është dhënë MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"Karta SIM nuk lejohet MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-sr/strings.xml b/core/res/res/values-mcc310-mnc560-sr/strings.xml new file mode 100644 index 000000000000..ec5a2b6e5991 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-sr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM картица није подешена MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM картица није дозвољена MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-sv/strings.xml b/core/res/res/values-mcc310-mnc560-sv/strings.xml new file mode 100644 index 000000000000..d1139893ec33 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-sv/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM-kort tillhandahålls inte MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM-kort tillåts inte MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-sw/strings.xml b/core/res/res/values-mcc310-mnc560-sw/strings.xml new file mode 100644 index 000000000000..4e3df8b93958 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-sw/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM haitumiki MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM hairuhusiwi MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-ta/strings.xml b/core/res/res/values-mcc310-mnc560-ta/strings.xml new file mode 100644 index 000000000000..78f824383ec0 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-ta/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"சிம் அமைக்கப்படவில்லை MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"சிம் அனுமதிக்கப்படவில்லை MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-te/strings.xml b/core/res/res/values-mcc310-mnc560-te/strings.xml new file mode 100644 index 000000000000..aeda9416d09a --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-te/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM MM#2ని సక్రియం చేయలేదు"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM MM#3ని అనుమతించలేదు"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-th/strings.xml b/core/res/res/values-mcc310-mnc560-th/strings.xml new file mode 100644 index 000000000000..7896973998bf --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-th/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"ไม่มีการจัดสรรซิม MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"ไม่อนุญาตให้ใช้ซิม MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-tl/strings.xml b/core/res/res/values-mcc310-mnc560-tl/strings.xml new file mode 100644 index 000000000000..ac87cb5a079d --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-tl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"Hindi na-provision ang SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"Hindi pinapahintulutan ang SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-tr/strings.xml b/core/res/res/values-mcc310-mnc560-tr/strings.xml new file mode 100644 index 000000000000..5ea1d80f2acc --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-tr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM, MM#2\'nin temel hazırlığını yapamadı"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM MM#3\'e izin vermiyor"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-uk/strings.xml b/core/res/res/values-mcc310-mnc560-uk/strings.xml new file mode 100644 index 000000000000..7ee6b88fc843 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-uk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM-карту не надано (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM-карта заборонена (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-ur/strings.xml b/core/res/res/values-mcc310-mnc560-ur/strings.xml new file mode 100644 index 000000000000..609d3e8c6717 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-ur/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM فراہم کردہ نہیں ہے MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM کی اجازت نہیں ہے MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-uz/strings.xml b/core/res/res/values-mcc310-mnc560-uz/strings.xml new file mode 100644 index 000000000000..41570415fe4f --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-uz/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM karta ishlatish taqiqlangan (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM karta ishlatish taqiqlangan (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-vi/strings.xml b/core/res/res/values-mcc310-mnc560-vi/strings.xml new file mode 100644 index 000000000000..b2284e1a40b1 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-vi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"SIM không được cấp phép MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"SIM không được phép MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-zh-rCN/strings.xml b/core/res/res/values-mcc310-mnc560-zh-rCN/strings.xml new file mode 100644 index 000000000000..050ea01aeae4 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-zh-rCN/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"未配置的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"不被允许的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-zh-rHK/strings.xml b/core/res/res/values-mcc310-mnc560-zh-rHK/strings.xml new file mode 100644 index 000000000000..43cfc016cb24 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-zh-rHK/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"未佈建的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"不支援的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-zh-rTW/strings.xml b/core/res/res/values-mcc310-mnc560-zh-rTW/strings.xml new file mode 100644 index 000000000000..43cfc016cb24 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-zh-rTW/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"未佈建的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"不支援的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc560-zu/strings.xml b/core/res/res/values-mcc310-mnc560-zu/strings.xml new file mode 100644 index 000000000000..e1b7abb80751 --- /dev/null +++ b/core/res/res/values-mcc310-mnc560-zu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="2976453378311251765">"I-SIM ayinikezelwe MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2519618694918727742">"I-SIM ayivunyelwe MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-af/strings.xml b/core/res/res/values-mcc310-mnc950-af/strings.xml new file mode 100644 index 000000000000..19ae78d584d8 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-af/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM is nie opgestel nie MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM word nie toegelaat nie MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-am/strings.xml b/core/res/res/values-mcc310-mnc950-am/strings.xml new file mode 100644 index 000000000000..e81745d04ea8 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-am/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"ሲም አልቀረበም MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"ሲም አይፈቀድም MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-ar/strings.xml b/core/res/res/values-mcc310-mnc950-ar/strings.xml new file mode 100644 index 000000000000..1aab01c3ef76 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-ar/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"لم يتم توفير SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"غير مسموح باستخدام SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-az/strings.xml b/core/res/res/values-mcc310-mnc950-az/strings.xml new file mode 100644 index 000000000000..26d91ef2effa --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-az/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM MM#2 təmin etmir"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM MM#3 dəstəkləmir"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-b+sr+Latn/strings.xml b/core/res/res/values-mcc310-mnc950-b+sr+Latn/strings.xml new file mode 100644 index 000000000000..44c5d1930d71 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-b+sr+Latn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM kartica nije podešena MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM kartica nije dozvoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-be/strings.xml b/core/res/res/values-mcc310-mnc950-be/strings.xml new file mode 100644 index 000000000000..2bae8c42ede3 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-be/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM-карты няма MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM-карта не дапускаецца MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-bg/strings.xml b/core/res/res/values-mcc310-mnc950-bg/strings.xml new file mode 100644 index 000000000000..761b43923dd7 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-bg/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM картата не е обезпечена MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM картата не е разрешена MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-bn/strings.xml b/core/res/res/values-mcc310-mnc950-bn/strings.xml new file mode 100644 index 000000000000..32ba8b87cd48 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-bn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"সিমের জন্য প্রস্তুত নয় MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"সিমের অনুমতি নেই MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-bs/strings.xml b/core/res/res/values-mcc310-mnc950-bs/strings.xml new file mode 100644 index 000000000000..b06b586f4b6a --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-bs/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM kartica nije dodijeljena MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM kartica nije dozvoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-ca/strings.xml b/core/res/res/values-mcc310-mnc950-ca/strings.xml new file mode 100644 index 000000000000..9b77ce77296b --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-ca/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"La SIM no està proporcionada a MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"La SIM no és compatible a MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-cs/strings.xml b/core/res/res/values-mcc310-mnc950-cs/strings.xml new file mode 100644 index 000000000000..3f8b8aa48d4a --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-cs/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM karta není poskytována (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM karta není povolena (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-da/strings.xml b/core/res/res/values-mcc310-mnc950-da/strings.xml new file mode 100644 index 000000000000..6cd830682f64 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-da/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM-kort leveres ikke MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM-kort er ikke tilladt MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-de/strings.xml b/core/res/res/values-mcc310-mnc950-de/strings.xml new file mode 100644 index 000000000000..70e3068ccfc3 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-de/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM-Karte nicht eingerichtet MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM-Karte nicht zulässig MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-el/strings.xml b/core/res/res/values-mcc310-mnc950-el/strings.xml new file mode 100644 index 000000000000..1a2542cf9895 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-el/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"Δεν παρέχεται κάρτα SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"Η κάρτα SIM δεν επιτρέπεται MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-en-rAU/strings.xml b/core/res/res/values-mcc310-mnc950-en-rAU/strings.xml new file mode 100644 index 000000000000..7ef660523838 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-en-rAU/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-en-rCA/strings.xml b/core/res/res/values-mcc310-mnc950-en-rCA/strings.xml new file mode 100644 index 000000000000..7ef660523838 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-en-rCA/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-en-rGB/strings.xml b/core/res/res/values-mcc310-mnc950-en-rGB/strings.xml new file mode 100644 index 000000000000..7ef660523838 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-en-rGB/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-en-rIN/strings.xml b/core/res/res/values-mcc310-mnc950-en-rIN/strings.xml new file mode 100644 index 000000000000..7ef660523838 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-en-rIN/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-en-rXC/strings.xml b/core/res/res/values-mcc310-mnc950-en-rXC/strings.xml new file mode 100644 index 000000000000..243d73186532 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-en-rXC/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-es-rUS/strings.xml b/core/res/res/values-mcc310-mnc950-es-rUS/strings.xml new file mode 100644 index 000000000000..31a863c26b62 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-es-rUS/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM no provista MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM no permitida MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-es/strings.xml b/core/res/res/values-mcc310-mnc950-es/strings.xml new file mode 100644 index 000000000000..ba8c78b2c6b8 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-es/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM no proporcionada (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM no admitida (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-et/strings.xml b/core/res/res/values-mcc310-mnc950-et/strings.xml new file mode 100644 index 000000000000..013243a3de95 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-et/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM-kaart on ette valmistamata MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM-kaart pole lubatud MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-eu/strings.xml b/core/res/res/values-mcc310-mnc950-eu/strings.xml new file mode 100644 index 000000000000..097e423ae883 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-eu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"Ez dago SIM txartelik MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"Ez da onartzen SIM txartela MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-fa/strings.xml b/core/res/res/values-mcc310-mnc950-fa/strings.xml new file mode 100644 index 000000000000..3281bb540f4f --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-fa/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"سیمکارت مجوز لازم را ندارد MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"سیمکارت مجاز نیست MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-fi/strings.xml b/core/res/res/values-mcc310-mnc950-fi/strings.xml new file mode 100644 index 000000000000..01e04f7c57c2 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-fi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM-kortti ei käyttäjien hallinnassa MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM-kortti estetty MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-fr-rCA/strings.xml b/core/res/res/values-mcc310-mnc950-fr-rCA/strings.xml new file mode 100644 index 000000000000..a310f82d70fd --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-fr-rCA/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"Carte SIM non configurée, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"Carte SIM non autorisée, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-fr/strings.xml b/core/res/res/values-mcc310-mnc950-fr/strings.xml new file mode 100644 index 000000000000..7b0fb2ca5a15 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-fr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"Carte SIM non provisionnée MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"Carte SIM non autorisée MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-gl/strings.xml b/core/res/res/values-mcc310-mnc950-gl/strings.xml new file mode 100644 index 000000000000..55ff461037a1 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-gl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"Non se introduciu ningunha tarxeta SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"Non se admite a tarxeta SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-gu/strings.xml b/core/res/res/values-mcc310-mnc950-gu/strings.xml new file mode 100644 index 000000000000..a6e1a83bbef6 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-gu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIMને MM#2ની જોગવાઈ નથી"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIMને MM#3 કરવાની મંજૂરી નથી"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-hi/strings.xml b/core/res/res/values-mcc310-mnc950-hi/strings.xml new file mode 100644 index 000000000000..41b9bc92e45d --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-hi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM काम नहीं कर रहा है MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM की अनुमति नहीं है MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-hr/strings.xml b/core/res/res/values-mcc310-mnc950-hr/strings.xml new file mode 100644 index 000000000000..1c39a0944f75 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-hr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"Ne pruža se usluga za SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM nije dopušten MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-hu/strings.xml b/core/res/res/values-mcc310-mnc950-hu/strings.xml new file mode 100644 index 000000000000..6b8ee76d4c97 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-hu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"Nem engedélyezett SIM-kártya (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"A SIM-kártya nem engedélyezett (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-hy/strings.xml b/core/res/res/values-mcc310-mnc950-hy/strings.xml new file mode 100644 index 000000000000..63dfa4604458 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-hy/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM քարտը նախապատրաստված չէ (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM քարտի օգտագործումն արգելված է (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-in/strings.xml b/core/res/res/values-mcc310-mnc950-in/strings.xml new file mode 100644 index 000000000000..a7c0232707ea --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-in/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM tidak di-provisioning MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM tidak diizinkan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-is/strings.xml b/core/res/res/values-mcc310-mnc950-is/strings.xml new file mode 100644 index 000000000000..ceee15aa09d3 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-is/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM-korti ekki úthlutað MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM-kort ekki leyft MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-it/strings.xml b/core/res/res/values-mcc310-mnc950-it/strings.xml new file mode 100644 index 000000000000..21e2a4a46f63 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-it/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"Scheda SIM non predisposta MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"Scheda SIM non consentita MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-iw/strings.xml b/core/res/res/values-mcc310-mnc950-iw/strings.xml new file mode 100644 index 000000000000..041408fc0347 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-iw/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"כרטיס ה-SIM לא הופעל MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"כרטיס ה-SIM לא מורשה לשימוש ברשת הסלולרית MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-ja/strings.xml b/core/res/res/values-mcc310-mnc950-ja/strings.xml new file mode 100644 index 000000000000..97f697e99d9c --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-ja/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM には対応していません(MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM は許可されていません(MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-ka/strings.xml b/core/res/res/values-mcc310-mnc950-ka/strings.xml new file mode 100644 index 000000000000..4d8c8a81ccbc --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-ka/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM ბარათი უზრუნველყოფილი არ არის (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM ბარათი დაუშვებელია (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-kk/strings.xml b/core/res/res/values-mcc310-mnc950-kk/strings.xml new file mode 100644 index 000000000000..899a9a273978 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-kk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM картасы қарастырылмаған MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM картасына рұқсат етілмеген MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-km/strings.xml b/core/res/res/values-mcc310-mnc950-km/strings.xml new file mode 100644 index 000000000000..3c80d9f3c93b --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-km/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"ស៊ីមកាតមិនត្រូវបានផ្ដល់ជូនទេ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"មិនអនុញ្ញាតចំពោះស៊ីមកាតទេ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-kn/strings.xml b/core/res/res/values-mcc310-mnc950-kn/strings.xml new file mode 100644 index 000000000000..1c7ab200f5b2 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-kn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"MM#2 ಗೆ ಸಿಮ್ ಸಿದ್ಧವಾಗಿಲ್ಲ"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"ಸಿಮ್ MM#3 ಅನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-ko/strings.xml b/core/res/res/values-mcc310-mnc950-ko/strings.xml new file mode 100644 index 000000000000..2419c2aa16ac --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-ko/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM이 프로비저닝되지 않음 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM이 허용되지 않음 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-ky/strings.xml b/core/res/res/values-mcc310-mnc950-ky/strings.xml new file mode 100644 index 000000000000..2583338924da --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-ky/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM карта таанылган жок (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM картаны колдонууга тыюу салынган (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-lo/strings.xml b/core/res/res/values-mcc310-mnc950-lo/strings.xml new file mode 100644 index 000000000000..b69536f9e392 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-lo/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM ບໍ່ໄດ້ເປີດໃຊ້ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM ບໍ່ອະນຸຍາດ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-lt/strings.xml b/core/res/res/values-mcc310-mnc950-lt/strings.xml new file mode 100644 index 000000000000..8ef0869b81a0 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-lt/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM kortelė neteikiama (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM kortelė neleidžiama (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-lv/strings.xml b/core/res/res/values-mcc310-mnc950-lv/strings.xml new file mode 100644 index 000000000000..2a491c0e75e0 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-lv/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM karte netiek nodrošināta: MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM karti nav atļauts izmantot: MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-mk/strings.xml b/core/res/res/values-mcc310-mnc950-mk/strings.xml new file mode 100644 index 000000000000..a1da44b72b10 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-mk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"Не е обезбедена SIM-картичка, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"Не е дозволена SIM-картичка, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-ml/strings.xml b/core/res/res/values-mcc310-mnc950-ml/strings.xml new file mode 100644 index 000000000000..0079c08ef7e8 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-ml/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"സിം MM#2 പ്രൊവിഷൻ ചെയ്തിട്ടില്ല"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"സിം MM#3 അനുവദിച്ചിട്ടില്ല"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-mn/strings.xml b/core/res/res/values-mcc310-mnc950-mn/strings.xml new file mode 100644 index 000000000000..2d4b5f53a442 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-mn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM-г идэвхжүүлээгүй байна MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM-г зөвшөөрөөгүй байна MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-mr/strings.xml b/core/res/res/values-mcc310-mnc950-mr/strings.xml new file mode 100644 index 000000000000..eca7dcaf12a3 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-mr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM ने MM#2 ची तरतूद केलेली नाही"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM ने MM#3 ला परवानगी दिली नाही"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-ms/strings.xml b/core/res/res/values-mcc310-mnc950-ms/strings.xml new file mode 100644 index 000000000000..4f5c7810dbac --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-ms/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM tidak diperuntukkan MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM tidak dibenarkan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-my/strings.xml b/core/res/res/values-mcc310-mnc950-my/strings.xml new file mode 100644 index 000000000000..ecf9f61ba0fb --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-my/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"ဆင်းမ်ကို ထောက်ပံ့မထားပါ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"ဆင်းမ်ကို ခွင့်မပြုပါ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-nb/strings.xml b/core/res/res/values-mcc310-mnc950-nb/strings.xml new file mode 100644 index 000000000000..907482edda8a --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-nb/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM-kortet er ikke klargjort, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM-kortet er ikke tillatt, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-ne/strings.xml b/core/res/res/values-mcc310-mnc950-ne/strings.xml new file mode 100644 index 000000000000..380f01c46c4f --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-ne/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM को प्रावधान छैन MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM लाई अनुमति छैन MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-nl/strings.xml b/core/res/res/values-mcc310-mnc950-nl/strings.xml new file mode 100644 index 000000000000..a01896cab40e --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-nl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"Simkaart niet geregistreerd MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"Simkaart niet toegestaan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-pa/strings.xml b/core/res/res/values-mcc310-mnc950-pa/strings.xml new file mode 100644 index 000000000000..a67b0fb9acc0 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-pa/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"ਸਿਮ ਦੀ ਵਿਵਸਥਾ ਨਹੀਂ ਹੈ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"ਸਿਮ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-pl/strings.xml b/core/res/res/values-mcc310-mnc950-pl/strings.xml new file mode 100644 index 000000000000..ce40c2263bf9 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-pl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"MM#2 – karta SIM nieobsługiwana"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"MM#3 – niedozwolona karta SIM"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-pt-rBR/strings.xml b/core/res/res/values-mcc310-mnc950-pt-rBR/strings.xml new file mode 100644 index 000000000000..1f89e4729904 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-pt-rBR/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-pt-rPT/strings.xml b/core/res/res/values-mcc310-mnc950-pt-rPT/strings.xml new file mode 100644 index 000000000000..1f89e4729904 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-pt-rPT/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-pt/strings.xml b/core/res/res/values-mcc310-mnc950-pt/strings.xml new file mode 100644 index 000000000000..1f89e4729904 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-pt/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-ro/strings.xml b/core/res/res/values-mcc310-mnc950-ro/strings.xml new file mode 100644 index 000000000000..7fb3f2e3f5e1 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-ro/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"Cardul SIM nu este activat MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"Cardul SIM nu este permis MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-ru/strings.xml b/core/res/res/values-mcc310-mnc950-ru/strings.xml new file mode 100644 index 000000000000..16deeed3ca12 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-ru/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM-карта не активирована (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"Использование SIM-карты запрещено (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-si/strings.xml b/core/res/res/values-mcc310-mnc950-si/strings.xml new file mode 100644 index 000000000000..dd512d91c090 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-si/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM MM#2 ප්රතිපාදනය නොකරයි"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM MM#3 ඉඩ නොදේ"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-sk/strings.xml b/core/res/res/values-mcc310-mnc950-sk/strings.xml new file mode 100644 index 000000000000..6a8e6f0e306f --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-sk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM karta nie je k dispozícii – MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM karta je zakázaná – MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-sl/strings.xml b/core/res/res/values-mcc310-mnc950-sl/strings.xml new file mode 100644 index 000000000000..391ee781bd51 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-sl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"Kartica SIM ni omogočena za uporabo MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"Kartica SIM ni dovoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-sq/strings.xml b/core/res/res/values-mcc310-mnc950-sq/strings.xml new file mode 100644 index 000000000000..ebc978c2a9d4 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-sq/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"Karta SIM nuk është dhënë MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"Karta SIM nuk lejohet MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-sr/strings.xml b/core/res/res/values-mcc310-mnc950-sr/strings.xml new file mode 100644 index 000000000000..4f3f86fdb043 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-sr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM картица није подешена MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM картица није дозвољена MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-sv/strings.xml b/core/res/res/values-mcc310-mnc950-sv/strings.xml new file mode 100644 index 000000000000..4739f064300e --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-sv/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM-kort tillhandahålls inte MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM-kort tillåts inte MM#3"</string> +</resources> diff --git a/core/res/res/values-sw380dp/dimens.xml b/core/res/res/values-mcc310-mnc950-sw/strings.xml index fc0e85d26bae..903b4a58e61f 100644 --- a/core/res/res/values-sw380dp/dimens.xml +++ b/core/res/res/values-mcc310-mnc950-sw/strings.xml @@ -1,9 +1,10 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml ** -** Copyright 2012, The Android Open Source Project +** Copyright 2006, The Android Open Source Project ** -** Licensed under the Apache License, Version 2.0 (the "License") +** 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 ** @@ -15,9 +16,10 @@ ** See the License for the specific language governing permissions and ** limitations under the License. */ ---> + --> -<resources> - <!-- Width of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) --> - <dimen name="keyguard_security_width">340dp</dimen> -</resources>
\ No newline at end of file +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM haitumiki MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM hairuhusiwi MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-ta/strings.xml b/core/res/res/values-mcc310-mnc950-ta/strings.xml new file mode 100644 index 000000000000..8838aed71700 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-ta/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"சிம் அமைக்கப்படவில்லை MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"சிம் அனுமதிக்கப்படவில்லை MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-te/strings.xml b/core/res/res/values-mcc310-mnc950-te/strings.xml new file mode 100644 index 000000000000..dc9625b21575 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-te/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM MM#2ని సక్రియం చేయలేదు"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM MM#3ని అనుమతించలేదు"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-th/strings.xml b/core/res/res/values-mcc310-mnc950-th/strings.xml new file mode 100644 index 000000000000..3feb1f6aa395 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-th/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"ไม่มีการจัดสรรซิม MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"ไม่อนุญาตให้ใช้ซิม MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-tl/strings.xml b/core/res/res/values-mcc310-mnc950-tl/strings.xml new file mode 100644 index 000000000000..55e0bfd47ac7 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-tl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"Hindi na-provision ang SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"Hindi pinapahintulutan ang SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-tr/strings.xml b/core/res/res/values-mcc310-mnc950-tr/strings.xml new file mode 100644 index 000000000000..7a274a4142fc --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-tr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM, MM#2\'nin temel hazırlığını yapamadı"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM MM#3\'e izin vermiyor"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-uk/strings.xml b/core/res/res/values-mcc310-mnc950-uk/strings.xml new file mode 100644 index 000000000000..bf5e6411edec --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-uk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM-карту не надано (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM-карта заборонена (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-ur/strings.xml b/core/res/res/values-mcc310-mnc950-ur/strings.xml new file mode 100644 index 000000000000..35857cd08583 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-ur/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM فراہم کردہ نہیں ہے MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM کی اجازت نہیں ہے MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-uz/strings.xml b/core/res/res/values-mcc310-mnc950-uz/strings.xml new file mode 100644 index 000000000000..e31c7b63c623 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-uz/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM karta ishlatish taqiqlangan (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM karta ishlatish taqiqlangan (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-vi/strings.xml b/core/res/res/values-mcc310-mnc950-vi/strings.xml new file mode 100644 index 000000000000..b9360b5a8451 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-vi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"SIM không được cấp phép MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"SIM không được phép MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-zh-rCN/strings.xml b/core/res/res/values-mcc310-mnc950-zh-rCN/strings.xml new file mode 100644 index 000000000000..3b4ba0a55e52 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-zh-rCN/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"未配置的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"不被允许的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-zh-rHK/strings.xml b/core/res/res/values-mcc310-mnc950-zh-rHK/strings.xml new file mode 100644 index 000000000000..763e498fbab3 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-zh-rHK/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"未佈建的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"不支援的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-zh-rTW/strings.xml b/core/res/res/values-mcc310-mnc950-zh-rTW/strings.xml new file mode 100644 index 000000000000..763e498fbab3 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-zh-rTW/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"未佈建的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"不支援的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc310-mnc950-zu/strings.xml b/core/res/res/values-mcc310-mnc950-zu/strings.xml new file mode 100644 index 000000000000..1c297545cef8 --- /dev/null +++ b/core/res/res/values-mcc310-mnc950-zu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="94675382531896663">"I-SIM ayinikezelwe MM#2"</string> + <string name="mmcc_illegal_ms" msgid="2418195136279399212">"I-SIM ayivunyelwe MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-af/strings.xml b/core/res/res/values-mcc311-mnc180-af/strings.xml new file mode 100644 index 000000000000..ead89927b7d3 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-af/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM is nie opgestel nie MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM word nie toegelaat nie MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-am/strings.xml b/core/res/res/values-mcc311-mnc180-am/strings.xml new file mode 100644 index 000000000000..a7d0d1dcd648 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-am/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"ሲም አልቀረበም MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"ሲም አይፈቀድም MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-ar/strings.xml b/core/res/res/values-mcc311-mnc180-ar/strings.xml new file mode 100644 index 000000000000..f5412bddc592 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-ar/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"لم يتم توفير SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"غير مسموح باستخدام SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-az/strings.xml b/core/res/res/values-mcc311-mnc180-az/strings.xml new file mode 100644 index 000000000000..c2c06be4be9a --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-az/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM MM#2 təmin etmir"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM MM#3 dəstəkləmir"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-b+sr+Latn/strings.xml b/core/res/res/values-mcc311-mnc180-b+sr+Latn/strings.xml new file mode 100644 index 000000000000..e8b35c3774de --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-b+sr+Latn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM kartica nije podešena MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM kartica nije dozvoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-be/strings.xml b/core/res/res/values-mcc311-mnc180-be/strings.xml new file mode 100644 index 000000000000..f2c10692a1d0 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-be/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM-карты няма MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM-карта не дапускаецца MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-bg/strings.xml b/core/res/res/values-mcc311-mnc180-bg/strings.xml new file mode 100644 index 000000000000..faf5a4240a28 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-bg/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM картата не е обезпечена MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM картата не е разрешена MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-bn/strings.xml b/core/res/res/values-mcc311-mnc180-bn/strings.xml new file mode 100644 index 000000000000..80efd0f10ace --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-bn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"সিমের জন্য প্রস্তুত নয় MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"সিমের অনুমতি নেই MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-bs/strings.xml b/core/res/res/values-mcc311-mnc180-bs/strings.xml new file mode 100644 index 000000000000..7c3e5b3a3f37 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-bs/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM kartica nije dodijeljena MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM kartica nije dozvoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-ca/strings.xml b/core/res/res/values-mcc311-mnc180-ca/strings.xml new file mode 100644 index 000000000000..e33a90100a3d --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-ca/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"La SIM no està proporcionada a MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"La SIM no és compatible a MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-cs/strings.xml b/core/res/res/values-mcc311-mnc180-cs/strings.xml new file mode 100644 index 000000000000..653a55a93fcd --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-cs/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM karta není poskytována (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM karta není povolena (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-da/strings.xml b/core/res/res/values-mcc311-mnc180-da/strings.xml new file mode 100644 index 000000000000..04c89a5931f6 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-da/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM-kort leveres ikke MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM-kort er ikke tilladt MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-de/strings.xml b/core/res/res/values-mcc311-mnc180-de/strings.xml new file mode 100644 index 000000000000..8fef08192b94 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-de/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM-Karte nicht eingerichtet MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM-Karte nicht zulässig MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-el/strings.xml b/core/res/res/values-mcc311-mnc180-el/strings.xml new file mode 100644 index 000000000000..795f48fadb0c --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-el/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"Δεν παρέχεται κάρτα SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"Η κάρτα SIM δεν επιτρέπεται MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-en-rAU/strings.xml b/core/res/res/values-mcc311-mnc180-en-rAU/strings.xml new file mode 100644 index 000000000000..9c972bc17f8e --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-en-rAU/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-en-rCA/strings.xml b/core/res/res/values-mcc311-mnc180-en-rCA/strings.xml new file mode 100644 index 000000000000..9c972bc17f8e --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-en-rCA/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-en-rGB/strings.xml b/core/res/res/values-mcc311-mnc180-en-rGB/strings.xml new file mode 100644 index 000000000000..9c972bc17f8e --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-en-rGB/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-en-rIN/strings.xml b/core/res/res/values-mcc311-mnc180-en-rIN/strings.xml new file mode 100644 index 000000000000..9c972bc17f8e --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-en-rIN/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-en-rXC/strings.xml b/core/res/res/values-mcc311-mnc180-en-rXC/strings.xml new file mode 100644 index 000000000000..f1a6cc7a447b --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-en-rXC/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM not provisioned MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM not allowed MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-es-rUS/strings.xml b/core/res/res/values-mcc311-mnc180-es-rUS/strings.xml new file mode 100644 index 000000000000..694cd7658170 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-es-rUS/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM no provista MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM no permitida MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-es/strings.xml b/core/res/res/values-mcc311-mnc180-es/strings.xml new file mode 100644 index 000000000000..605e314f1bed --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-es/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM no proporcionada (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM no admitida (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-et/strings.xml b/core/res/res/values-mcc311-mnc180-et/strings.xml new file mode 100644 index 000000000000..39dfa1b27478 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-et/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM-kaart on ette valmistamata MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM-kaart pole lubatud MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-eu/strings.xml b/core/res/res/values-mcc311-mnc180-eu/strings.xml new file mode 100644 index 000000000000..84732c90c970 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-eu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"Ez dago SIM txartelik MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"Ez da onartzen SIM txartela MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-fa/strings.xml b/core/res/res/values-mcc311-mnc180-fa/strings.xml new file mode 100644 index 000000000000..902d8210bc93 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-fa/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"سیمکارت مجوز لازم را ندارد MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"سیمکارت مجاز نیست MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-fi/strings.xml b/core/res/res/values-mcc311-mnc180-fi/strings.xml new file mode 100644 index 000000000000..004e6453d99c --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-fi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM-kortti ei käyttäjien hallinnassa MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM-kortti estetty MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-fr-rCA/strings.xml b/core/res/res/values-mcc311-mnc180-fr-rCA/strings.xml new file mode 100644 index 000000000000..c0aaf9908e08 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-fr-rCA/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"Carte SIM non configurée, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"Carte SIM non autorisée, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-fr/strings.xml b/core/res/res/values-mcc311-mnc180-fr/strings.xml new file mode 100644 index 000000000000..b9adf795b390 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-fr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"Carte SIM non provisionnée MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"Carte SIM non autorisée MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-gl/strings.xml b/core/res/res/values-mcc311-mnc180-gl/strings.xml new file mode 100644 index 000000000000..cb59c970269d --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-gl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"Non se introduciu ningunha tarxeta SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"Non se admite a tarxeta SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-gu/strings.xml b/core/res/res/values-mcc311-mnc180-gu/strings.xml new file mode 100644 index 000000000000..556416e8c735 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-gu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIMને MM#2ની જોગવાઈ નથી"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIMને MM#3 કરવાની મંજૂરી નથી"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-hi/strings.xml b/core/res/res/values-mcc311-mnc180-hi/strings.xml new file mode 100644 index 000000000000..da1f9e1beab1 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-hi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM काम नहीं कर रहा है MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM की अनुमति नहीं है MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-hr/strings.xml b/core/res/res/values-mcc311-mnc180-hr/strings.xml new file mode 100644 index 000000000000..a1f0b0e09b64 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-hr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"Ne pruža se usluga za SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM nije dopušten MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-hu/strings.xml b/core/res/res/values-mcc311-mnc180-hu/strings.xml new file mode 100644 index 000000000000..917c2ee9b8e3 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-hu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"Nem engedélyezett SIM-kártya (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"A SIM-kártya nem engedélyezett (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-hy/strings.xml b/core/res/res/values-mcc311-mnc180-hy/strings.xml new file mode 100644 index 000000000000..a832d020ebdc --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-hy/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM քարտը նախապատրաստված չէ (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM քարտի օգտագործումն արգելված է (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-in/strings.xml b/core/res/res/values-mcc311-mnc180-in/strings.xml new file mode 100644 index 000000000000..bdc8d2071aff --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-in/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM tidak di-provisioning MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM tidak diizinkan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-is/strings.xml b/core/res/res/values-mcc311-mnc180-is/strings.xml new file mode 100644 index 000000000000..35966f77643d --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-is/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM-korti ekki úthlutað MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM-kort ekki leyft MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-it/strings.xml b/core/res/res/values-mcc311-mnc180-it/strings.xml new file mode 100644 index 000000000000..25f301b7075d --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-it/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"Scheda SIM non predisposta MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"Scheda SIM non consentita MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-iw/strings.xml b/core/res/res/values-mcc311-mnc180-iw/strings.xml new file mode 100644 index 000000000000..c6bdc1464920 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-iw/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"כרטיס ה-SIM לא הופעל MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"כרטיס ה-SIM לא מורשה לשימוש ברשת הסלולרית MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-ja/strings.xml b/core/res/res/values-mcc311-mnc180-ja/strings.xml new file mode 100644 index 000000000000..6d308082de90 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-ja/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM には対応していません(MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM は許可されていません(MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-ka/strings.xml b/core/res/res/values-mcc311-mnc180-ka/strings.xml new file mode 100644 index 000000000000..b86ce07dcf4c --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-ka/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM ბარათი უზრუნველყოფილი არ არის (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM ბარათი დაუშვებელია (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-kk/strings.xml b/core/res/res/values-mcc311-mnc180-kk/strings.xml new file mode 100644 index 000000000000..539fbe45668c --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-kk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM картасы қарастырылмаған MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM картасына рұқсат етілмеген MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-km/strings.xml b/core/res/res/values-mcc311-mnc180-km/strings.xml new file mode 100644 index 000000000000..970532eef852 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-km/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"ស៊ីមកាតមិនត្រូវបានផ្ដល់ជូនទេ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"មិនអនុញ្ញាតចំពោះស៊ីមកាតទេ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-kn/strings.xml b/core/res/res/values-mcc311-mnc180-kn/strings.xml new file mode 100644 index 000000000000..53a04190c6e1 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-kn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"MM#2 ಗೆ ಸಿಮ್ ಸಿದ್ಧವಾಗಿಲ್ಲ"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"ಸಿಮ್ MM#3 ಅನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-ko/strings.xml b/core/res/res/values-mcc311-mnc180-ko/strings.xml new file mode 100644 index 000000000000..01d6fecd3321 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-ko/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM이 프로비저닝되지 않음 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM이 허용되지 않음 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-ky/strings.xml b/core/res/res/values-mcc311-mnc180-ky/strings.xml new file mode 100644 index 000000000000..7339e40e8b91 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-ky/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM карта таанылган жок (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM картаны колдонууга тыюу салынган (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-lo/strings.xml b/core/res/res/values-mcc311-mnc180-lo/strings.xml new file mode 100644 index 000000000000..5cbd1c8c3dac --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-lo/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM ບໍ່ໄດ້ເປີດໃຊ້ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM ບໍ່ອະນຸຍາດ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-lt/strings.xml b/core/res/res/values-mcc311-mnc180-lt/strings.xml new file mode 100644 index 000000000000..40a7e4ab08b3 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-lt/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM kortelė neteikiama (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM kortelė neleidžiama (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-lv/strings.xml b/core/res/res/values-mcc311-mnc180-lv/strings.xml new file mode 100644 index 000000000000..74b681815dd4 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-lv/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM karte netiek nodrošināta: MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM karti nav atļauts izmantot: MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-mk/strings.xml b/core/res/res/values-mcc311-mnc180-mk/strings.xml new file mode 100644 index 000000000000..7db80fa675f9 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-mk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"Не е обезбедена SIM-картичка, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"Не е дозволена SIM-картичка, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-ml/strings.xml b/core/res/res/values-mcc311-mnc180-ml/strings.xml new file mode 100644 index 000000000000..7cdd126f95ea --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-ml/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"സിം MM#2 പ്രൊവിഷൻ ചെയ്തിട്ടില്ല"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"സിം MM#3 അനുവദിച്ചിട്ടില്ല"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-mn/strings.xml b/core/res/res/values-mcc311-mnc180-mn/strings.xml new file mode 100644 index 000000000000..1be055c24d35 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-mn/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM-г идэвхжүүлээгүй байна MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM-г зөвшөөрөөгүй байна MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-mr/strings.xml b/core/res/res/values-mcc311-mnc180-mr/strings.xml new file mode 100644 index 000000000000..f8e08ae814ea --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-mr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM ने MM#2 ची तरतूद केलेली नाही"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM ने MM#3 ला परवानगी दिली नाही"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-ms/strings.xml b/core/res/res/values-mcc311-mnc180-ms/strings.xml new file mode 100644 index 000000000000..305a10d84660 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-ms/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM tidak diperuntukkan MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM tidak dibenarkan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-my/strings.xml b/core/res/res/values-mcc311-mnc180-my/strings.xml new file mode 100644 index 000000000000..306c0dd21926 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-my/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"ဆင်းမ်ကို ထောက်ပံ့မထားပါ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"ဆင်းမ်ကို ခွင့်မပြုပါ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-nb/strings.xml b/core/res/res/values-mcc311-mnc180-nb/strings.xml new file mode 100644 index 000000000000..e1296f4c7ac5 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-nb/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM-kortet er ikke klargjort, MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM-kortet er ikke tillatt, MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-ne/strings.xml b/core/res/res/values-mcc311-mnc180-ne/strings.xml new file mode 100644 index 000000000000..6177a83f025f --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-ne/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM को प्रावधान छैन MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM लाई अनुमति छैन MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-nl/strings.xml b/core/res/res/values-mcc311-mnc180-nl/strings.xml new file mode 100644 index 000000000000..3f12e64b9483 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-nl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"Simkaart niet geregistreerd MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"Simkaart niet toegestaan MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-pa/strings.xml b/core/res/res/values-mcc311-mnc180-pa/strings.xml new file mode 100644 index 000000000000..32f6a7edbfeb --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-pa/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"ਸਿਮ ਦੀ ਵਿਵਸਥਾ ਨਹੀਂ ਹੈ MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"ਸਿਮ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-pl/strings.xml b/core/res/res/values-mcc311-mnc180-pl/strings.xml new file mode 100644 index 000000000000..0744491953f2 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-pl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"MM#2 – karta SIM nieobsługiwana"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"MM#3 – niedozwolona karta SIM"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-pt-rBR/strings.xml b/core/res/res/values-mcc311-mnc180-pt-rBR/strings.xml new file mode 100644 index 000000000000..c4d22409c216 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-pt-rBR/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-pt-rPT/strings.xml b/core/res/res/values-mcc311-mnc180-pt-rPT/strings.xml new file mode 100644 index 000000000000..c4d22409c216 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-pt-rPT/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-pt/strings.xml b/core/res/res/values-mcc311-mnc180-pt/strings.xml new file mode 100644 index 000000000000..c4d22409c216 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-pt/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM não aprovisionado MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM não permitido MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-ro/strings.xml b/core/res/res/values-mcc311-mnc180-ro/strings.xml new file mode 100644 index 000000000000..68cab29e248c --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-ro/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"Cardul SIM nu este activat MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"Cardul SIM nu este permis MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-ru/strings.xml b/core/res/res/values-mcc311-mnc180-ru/strings.xml new file mode 100644 index 000000000000..90a3a095026f --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-ru/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM-карта не активирована (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"Использование SIM-карты запрещено (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-si/strings.xml b/core/res/res/values-mcc311-mnc180-si/strings.xml new file mode 100644 index 000000000000..1907d3ecf416 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-si/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM MM#2 ප්රතිපාදනය නොකරයි"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM MM#3 ඉඩ නොදේ"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-sk/strings.xml b/core/res/res/values-mcc311-mnc180-sk/strings.xml new file mode 100644 index 000000000000..a456431c6f1e --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-sk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM karta nie je k dispozícii – MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM karta je zakázaná – MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-sl/strings.xml b/core/res/res/values-mcc311-mnc180-sl/strings.xml new file mode 100644 index 000000000000..454a1cd9c681 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-sl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"Kartica SIM ni omogočena za uporabo MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"Kartica SIM ni dovoljena MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-sq/strings.xml b/core/res/res/values-mcc311-mnc180-sq/strings.xml new file mode 100644 index 000000000000..23da1a3e78b0 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-sq/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"Karta SIM nuk është dhënë MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"Karta SIM nuk lejohet MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-sr/strings.xml b/core/res/res/values-mcc311-mnc180-sr/strings.xml new file mode 100644 index 000000000000..182a7bc1e8e6 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-sr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM картица није подешена MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM картица није дозвољена MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-sv/strings.xml b/core/res/res/values-mcc311-mnc180-sv/strings.xml new file mode 100644 index 000000000000..fee7a1f92ac3 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-sv/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM-kort tillhandahålls inte MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM-kort tillåts inte MM#3"</string> +</resources> diff --git a/core/res/res/values-sw380dp-land/dimens.xml b/core/res/res/values-mcc311-mnc180-sw/strings.xml index 20eb1be0bb34..e49b3d15f20c 100644 --- a/core/res/res/values-sw380dp-land/dimens.xml +++ b/core/res/res/values-mcc311-mnc180-sw/strings.xml @@ -1,8 +1,8 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* //device/apps/common/assets/res/any/dimens.xml +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml ** -** Copyright 2012, The Android Open Source Project +** Copyright 2006, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -16,8 +16,10 @@ ** See the License for the specific language governing permissions and ** limitations under the License. */ ---> -<resources> - <!-- Top margin for the clock view --> - <dimen name="kg_clock_top_margin">48dp</dimen> + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM haitumiki MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM hairuhusiwi MM#3"</string> </resources> diff --git a/core/res/res/values-mcc311-mnc180-ta/strings.xml b/core/res/res/values-mcc311-mnc180-ta/strings.xml new file mode 100644 index 000000000000..6c11c4f93355 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-ta/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"சிம் அமைக்கப்படவில்லை MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"சிம் அனுமதிக்கப்படவில்லை MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-te/strings.xml b/core/res/res/values-mcc311-mnc180-te/strings.xml new file mode 100644 index 000000000000..5bb9f97c7b57 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-te/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM MM#2ని సక్రియం చేయలేదు"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM MM#3ని అనుమతించలేదు"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-th/strings.xml b/core/res/res/values-mcc311-mnc180-th/strings.xml new file mode 100644 index 000000000000..be4b08e5995c --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-th/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"ไม่มีการจัดสรรซิม MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"ไม่อนุญาตให้ใช้ซิม MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-tl/strings.xml b/core/res/res/values-mcc311-mnc180-tl/strings.xml new file mode 100644 index 000000000000..6aacf160a6d5 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-tl/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"Hindi na-provision ang SIM MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"Hindi pinapahintulutan ang SIM MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-tr/strings.xml b/core/res/res/values-mcc311-mnc180-tr/strings.xml new file mode 100644 index 000000000000..cf4fd77915f9 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-tr/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM, MM#2\'nin temel hazırlığını yapamadı"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM MM#3\'e izin vermiyor"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-uk/strings.xml b/core/res/res/values-mcc311-mnc180-uk/strings.xml new file mode 100644 index 000000000000..fae40acd8fd3 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-uk/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM-карту не надано (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM-карта заборонена (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-ur/strings.xml b/core/res/res/values-mcc311-mnc180-ur/strings.xml new file mode 100644 index 000000000000..ebceb5eb8a32 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-ur/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM فراہم کردہ نہیں ہے MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM کی اجازت نہیں ہے MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-uz/strings.xml b/core/res/res/values-mcc311-mnc180-uz/strings.xml new file mode 100644 index 000000000000..ebcdd3b6bbb6 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-uz/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM karta ishlatish taqiqlangan (MM#2)"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM karta ishlatish taqiqlangan (MM#3)"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-vi/strings.xml b/core/res/res/values-mcc311-mnc180-vi/strings.xml new file mode 100644 index 000000000000..0d7ff969d250 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-vi/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"SIM không được cấp phép MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM không được phép MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-zh-rCN/strings.xml b/core/res/res/values-mcc311-mnc180-zh-rCN/strings.xml new file mode 100644 index 000000000000..d8ff182fa535 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-zh-rCN/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"未配置的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"不被允许的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-zh-rHK/strings.xml b/core/res/res/values-mcc311-mnc180-zh-rHK/strings.xml new file mode 100644 index 000000000000..14332bf0deec --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-zh-rHK/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"未佈建的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"SIM 卡不允許 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-zh-rTW/strings.xml b/core/res/res/values-mcc311-mnc180-zh-rTW/strings.xml new file mode 100644 index 000000000000..775a70b60d54 --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-zh-rTW/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"未佈建的 SIM 卡 MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"不支援的 SIM 卡 MM#3"</string> +</resources> diff --git a/core/res/res/values-mcc311-mnc180-zu/strings.xml b/core/res/res/values-mcc311-mnc180-zu/strings.xml new file mode 100644 index 000000000000..a66760fddb8c --- /dev/null +++ b/core/res/res/values-mcc311-mnc180-zu/strings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* //device/apps/common/assets/res/any/strings.xml +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="mmcc_imsi_unknown_in_hlr" msgid="531930017979728896">"I-SIM ayinikezelwe MM#2"</string> + <string name="mmcc_illegal_ms" msgid="97745044956236881">"I-SIM ayivunyelwe MM#3"</string> +</resources> diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index 67e83e22d7ef..3df154341f2e 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Предупредувања"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Демонстрација за малопродажба"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB-врска"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Апликациите се извршуваат во заднина"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> се извршува во заднина"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> апликации се извршуваат во заднина"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Апликации што ја трошат батеријата"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> користи батерија"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> апликации користат батерија"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Допрете за детали за батеријата и потрошениот сообраќај"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Безбеден режим"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Поврзани сте на <xliff:g id="SESSION">%s</xliff:g>. Допрете за да управувате со мрежата."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Поврзување со секогаш вклучена VPN..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Поврзани со секогаш вклучена VPN"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Секогаш вклучената VPN е неповрзана"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Исклучено од секогаш вклучената VPN"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Грешка на секогаш вклучена VPN"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Допрете за да поставите"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Променете ја мрежата или поставките за VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Избери датотека"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Не е избрана датотека"</string> <string name="reset" msgid="2448168080964209908">"Ресетирај"</string> @@ -1764,7 +1764,7 @@ <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Да се зачуваат <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> во <b><xliff:g id="LABEL">%3$s</xliff:g></b>?"</string> <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Да се зачуваат <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> во <b><xliff:g id="LABEL">%4$s</xliff:g></b>?"</string> <string name="autofill_save_yes" msgid="6398026094049005921">"Зачувај"</string> - <string name="autofill_save_no" msgid="2625132258725581787">"Не, благодарам"</string> + <string name="autofill_save_no" msgid="2625132258725581787">"Не, фала"</string> <string name="autofill_save_type_password" msgid="5288448918465971568">"лозинка"</string> <string name="autofill_save_type_address" msgid="4936707762193009542">"адреса"</string> <string name="autofill_save_type_credit_card" msgid="7127694776265563071">"кредитна картичка"</string> diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index 650ccd1cf4ed..690b7f19290d 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"അലേർട്ടുകൾ"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"റീട്ടെയിൽ ഡെമോ"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB കണക്ഷൻ"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"ആപ്പുകൾ പശ്ചാത്തലത്തിൽ റൺ ചെയ്യുന്നു"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> പശ്ചാത്തലത്തിൽ റൺ ചെയ്യുന്നു"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> ആപ്പുകൾ പശ്ചാത്തലത്തിൽ റൺ ചെയ്യുന്നു"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"ആപ്പുകൾ ബാറ്ററി ഉപയോഗിക്കുന്നു"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> ബാറ്ററി ഉപയോഗിക്കുന്നു"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> ആപ്പുകൾ ബാറ്ററി ഉപയോഗിക്കുന്നു"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"ബാറ്ററി, ഡാറ്റ ഉപയോഗം എന്നിവയുടെ വിശദാംശങ്ങളറിയാൻ ടാപ്പുചെയ്യുക"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"സുരക്ഷിത മോഡ്"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> എന്ന സെഷനിലേക്ക് കണക്റ്റുചെയ്തു. നെറ്റ്വർക്ക് മാനേജുചെയ്യാൻ ടാപ്പുചെയ്യുക."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"എല്ലായ്പ്പോഴും ഓണായിരിക്കുന്ന VPN കണക്റ്റുചെയ്യുന്നു…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"എല്ലായ്പ്പോഴും ഓണായിരിക്കുന്ന VPN കണക്റ്റുചെയ്തു"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"\'എല്ലായ്പ്പോഴും ഓണായിരിക്കുന്ന VPN\' വിച്ഛേദിച്ചു"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"എപ്പോഴും ഓണായിരിക്കുന്ന VPN-ൽ നിന്ന് വിച്ഛേദിച്ചു"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"എല്ലായ്പ്പോഴും ഓണായിരിക്കുന്ന VPN പിശക്"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"സജ്ജമാക്കാൻ ടാപ്പുചെയ്യുക"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"നെറ്റ്വര്ക്ക് അല്ലെങ്കിൽ VPN ക്രമീകരണം മാറ്റുക"</string> <string name="upload_file" msgid="2897957172366730416">"ഫയല് തിരഞ്ഞെടുക്കുക"</string> <string name="no_file_chosen" msgid="6363648562170759465">"ഫയലൊന്നും തിരഞ്ഞെടുത്തില്ല"</string> <string name="reset" msgid="2448168080964209908">"പുനഃസജ്ജമാക്കുക"</string> diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml index c4b1193cd427..d355ffc2338a 100644 --- a/core/res/res/values-mn/strings.xml +++ b/core/res/res/values-mn/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Сануулга"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Жижиглэнгийн жишээ"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB холболт"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Цаана ажиллаж буй апп"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> ард ажиллаж байна"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> апп цаана ажиллаж байна"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Апп батерей ашиглаж байна"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> батерей ашиглаж байна"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> апп батерей ашиглаж байна"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Батерей, дата ашиглалтын талаар дэлгэрэнгүйг харахын тулд товшино уу"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Аюулгүй горим"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g>-д холбогдов. Сүлжээг удирдах бол товшино уу."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Байнгын VPN-д холбогдож байна..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Байнга VPN холбоотой"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Тогтмол асаалттай VPN салсан"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Тогтмол асаалттай VPN-с салсан"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Байнгын VPN алдаа"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Тохируулахын тулд товшино уу"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Сүлжээ эсвэл VPN тохиргоог өөрчлөх"</string> <string name="upload_file" msgid="2897957172366730416">"Файл сонгох"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Сонгосон файл байхгүй"</string> <string name="reset" msgid="2448168080964209908">"Бүгдийг цэвэрлэх"</string> diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index d6082554c9bb..a30039eeef4e 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -79,8 +79,8 @@ <string name="RestrictedOnAllVoiceTitle" msgid="158800171499150681">"व्हॉइस/आणीबाणी सेवा नाही"</string> <string name="RestrictedStateContent" msgid="4278821484643362350">"तुम्ही असलेल्या स्थानी मोबाइल नेटवर्क तात्पुरते उपलब्ध नाही"</string> <string name="NetworkPreferenceSwitchTitle" msgid="4008877505368566980">"नेटवर्कवर पोहोचूू शकत नाही"</string> - <string name="NetworkPreferenceSwitchSummary" msgid="1203771446683319957">"रिसेप्शन सुधारण्यासाठी, सोटिंग्ज > नेटवर्क आणि इंटरनेट > मोबाइल नेटवर्क > प्राधान्य दिलेला नेटवर्क प्रकार बदलून पहा."</string> - <string name="EmergencyCallWarningTitle" msgid="4790413876281901612">"वाय-फाय कॉलिंग सक्रिय आहे"</string> + <string name="NetworkPreferenceSwitchSummary" msgid="1203771446683319957">"रीसेप्शन सुधारण्यासाठी, सेटिंग्ज > नेटवर्क आणि इंटरनेट > मोबाइल नेटवर्क > अग्रमानांकित नेटवर्क प्रकार बदलून पहा."</string> + <string name="EmergencyCallWarningTitle" msgid="4790413876281901612">"वाय-फाय कॉलिंग चालू आहे"</string> <string name="EmergencyCallWarningSummary" msgid="8973232888021643293">"आपात्कालीन कॉलसाठी मोबाइल नेटवर्क असणे आवश्यक आहे."</string> <string name="notification_channel_network_alert" msgid="4427736684338074967">"अलर्ट"</string> <string name="notification_channel_call_forward" msgid="2419697808481833249">"कॉल फॉरवर्डिंग"</string> @@ -88,7 +88,7 @@ <string name="notification_channel_mobile_data_status" msgid="4575131690860945836">"मोबाइल डेटा स्थिती"</string> <string name="notification_channel_sms" msgid="3441746047346135073">"SMS संदेश"</string> <string name="notification_channel_voice_mail" msgid="3954099424160511919">"व्हॉइसमेल संदेश"</string> - <string name="notification_channel_wfc" msgid="2130802501654254801">"Wi-Fi कॉलिंग"</string> + <string name="notification_channel_wfc" msgid="2130802501654254801">"वाय-फाय कॉलिंग"</string> <string name="peerTtyModeFull" msgid="6165351790010341421">"समवयस्क व्यक्तीने TTY मोड पूर्ण ची विनंती केली"</string> <string name="peerTtyModeHco" msgid="5728602160669216784">"समवयस्क व्यक्तीने TTY मोड HCO ची विनंती केली"</string> <string name="peerTtyModeVco" msgid="1742404978686538049">"समवयस्क व्यक्तीने TTY मोड VCO ची विनंती केली"</string> @@ -127,7 +127,7 @@ <item msgid="4397097370387921767">"%s वाय-फाय कॉलिंग"</item> </string-array> <string name="wifi_calling_off_summary" msgid="8720659586041656098">"बंद"</string> - <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"वाय-फाय प्राधान्यकृत"</string> + <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"वाय-फाय अग्रमानांकित"</string> <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"प्राधान्य दिलेला मोबाइल"</string> <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"केवळ वाय-फाय"</string> <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: अग्रेषित केला नाही"</string> @@ -136,11 +136,11 @@ <string name="cfTemplateRegistered" msgid="5073237827620166285">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: अग्रेषित केला नाही"</string> <string name="cfTemplateRegisteredTime" msgid="6781621964320635172">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: अग्रेषित केला नाही"</string> <string name="fcComplete" msgid="3118848230966886575">"वैशिष्ट्य कोड पूर्ण."</string> - <string name="fcError" msgid="3327560126588500777">"कनेक्शन समस्या किंवा अवैध वैशिष्ट्य कोड."</string> + <string name="fcError" msgid="3327560126588500777">"कनेक्शन समस्या किंवा अवैध फीचर कोड."</string> <string name="httpErrorOk" msgid="1191919378083472204">"ठीक"</string> - <string name="httpError" msgid="7956392511146698522">"नेटवर्क त्रुटी आली."</string> + <string name="httpError" msgid="7956392511146698522">"नेटवर्क एरर आली."</string> <string name="httpErrorLookup" msgid="4711687456111963163">"URL शोधू शकलो नाही."</string> - <string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"साइट प्रमाणीकरण योजना समर्थित नाही."</string> + <string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"साइट प्रमाणीकरण योजनेस सपोर्ट नाही."</string> <string name="httpErrorAuth" msgid="1435065629438044534">"प्रमाणीकृत करू शकलो नाही."</string> <string name="httpErrorProxyAuth" msgid="1788207010559081331">"प्रॉक्सी सर्व्हरद्वारे प्रमाणीकरण यशस्वी झाले."</string> <string name="httpErrorConnect" msgid="8714273236364640549">"सर्व्हरशी कनेक्ट करू शकलो नाही."</string> @@ -148,12 +148,12 @@ <string name="httpErrorTimeout" msgid="4743403703762883954">"सर्व्हरवरील कनेक्शन टाइमआउट झाले."</string> <string name="httpErrorRedirectLoop" msgid="8679596090392779516">"पृष्ठामध्ये बरीच सर्व्हर पुनर्निर्देशने आहेत."</string> <string name="httpErrorUnsupportedScheme" msgid="5015730812906192208">"प्रोटोकॉल समर्थित नाही."</string> - <string name="httpErrorFailedSslHandshake" msgid="96549606000658641">"सुरक्षित कनेक्शन स्थापित करू शकलो नाही."</string> - <string name="httpErrorBadUrl" msgid="3636929722728881972">"URL अवैध असल्यामुळे पृष्ठ उघडू शकलो नाही."</string> + <string name="httpErrorFailedSslHandshake" msgid="96549606000658641">"सुरक्षित कनेक्शन इंस्टॉल करू शकलो नाही."</string> + <string name="httpErrorBadUrl" msgid="3636929722728881972">"URL अवैध असल्यामुळे पेज उघडू शकलो नाही."</string> <string name="httpErrorFile" msgid="2170788515052558676">"फायलीवर प्रवेश करू शकलो नाही."</string> <string name="httpErrorFileNotFound" msgid="6203856612042655084">"विनंती केलेली फाईल शोधू शकलो नाही."</string> <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"बर्याच विनंत्यांवर प्रक्रिया होत आहे. नंतर पुन्हा प्रयत्न करा."</string> - <string name="notification_title" msgid="8967710025036163822">"<xliff:g id="ACCOUNT">%1$s</xliff:g> साठी साइन इन त्रुटी"</string> + <string name="notification_title" msgid="8967710025036163822">"<xliff:g id="ACCOUNT">%1$s</xliff:g> साठी साइन इन एरर"</string> <string name="contentServiceSync" msgid="8353523060269335667">"संकालन करा"</string> <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"संकालन करा"</string> <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"खूप <xliff:g id="CONTENT_TYPE">%s</xliff:g> हटविणे."</string> @@ -162,15 +162,15 @@ <string name="low_memory" product="tv" msgid="516619861191025923">"टीव्ही संचयन भरले आहे. स्थान मोकळे करण्यासाठी काही फायली हटवा."</string> <string name="low_memory" product="default" msgid="3475999286680000541">"फोन संचयन पूर्ण भरले आहे. स्थान मोकळे करण्यासाठी काही फायली हटवा."</string> <plurals name="ssl_ca_cert_warning" formatted="false" msgid="5106721205300213569"> - <item quantity="one">प्रमाणपत्र अधिकार स्थापित केला</item> - <item quantity="other">प्रमाणपत्र अधिकार स्थापित केले</item> + <item quantity="one">प्रमाणपत्र अधिकार इंस्टॉल केला</item> + <item quantity="other">प्रमाणपत्र अधिकार इंस्टॉल केले</item> </plurals> <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"एका अज्ञात तृतीय पक्षाद्वारे"</string> <string name="ssl_ca_cert_noti_by_administrator" msgid="3541729986326153557">"आपल्या कार्य प्रोफाइल प्रशासकाद्वारे"</string> <string name="ssl_ca_cert_noti_managed" msgid="4030263497686867141">"<xliff:g id="MANAGING_DOMAIN">%s</xliff:g> द्वारे"</string> <string name="work_profile_deleted" msgid="5005572078641980632">"कार्य प्रोफाईल हटविले"</string> <string name="work_profile_deleted_description" msgid="1100529432509639864">"प्रशासक अॅप गहाळ असल्यामुळे कार्य प्रोफाइल हटवले गेले"</string> - <string name="work_profile_deleted_details" msgid="6307630639269092360">"कार्य प्रोफाइल प्रशासक अॅप गहाळ आहे किंवा दूषित आहे. परिणामी, आपले कार्य प्रोफाइल आणि संबंधित डेटा हटवले गेले आहेत. सहाय्यासाठी आपल्या प्रशासकाशी संपर्क साधा."</string> + <string name="work_profile_deleted_details" msgid="6307630639269092360">"कार्य प्रोफाइल प्रशासक अॅप गहाळ आहे किंवा करप्ट आहे. परिणामी, आपले कार्य प्रोफाइल आणि संबंधित डेटा हटवले गेले आहेत. सहाय्यासाठी आपल्या प्रशासकाशी संपर्क साधा."</string> <string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"आपले कार्य प्रोफाइल आता या डिव्हाइसवर उपलब्ध नाही"</string> <string name="network_logging_notification_title" msgid="6399790108123704477">"डीव्हाइस व्यवस्थापित केले आहे"</string> <string name="network_logging_notification_text" msgid="7930089249949354026">"आपली संस्था हे डीव्हाइस व्यवस्थापित करते आणि नेटवर्क रहदारीचे निरीक्षण करू शकते. तपशीलांसाठी टॅप करा."</string> @@ -201,7 +201,7 @@ <string name="shutdown_confirm" product="default" msgid="649792175242821353">"आपला फोन बंद होईल."</string> <string name="shutdown_confirm_question" msgid="2906544768881136183">"आपण बंद करू इच्छिता?"</string> <string name="reboot_safemode_title" msgid="7054509914500140361">"सुरक्षित मोडमध्ये रीबूट करा"</string> - <string name="reboot_safemode_confirm" msgid="55293944502784668">"आपण सुरक्षित मोडमध्ये रीबूट करू इच्छिता? हे आपण स्थापित केलेले सर्व तृतीय पक्ष अनुप्रयोग अक्षम करेल. आपण पुन्हा रीबूट करता तेव्हा ते पुनर्संचयित केले जातील."</string> + <string name="reboot_safemode_confirm" msgid="55293944502784668">"आपण सुरक्षित मोडमध्ये रीबूट करू इच्छिता? हे आपण इंस्टॉल केलेले सर्व तृतीय पक्ष अॅप्लिकेशन अक्षम करेल. आपण पुन्हा रीबूट करता तेव्हा ते पुनर्संचयित केले जातील."</string> <string name="recent_tasks_title" msgid="3691764623638127888">"अलीकडील"</string> <string name="no_recent_tasks" msgid="8794906658732193473">"अलीकडील कोणतेही अॅप्स नाहीत."</string> <string name="global_actions" product="tablet" msgid="408477140088053665">"टॅबलेट पर्याय"</string> @@ -210,9 +210,9 @@ <string name="global_action_lock" msgid="2844945191792119712">"स्क्रीन लॉक"</string> <string name="global_action_power_off" msgid="4471879440839879722">"बंद"</string> <string name="global_action_emergency" msgid="7112311161137421166">"आणीबाणी"</string> - <string name="global_action_bug_report" msgid="7934010578922304799">"दोष अहवाल"</string> - <string name="bugreport_title" msgid="2667494803742548533">"दोष अहवाल घ्या"</string> - <string name="bugreport_message" msgid="398447048750350456">"ई-मेल संदेश म्हणून पाठविण्यासाठी, हे तुमच्या सद्य डीव्हाइस स्थितीविषयी माहिती संकलित करेल. दोष अहवाल सुरू करण्यापासून तो पाठविण्यापर्यंत थोडा वेळ लागेल; कृपया धीर धरा."</string> + <string name="global_action_bug_report" msgid="7934010578922304799">"बग रीपोर्ट"</string> + <string name="bugreport_title" msgid="2667494803742548533">"बग रीपोर्ट घ्या"</string> + <string name="bugreport_message" msgid="398447048750350456">"ई-मेल संदेश म्हणून पाठविण्यासाठी, हे तुमच्या सद्य डीव्हाइस स्थितीविषयी माहिती संकलित करेल. बग रीपोर्ट सुरू करण्यापासून तो पाठविण्यापर्यंत थोडा वेळ लागेल; कृपया धीर धरा."</string> <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"परस्परसंवादी अहवाल"</string> <string name="bugreport_option_interactive_summary" msgid="229299488536107968">"बहुतांश प्रसंगांमध्ये याचा वापर करा. ते आपल्याला अहवालाच्या प्रगतीचा मागोवा घेण्याची, समस्येविषयी आणखी तपाशील प्रविष्ट करण्याची आणि स्क्रीनशॉट घेण्याची अनुमती देते. ते कदाचित अहवाल देण्यासाठी बराच वेळ घेणारे कमी-वापरलेले विभाग वगळू शकते."</string> <string name="bugreport_option_full_title" msgid="6354382025840076439">"संपूर्ण अहवाल"</string> @@ -239,7 +239,7 @@ <string name="notification_channel_car_mode" msgid="3553380307619874564">"कार मोड"</string> <string name="notification_channel_account" msgid="7577959168463122027">"खाते स्थिती"</string> <string name="notification_channel_developer" msgid="7579606426860206060">"विकसक संदेश"</string> - <string name="notification_channel_updates" msgid="4794517569035110397">"अद्यतने"</string> + <string name="notification_channel_updates" msgid="4794517569035110397">"अपडेट"</string> <string name="notification_channel_network_status" msgid="5025648583129035447">"नेटवर्क स्थिती"</string> <string name="notification_channel_network_alerts" msgid="2895141221414156525">"नेटवर्क सूचना"</string> <string name="notification_channel_network_available" msgid="4531717914138179517">"नेटवर्क उपलब्ध"</string> @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"सूचना"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"रीटेल डेमो"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB कनेक्शन"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"अॅप्स बॅकग्राउंडमध्ये चालू आहेत"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> बॅकग्राउंडमध्ये चालू आहे"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> अॅप्स बॅकग्राउंडमध्ये चालू आहेत"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"अॅप्समुळे बॅटरी संपत आहे"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> बॅटरी वापरत आहे"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> अॅप्स बॅटरी वापरत आहेत"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"बॅटरी आणि डेटा वापराच्या तपशीलांसाठी टॅप करा"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string> @@ -282,7 +282,7 @@ <string name="permgroupdesc_phone" msgid="6234224354060641055">"फोन कॉल आणि व्यवस्थापित"</string> <string name="permgrouprequest_phone" msgid="7084161459732093690">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ला फोन कॉल करू आणि ते व्यवस्थापित करू द्या"</string> <string name="permgrouplab_sensors" msgid="416037179223226722">"शरीर सेन्सर"</string> - <string name="permgroupdesc_sensors" msgid="7147968539346634043">"आपल्या महत्त्वाच्या मापनांविषयी सेन्सर डेटामध्ये प्रवेश करा"</string> + <string name="permgroupdesc_sensors" msgid="7147968539346634043">"आपल्या महत्त्वाच्या मापनांविषयी सेंसर डेटा अॅक्सेस करा"</string> <string name="permgrouprequest_sensors" msgid="8631146669524259656">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ला तुमच्या महत्त्वपूर्ण संकेतांविषयी सेन्सर डेटा अॅक्सेस करू द्या"</string> <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"विंडो सामग्री पुनर्प्राप्त करा"</string> <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"आपण परस्परसंवाद करीत असलेल्या विंडोची सामग्री तपासा."</string> @@ -290,7 +290,7 @@ <string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"टॅप केलेले आयटम मोठ्याने बोलले जातील आणि जेश्चरचा वापर करून स्क्रीन एक्सप्लोर केली जाऊ शकते."</string> <string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"आपण टाइप करता त्या मजकुराचे निरीक्षण करा"</string> <string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"क्रेडिट कार्ड नंबर आणि संकेतशब्द यासारखा वैयक्तिक डेटा समाविष्ट करते."</string> - <string name="capability_title_canControlMagnification" msgid="3593493281059424855">"प्रदर्शन विस्तृतीकरण नियंत्रित करा"</string> + <string name="capability_title_canControlMagnification" msgid="3593493281059424855">"डिस्प्ले मॅग्निफिकेशन नियंत्रित करा"</string> <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"प्रदर्शनाचा झूम स्तर आणि स्थिती निर्धारण नियंत्रित करा."</string> <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"जेश्चर करा"</string> <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"टॅप, स्वाइप, पिंच आणि इतर जेश्चर करू शकते."</string> @@ -310,9 +310,9 @@ <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"कॉल केला जात असताना कॉलला भिन्न नंबरवर पुनर्निर्देशित करण्याच्या किंवा संपूर्ण कॉल रद्द करण्याच्या पर्यायासह डायल केला जाणारा नंबर पाहण्याची अॅपला अनुमती देते"</string> <string name="permlab_answerPhoneCalls" msgid="4077162841226223337">"फोन कॉलचे उत्तर द्या"</string> <string name="permdesc_answerPhoneCalls" msgid="2901889867993572266">"येणार्या फोन कॉलचे उत्तर देण्यास अॅपला अनुमती देते."</string> - <string name="permlab_receiveSms" msgid="8673471768947895082">"मजकूर संदेश प्राप्त करा (SMS)"</string> - <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS संदेश प्राप्त करण्याची आणि त्यावर प्रक्रिया करण्याची अॅप ला अनुमती देते. म्हणजेच अॅप आपल्या डिव्हाइसवर पाठविलेले संदेश आपल्याला न दर्शवता त्यांचे परीक्षण करू किंवा ते हटवू शकतो."</string> - <string name="permlab_receiveMms" msgid="1821317344668257098">"मजकूर संदेश प्राप्त करा (MMS)"</string> + <string name="permlab_receiveSms" msgid="8673471768947895082">"मजकूर संदेश मिळवा (SMS)"</string> + <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS संदेश प्राप्त करण्याची आणि त्यावर प्रक्रिया करण्याची अॅप ला अनुमती देते. म्हणजेच अॅप आपल्या डीव्हाइसवर पाठविलेले संदेश तुम्हाला न दर्शवता त्यांचे परीक्षण करू किंवा ते हटवू शकतो."</string> + <string name="permlab_receiveMms" msgid="1821317344668257098">"मजकूर संदेश मिळवा (MMS)"</string> <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS संदेश प्राप्त करण्यास आणि त्यावर प्रक्रिया करण्यास अॅप ला अनुमती देते. म्हणजेच अॅप आपल्या डिव्हाइसवर पाठविलेले संदेश आपल्याला न दर्शवता त्यांचे परीक्षण करू किंवा ते हटवू शकतो."</string> <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"सेल प्रसारण संदेश वाचा"</string> <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"आपल्या डिव्हाइसद्वारे प्राप्त केलेले सेल प्रसारण संदेश वाचण्यासाठी अॅप ला अनुमती देते. काही स्थानांमध्ये आपल्याला आणीबाणीच्या परिस्थितीची चेतावणी देण्यासाठी सेल प्रसारण सूचना वितरीत केल्या जातात. आणीबाणी सेल प्रसारण प्राप्त होते तेव्हा आपल्या डिव्हाइसच्या कार्यप्रदर्शनात किंवा कार्यात दुर्भावनापूर्ण अॅप्स व्यत्यय आणू शकतात."</string> @@ -321,13 +321,13 @@ <string name="permlab_sendSms" msgid="7544599214260982981">"SMS संदेश पाठवणे आणि पाहणे"</string> <string name="permdesc_sendSms" msgid="7094729298204937667">"SMS संदेश पाठविण्यासाठी अॅप ला अनुमती देते. हे अनपेक्षित शुल्कामुळे होऊ शकते. दुर्भावनापूर्ण अॅप्स नी आपल्या पुष्टिकरणाशिवाय संदेश पाठवल्यामुळे आपले पैसे खर्च होऊ शकतात."</string> <string name="permlab_readSms" msgid="8745086572213270480">"आपले मजकूर संदेश वाचा (SMS किंवा MMS)"</string> - <string name="permdesc_readSms" product="tablet" msgid="4741697454888074891">"हा अॅप आपल्या टॅब्लेटवर संचयित केलेले सर्व SMS (मजकूर) संदेश वाचू शकतो."</string> - <string name="permdesc_readSms" product="tv" msgid="5796670395641116592">"हा अॅप आपल्या टीव्हीवर संचयित केलेले सर्व SMS (मजकूर) संदेश वाचू शकतो."</string> - <string name="permdesc_readSms" product="default" msgid="6826832415656437652">"हा अॅप आपल्या फोनवर संचयित केलेले सर्व SMS (मजकूर) संदेश वाचू शकतो."</string> - <string name="permlab_receiveWapPush" msgid="5991398711936590410">"मजकूर संदेश प्राप्त करा (WAP)"</string> + <string name="permdesc_readSms" product="tablet" msgid="4741697454888074891">"हा अॅप तुमच्या टॅब्लेटवर स्टोअर केलेले सर्व SMS (मजकूर) संदेश वाचू शकतो."</string> + <string name="permdesc_readSms" product="tv" msgid="5796670395641116592">"हा अॅप तुमच्या टीव्हीवर स्टोअर केलेले सर्व SMS (मजकूर) संदेश वाचू शकतो."</string> + <string name="permdesc_readSms" product="default" msgid="6826832415656437652">"हा अॅप तुमच्या फोनवर स्टोअर केलेले सर्व SMS (मजकूर) संदेश वाचू शकतो."</string> + <string name="permlab_receiveWapPush" msgid="5991398711936590410">"मजकूर संदेश मिळवा (WAP)"</string> <string name="permdesc_receiveWapPush" msgid="748232190220583385">"WAP संदेश प्राप्त करण्यास आणि त्यावर प्रक्रिया करण्यासाठी अॅप ला अनुमती देते. ही परवानगी आपल्याला पाठविलेले संदेश आपल्याला न दर्शविता त्यांचे परीक्षण करण्याची आणि ते हटविण्याची क्षमता समाविष्ट करते."</string> <string name="permlab_getTasks" msgid="6466095396623933906">"चालणारे अॅप्स पुनर्प्राप्त करा"</string> - <string name="permdesc_getTasks" msgid="7454215995847658102">"सध्या आणि अलीकडे चालणार्या कार्यांविषयी माहिती पुनर्प्राप्त करण्यासाठी अॅप ला अनुमती देते. हे डिव्हाइसवर कोणते अनुप्रयोग वापरले जात आहेत त्याविषयी माहिती शोधण्यासाठी अॅप ला अनुमती देऊ शकतात."</string> + <string name="permdesc_getTasks" msgid="7454215995847658102">"सध्या आणि अलीकडे चालणार्या कार्यांविषयी माहिती पुनर्प्राप्त करण्यासाठी अॅप ला अनुमती देते. हे डिव्हाइसवर कोणते अॅप्लिकेशन वापरले जात आहेत त्याविषयी माहिती शोधण्यासाठी अॅप ला अनुमती देऊ शकतात."</string> <string name="permlab_manageProfileAndDeviceOwners" msgid="7918181259098220004">"प्रोफाईल आणि डीव्हाइस मालक व्यवस्थापित करा"</string> <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"प्रोफाईल मालक आणि डीव्हाइस मालक सेट करण्याची अॅप्सना अनुमती द्या."</string> <string name="permlab_reorderTasks" msgid="2018575526934422779">"चालणारे अॅप्स पुनर्क्रमित करा"</string> @@ -337,7 +337,7 @@ <string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"अन्य अॅप्स बंद करा"</string> <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"अन्य अॅप्सच्या पार्श्वभूमी प्रक्रिया समाप्त करण्यासाठी अॅप ला अनुमती देते. यामुळे अन्य अॅप्स चालणे थांबू शकते."</string> <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"हा अॅप इतर अॅप्सच्या शीर्षस्थानी दिसू शकतो."</string> - <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"हा अॅप इतर अॅप्सच्या शीर्षस्थानी किंवा स्क्रीनच्या इतर भागांवर दिसू शकतो. हे सामान्य अॅप वापरात व्यत्यय आणू शकते किंवा इतर अॅप्सची प्रदर्शन पद्धत बदलू शकते."</string> + <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"हे अॅप इतर अॅप्सच्या शीर्षस्थानी किंवा स्क्रीनच्या इतर भागांवर दिसू शकतो. हे सामान्य अॅप वापरात व्यत्यय आणू शकते किंवा इतर अॅप्सची डिस्प्ले पद्धत बदलू शकते."</string> <string name="permlab_runInBackground" msgid="7365290743781858803">"पार्श्वभूमीत चालवा"</string> <string name="permdesc_runInBackground" msgid="7370142232209999824">"हे अॅप पार्श्वभूमीत चालू शकते. हे बॅटरी अधिक जलद संपवू शकते."</string> <string name="permlab_useDataInBackground" msgid="8694951340794341809">"पार्श्वभूमीत डेटा वापरा"</string> @@ -372,7 +372,7 @@ <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"येणार्या आणि केल्या जाणार्या कॉलविषयीच्या डेटासह, आपल्या टॅब्लेटचा कॉल लॉग सुधारित करण्यासाठी अॅप ला अनुमती देते. दुर्भावनापूर्ण अॅप्स आपला कॉल लॉग मिटवण्यासाठी किंवा सुधारित करण्यासाठी याचा वापर करू शकतात."</string> <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"येणार्या आणि केल्या जाणार्या कॉलविषयीच्या डेटासह, आपल्या टीव्हीचा कॉल लॉग सुधारित करण्यासाठी अॅपला अनुमती देते. दुर्भावनापूर्ण अॅप्स आपला कॉल लॉग मिटवण्यासाठी किंवा सुधारित करण्यासाठी याचा वापर करू शकतात."</string> <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"येणार्या आणि केल्या जाणार्या कॉलविषयीच्या डेटासह, आपल्या फोनचा कॉल लॉग सुधारित करण्यासाठी अॅप ला अनुमती देते. दुर्भावनापूर्ण अॅप्स आपला कॉल लॉग मिटवण्यासाठी किंवा सुधारित करण्यासाठी याचा वापर करू शकतात."</string> - <string name="permlab_bodySensors" msgid="4683341291818520277">"शरीर सेन्सरमध्ये (हृदय गती मॉनिटरसारखे) प्रवेश करा"</string> + <string name="permlab_bodySensors" msgid="4683341291818520277">"शरीर सेंसर (हृदय गती मॉनिटरसारखे) अॅक्सेस करा"</string> <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"हृदय गती सारख्या, आपल्या शारीरिक स्थितीचे नियंत्रण करणार्या सेन्सरवरून डेटामध्ये प्रवेश करण्यासाठी अॅपला अनुमती देते."</string> <string name="permlab_readCalendar" msgid="6716116972752441641">"कॅलेंडर इव्हेंट आणि तपशील वाचा"</string> <string name="permdesc_readCalendar" product="tablet" msgid="4993979255403945892">"हा अॅप आपल्या टॅब्लेटवर संचयित केलेले सर्व कॅलेंडर इव्हेंट वाचू आणि सामायिक करू शकतो किंवा आपला कॅलेंडर डेटा जतन करू शकतो."</string> @@ -382,27 +382,27 @@ <string name="permdesc_writeCalendar" product="tablet" msgid="1675270619903625982">"हा अॅप आपल्या टॅब्लेटवर कॅलेंडर इव्हेंट जोडू, काढू किंवा बदलू शकतो. हा अॅप कॅलेंडर मालकांकडून येत आहेत असे वाटणारे संदेश पाठवू किंवा त्यांच्या मालकांना सूचित केल्याशिवाय इव्हेंट बदलू शकतो."</string> <string name="permdesc_writeCalendar" product="tv" msgid="9017809326268135866">"हा अॅप आपल्या टीव्हीवर कॅलेंडर इव्हेंट जोडू, काढू किंवा बदलू शकतो. हा अॅप कॅलेंडर मालकांकडून येत आहेत असे वाटणारे संदेश पाठवू किंवा त्यांच्या मालकांना सूचित केल्याशिवाय इव्हेंट बदलू शकतो."</string> <string name="permdesc_writeCalendar" product="default" msgid="7592791790516943173">"हा अॅप आपल्या फोनवर कॅलेंडर इव्हेंट जोडू, काढू किंवा बदलू शकतो. हा अॅप कॅलेंडर मालकांकडून येत आहेत असे वाटणारे संदेश पाठवू किंवा त्यांच्या मालकांना सूचित केल्याशिवाय इव्हेंट बदलू शकतो."</string> - <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"अतिरिक्त स्थान प्रदाता आदेशांवर प्रवेश करा"</string> + <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"अतिरिक्त स्थान प्रदाता आदेश अॅक्सेस करा"</string> <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"अॅपला अतिरिक्त स्थान प्रदाता आदेशावर प्रवेश करण्याची अनुमती देते. हे कदाचित अॅपला GPS किंवा इतर स्थान स्त्रोत च्या ऑपरेशनमध्ये हस्तक्षेप करण्याची अनुमती देऊ शकते."</string> - <string name="permlab_accessFineLocation" msgid="251034415460950944">"अचूक स्थानामध्ये (GPS आणि नेटवर्क-आधारित) प्रवेश करा"</string> - <string name="permdesc_accessFineLocation" msgid="5821994817969957884">"हा अॅप सेल टॉवर आणि वाय-फाय नेटवर्क सारख्या GPS किंवा नेटवर्क स्रोतांच्या आधारावर आपले स्थान मिळवू शकतो. या स्थान सेवा वापरण्यास सक्षम असण्यासाठी त्या आपल्या फोनवर चालू केलेल्या आणि उपलब्ध असणे आवश्यक आहे. हे बॅटरी वापर वाढवू शकते."</string> - <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"अंदाजे स्थानामध्ये (नेटवर्क-आधारित) प्रवेश करा"</string> - <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"हा अॅप सेल टॉवर आणि वाय-फाय नेटवर्क सारख्या नेटवर्क स्रोतांच्या आधारावर आपले स्थान मिळवू शकतो. अॅपला या स्थान सेवा वापरण्यास सक्षम असण्यासाठी आपल्या टॅॅब्लेटवर त्या चालू केलेल्या आणि उपलब्ध असणे आवश्यक आहे."</string> - <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"हा अॅप सेल टॉवर आणि वाय-फाय नेटवर्क सारख्या नेटवर्क स्रोतांच्या आधारावर आपले स्थान मिळवू शकतो. अॅपला या स्थान सेवा वापरण्यास सक्षम असण्यासाठी आपल्या टीव्हीवर त्या चालू केलेल्या आणि उपलब्ध असणे आवश्यक आहे."</string> - <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"हा अॅप सेल टॉवर आणि वाय-फाय नेटवर्क सारख्या नेटवर्क स्रोतांच्या आधारावर आपले स्थान मिळवू शकतो. अॅपला या स्थान सेवा वापरण्यास सक्षम असण्यासाठी आपल्या फोनवर त्या चालू केलेल्या आणि उपलब्ध असणे आवश्यक आहे."</string> + <string name="permlab_accessFineLocation" msgid="251034415460950944">"अचूक स्थानामध्ये (GPS आणि नेटवर्क-आधारित) अॅक्सेस करा"</string> + <string name="permdesc_accessFineLocation" msgid="5821994817969957884">"हा अॅप सेल टॉवर आणि वाय-फाय नेटवर्क सारख्या GPS किंवा नेटवर्क स्रोतांच्या आधारावर तुमचे स्थान मिळवू शकतो. या स्थान सेवा वापरण्यास सक्षम असण्यासाठी त्या तुमच्या फोनवर चालू केलेल्या आणि उपलब्ध असणे आवश्यक आहे. हे बॅटरी वापर वाढवू शकते."</string> + <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"अंदाजे स्थानामध्ये (नेटवर्क-आधारित) अॅक्सेस करा"</string> + <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"हा अॅप सेल टॉवर आणि वाय-फाय नेटवर्क सारख्या नेटवर्क स्रोतांच्या आधारावर तुमचे स्थान मिळवू शकतो. अॅपला या स्थान सेवा वापरण्यास सक्षम असण्यासाठी तुमच्या टॅब्लेटवर त्या चालू केलेल्या आणि उपलब्ध असणे आवश्यक आहे."</string> + <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"हा अॅप सेल टॉवर आणि वाय-फाय नेटवर्क सारख्या नेटवर्क स्रोतांच्या आधारावर तुमचे स्थान मिळवू शकतो. अॅपला या स्थान सेवा वापरण्यास सक्षम असण्यासाठी तुमच्या टीव्हीवर त्या चालू केलेल्या आणि उपलब्ध असणे आवश्यक आहे."</string> + <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"हा अॅप सेल टॉवर आणि वाय-फाय नेटवर्क सारख्या नेटवर्क स्रोतांच्या आधारावर तुमचे स्थान मिळवू शकतो. अॅपला या स्थान सेवा वापरण्यास सक्षम असण्यासाठी तुमच्या फोनवर त्या चालू केलेल्या आणि उपलब्ध असणे आवश्यक आहे."</string> <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"आपल्या ऑडिओ सेटिंग्ज बदला"</string> <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"व्हॉल्यूम आणि आउटपुटसाठी कोणता स्पीकर वापरला आहे यासारख्या समग्र ऑडिओ सेटिंग्ज सुधारित करण्यासाठी अॅप ला अनुमती देते."</string> <string name="permlab_recordAudio" msgid="3876049771427466323">"ऑडिओ रेकॉर्ड"</string> <string name="permdesc_recordAudio" msgid="4245930455135321433">"हा अॅप कोणत्याही वेळी मायक्रोफोन वापरून ऑडिओ रेकॉर्ड करू शकता."</string> - <string name="permlab_sim_communication" msgid="2935852302216852065">"सिम वर आदेश पाठवा"</string> - <string name="permdesc_sim_communication" msgid="5725159654279639498">"अॅप ला सिम वर आदेश पाठविण्याची अनुमती देते. हे खूप धोकादायक असते."</string> + <string name="permlab_sim_communication" msgid="2935852302216852065">"सिम वर कमांड पाठवा"</string> + <string name="permdesc_sim_communication" msgid="5725159654279639498">"अॅप ला सिम वर कमांड पाठविण्याची अनुमती देते. हे खूप धोकादायक असते."</string> <string name="permlab_camera" msgid="3616391919559751192">"चित्रे आणि व्हिडिओ घ्या"</string> <string name="permdesc_camera" msgid="5392231870049240670">"हा अॅप कोणत्याही वेळी कॅमेरा वापरून चित्रेे घेऊ आणि व्हिडिअो रेकॉर्ड करू शकतो."</string> <string name="permlab_vibrate" msgid="7696427026057705834">"कंपन नियंत्रित करा"</string> <string name="permdesc_vibrate" msgid="6284989245902300945">"अॅप ला व्हायब्रेटर नियंत्रित करण्यासाठी अनुमती देते."</string> <string name="permlab_callPhone" msgid="3925836347681847954">"फोन नंबरवर प्रत्यक्ष कॉल करा"</string> <string name="permdesc_callPhone" msgid="3740797576113760827">"आपल्या हस्तक्षेपाशिवाय फोन नंबरवर कॉल करण्यासाठी अॅप ला अनुमती देते. यामुळे अनपेक्षित शुल्क किंवा कॉल लागू शकतात. लक्षात ठेवा की हे आणीबाणीच्या नंबरवर कॉल करण्यासाठी अॅप ला अनुमती देत नाही. दुर्भावनापूर्ण अॅप्स नी आपल्या पुष्टिकरणाशिवाय कॉल केल्यामुळे आपले पैसे खर्च होऊ शकतात."</string> - <string name="permlab_accessImsCallService" msgid="3574943847181793918">"IMS कॉल सेवेमध्ये प्रवेश करा"</string> + <string name="permlab_accessImsCallService" msgid="3574943847181793918">"IMS कॉल सेवा अॅक्सेस करा"</string> <string name="permdesc_accessImsCallService" msgid="8992884015198298775">"आपल्या हस्तक्षेपाशिवाय अॅपला कॉल करण्यासाठी IMS सेवा वापरण्याची अनुमती देते."</string> <string name="permlab_readPhoneState" msgid="9178228524507610486">"फोन स्थिती आणि ओळख वाचा"</string> <string name="permdesc_readPhoneState" msgid="1639212771826125528">"डीव्हाइस च्या फोन वैशिष्ट्यांवर अॅक्सेस करण्यास अॅपला अनुमती देते. ही परवानगी कॉल अॅक्टिव्हेट असला किंवा नसला तरीही, फोन नंबर आणि डीव्हाइस आयडी आणि कॉलद्वारे कनेक्ट केलेला रीमोट नंबर निर्धारित करण्यासाठी अॅपला अनुमती देते."</string> @@ -429,39 +429,39 @@ <string name="permdesc_setTimeZone" product="tv" msgid="888864653946175955">"टीव्हीचा टाईम झोन बदलण्यासाठी अॅपला अनुमती देते."</string> <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"फोनचा टाइम झोन बदलण्यासाठी अॅप ला अनुमती देते."</string> <string name="permlab_getAccounts" msgid="1086795467760122114">"डिव्हाइसवरील खाती शोधा"</string> - <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"टॅब्लेटद्वारे ज्ञात खात्यांची सूची मिळवण्यासाठी अॅप ला अनुमती देते. यात आपण स्थापित केलेल्या अनुप्रयोगांद्वारे तयार केलेली कोणतीही खाती समाविष्ट होऊ शकतात."</string> - <string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"टीव्हीद्वारे ज्ञात खात्यांची सूची मिळविण्यासाठी अॅपला अनुमती देतो. यात आपण स्थापित केलेल्या अनुप्रयोगांद्वारे तयार केलेली कोणतीही खाती समाविष्ट असू शकतात."</string> - <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"फोनद्वारे ज्ञात खात्यांची सूची मिळवण्यासाठी अॅप ला अनुमती देते. यात आपण स्थापित केलेल्या अनुप्रयोगांद्वारे तयार केलेली कोणतीही खाती समाविष्ट करू शकतात."</string> + <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"टॅब्लेटद्वारे ज्ञात खात्यांची सूची मिळवण्यासाठी अॅप ला अनुमती देते. यात आपण इंस्टॉल केलेल्या अनुप्रयोगांद्वारे तयार केलेली कोणतीही खाती समाविष्ट होऊ शकतात."</string> + <string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"टीव्हीद्वारे ज्ञात खात्यांची सूची मिळविण्यासाठी अॅपला अनुमती देतो. यात आपण इंस्टॉल केलेल्या अनुप्रयोगांद्वारे तयार केलेली कोणतीही खाती समाविष्ट असू शकतात."</string> + <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"फोनद्वारे ज्ञात खात्यांची सूची मिळवण्यासाठी अॅप ला अनुमती देते. यात आपण इंस्टॉल केलेल्या अनुप्रयोगांद्वारे तयार केलेली कोणतीही खाती समाविष्ट करू शकतात."</string> <string name="permlab_accessNetworkState" msgid="4951027964348974773">"नेटवर्क कनेक्शन पहा"</string> <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"कोणती नेटवर्क अस्तित्वात आहेत आणि कनेक्ट केलेली आहेत यासारख्या नेटवर्क कनेक्शनविषयीची माहिती पाहण्यासाठी अॅप ला अनुमती देते."</string> <string name="permlab_createNetworkSockets" msgid="7934516631384168107">"पूर्ण नेटवर्क प्रवेश आहे"</string> - <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"नेटवर्क सॉकेट तयार करण्यासाठी आणि सानुकूल नेटवर्क प्रोटोकॉल वापरण्यासाठी अॅप ला अनुमती देते. ब्राउझर आणि अन्य अनुप्रयोग म्हणजे इंटरनेटवर डेटा पाठवण्याचा मार्ग, म्हणजे इंटरनेटवर डेटा पाठविण्यासाठी परवानगीची आवश्यकता नसते."</string> + <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"नेटवर्क सॉकेट तयार करण्यासाठी आणि सानुकूल नेटवर्क प्रोटोकॉल वापरण्यासाठी अॅप ला अनुमती देते. ब्राउझर आणि अन्य अॅप्लिकेशन म्हणजे इंटरनेटवर डेटा पाठवण्याचा मार्ग, म्हणजे इंटरनेटवर डेटा पाठविण्यासाठी परवानगीची आवश्यकता नसते."</string> <string name="permlab_changeNetworkState" msgid="958884291454327309">"नेटवर्क कनेक्टिव्हिटी बदला"</string> <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"नेटवर्क कनेक्टिव्हिटीची स्थिती बदलण्यासाठी अॅप ला अनुमती देते."</string> <string name="permlab_changeTetherState" msgid="5952584964373017960">"टिथर केलेली कनेक्टिव्हिटी बदला"</string> <string name="permdesc_changeTetherState" msgid="1524441344412319780">"टेदर केलेल्या नेटवर्क कनेक्टिव्हिटीची स्थिती बदलण्यासाठी अॅप ला अनुमती देते."</string> <string name="permlab_accessWifiState" msgid="5202012949247040011">"वाय-फाय कनेक्शन पहा"</string> - <string name="permdesc_accessWifiState" msgid="5002798077387803726">"वाय-फाय सक्षम केले आहे किंवा नाही आणि कनेक्ट केलेल्या वाय-फाय डिव्हाइसेसचे नाव यासारख्या, वाय-फाय नेटवर्किंग विषयीची माहिती पाहण्यासाठी अॅप ला अनुमती देते."</string> + <string name="permdesc_accessWifiState" msgid="5002798077387803726">"वाय-फाय सक्षम केले आहे किंवा नाही आणि कनेक्ट केलेल्या वाय-फाय डीव्हाइसचे नाव यासारख्या, वाय-फाय नेटवर्किंग विषयीची माहिती पाहण्यासाठी अॅप ला अनुमती देते."</string> <string name="permlab_changeWifiState" msgid="6550641188749128035">"वाय-फाय वरून कनेक्ट करा आणि डिस्कनेक्ट करा"</string> <string name="permdesc_changeWifiState" msgid="7137950297386127533">"वाय-फाय अॅक्सेस बिंदूंवर कनेक्ट करण्यासाठी आणि त्यावरून डिस्कनेक्ट करण्यासाठी आणि वाय-फाय नेटवर्कसाठी डीव्हाइस कॉंफिगरेशनमध्ये बदल करण्यासाठी अॅपला अनुमती देते."</string> <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"वाय-फाय मल्टिकास्ट रिसेप्शनला अनुमती द्या"</string> - <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"मल्टिकास्ट पत्ते वापरून फक्त आपल्या टॅब्लेटवर नाही, तर वाय-फाय नेटवर्कवरील सर्व डिव्हाइसेसवर पाठविलेले पॅकेट प्राप्त करण्यासाठी अॅप ला अनुमती देते. हे गैर-मल्टिकास्ट मोडपेक्षा अधिक पॉवर वापरते."</string> - <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"केवळ आपला टीव्ही न वापरता, एकाधिक पत्ते वापरून एका वाय-फाय नेटवकवरील सर्व डिव्हाइसवर पाठविलेली पॅकेट प्राप्त करण्यासाठी अॅपला अनुमती देते."</string> - <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"मल्टिकास्ट पत्ते वापरून फक्त आपल्या फोनवर नाही, तर वाय-फाय नेटवर्कवरील सर्व डिव्हाइसेसवर पाठविलेले पॅकेट प्राप्त करण्यासाठी अॅप ला अनुमती देते. हे गैर-मल्टिकास्ट मोडपेक्षा अधिक पॉवर वापरते."</string> - <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"ब्लूटुथ सेटिंग्जवर प्रवेश करा"</string> - <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"स्थानिक ब्लूटुथ टॅबलेट कॉन्फिगर करण्याकरिता आणि दूरस्थ डिव्हाइसेस शोधण्यासाठी आणि त्यासह जोडण्यासाठी अॅप ला अनुमती देते."</string> - <string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"स्थानिक ब्लूटुथ टीव्ही कॉन्फिगर करण्यासाठी आणि दूरस्थ डिव्हाइसेससह शोधण्यासाठी आणि जोडण्यासाठी अॅपला अनुमती देते."</string> - <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"स्थानिक ब्लूटुथ फोन कॉन्फिगर करण्याकरिता आणि दूरस्थ डिव्हाइसेस शोधण्यासाठी आणि त्यासह जोडण्यासाठी अॅप ला अनुमती देते."</string> + <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"मल्टिकास्ट पत्ते वापरून फक्त तुमच्या टॅब्लेटवर नाही, तर वाय-फाय नेटवर्कवरील सर्व डीव्हाइसवर पाठविलेले पॅकेट प्राप्त करण्यासाठी अॅप ला अनुमती देते. हे मल्टिकास्टखेरिज इतर मोडसाठी अधिक पॉवर वापरते."</string> + <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"केवळ आपला टीव्ही न वापरता, एकाधिक पत्ते वापरून एका वाय-फाय नेटवकवरील सर्व डीव्हाइसवर पाठविलेली पॅकेट प्राप्त करण्यासाठी अॅपला अनुमती देते."</string> + <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"मल्टिकास्ट पत्ते वापरून फक्त तुमच्या फोनवर नाही, तर वाय-फाय नेटवर्कवरील सर्व डीव्हाइसवर पाठविलेले पॅकेट प्राप्त करण्यासाठी अॅप ला अनुमती देते. हे मल्टिकास्टखेरिज इतर मोडसाठी अधिक पॉवर वापरते."</string> + <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"ब्लूटूथ सेटिंग्ज अॅक्सेस करा"</string> + <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"स्थानिक ब्लूटूथ टॅबलेट कॉंफिगर करण्याकरिता आणि दूरस्थ डीव्हाइस शोधण्यासाठी आणि त्यासह जोडण्यासाठी अॅप ला अनुमती देते."</string> + <string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"स्थानिक ब्लूटूथ टीव्ही कॉंफिगर करण्यासाठी आणि दूरस्थ डीव्हाइससह शोधण्यासाठी आणि जोडण्यासाठी अॅपला अनुमती देते."</string> + <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"स्थानिक ब्लूटूथ फोन कॉंफिगर करण्याकरिता आणि दूरस्थ डीव्हाइस शोधण्यासाठी आणि त्यासह जोडण्यासाठी अॅप ला अनुमती देते."</string> <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAX कनेक्ट करा आणि त्यावरून डिस्कनेक्ट करा"</string> <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"WiMAX सक्षम केले आहे किंवा नाही आणि कनेक्ट केलेल्या कोणत्याही WiMAX नेटवर्क विषयीची माहिती निर्धारित करण्यासाठी अॅप ला अनुमती देते."</string> <string name="permlab_changeWimaxState" msgid="340465839241528618">"WiMAX स्थिती बदला"</string> <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"WiMAX नेटवर्कवर टॅबलेट कनेक्ट करण्यास आणि त्यावरून टॅबलेट डिस्कनेक्ट करण्यास अॅप ला अनुमती देते."</string> <string name="permdesc_changeWimaxState" product="tv" msgid="6022307083934827718">"WiMAX नेटवर्कवरून टीव्ही कनेक्ट करण्यासाठी आणि त्यावरून टीव्ही डिस्कनेक्ट करण्यासाठी अॅपला अनुमती देते."</string> <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"WiMAX नेटवर्कवर फोन कनेक्ट करण्यास आणि त्यावरून फोन डिस्कनेक्ट करण्यास अॅप ला अनुमती देते."</string> - <string name="permlab_bluetooth" msgid="6127769336339276828">"ब्लुटूथ डीव्हाइससह जोडा"</string> - <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"टॅब्लेटवर ब्लूटुथ चे कॉन्फिगरेशन पाहण्यासाठी आणि जोडलेल्या डिव्हाइसेससह कनेक्शन करण्यासाठी आणि स्वीकारण्यासाठी, अॅप ला अनुमती देते."</string> - <string name="permdesc_bluetooth" product="tv" msgid="3974124940101104206">"टीव्हीवर ब्लूटुथचे कॉन्फिगरेशन पाहण्यासाठी आणि जोडलेल्या डिव्हाइसेससह कनेक्शन करण्यासाठी आणि स्वीकारण्यासाठी अॅपला अनुमती देते."</string> - <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"फोनवर ब्लूटुथ चे कॉन्फिगरेशन पाहण्यासाठी आणि जोडलेल्या डिव्हाइसेससह कनेक्शन करण्यासाठी आणि स्वीकारण्यासाठी, अॅप ला अनुमती देते."</string> + <string name="permlab_bluetooth" msgid="6127769336339276828">"ब्लूटूथ डीव्हाइससह जोडा"</string> + <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"टॅबलेटवर ब्लूटूथ चे कॉंफिगरेशन पाहण्यासाठी आणि पेअर केलेल्या डीव्हाइससह कनेक्शन स्थापित करण्यासाठी आणि स्वीकारण्यासाठी, अॅप ला अनुमती देते."</string> + <string name="permdesc_bluetooth" product="tv" msgid="3974124940101104206">"टीव्हीवर ब्लूटूथचे कॉंफिगरेशन पाहण्यासाठी आणि जोडलेल्या डीव्हाइससह कनेक्शन स्थापित करण्यासाठी आणि स्वीकारण्यासाठी अॅपला अनुमती देते."</string> + <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"फोनवर ब्लूटूथ चे कॉंफिगरेशन पाहण्यासाठी आणि पेअर केलेल्या डीव्हाइससह कनेक्शन स्थापित करण्यासाठी आणि स्वीकारण्यासाठी, अॅप ला अनुमती देते."</string> <string name="permlab_nfc" msgid="4423351274757876953">"फील्ड जवळील कम्युनिकेशन नियंत्रित करा"</string> <string name="permdesc_nfc" msgid="7120611819401789907">"फील्ड जवळील कम्युनिकेशन (NFC) टॅग, कार्डे आणि वाचक यांच्यासह संवाद करण्यासाठी अॅपला अनुमती देते."</string> <string name="permlab_disableKeyguard" msgid="3598496301486439258">"आपले स्क्रीन लॉक अक्षम करा"</string> @@ -478,7 +478,7 @@ <string-array name="fingerprint_acquired_vendor"> </string-array> <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"फिंगरप्रिंट हार्डवेअर उपलब्ध नाही."</string> - <string name="fingerprint_error_no_space" msgid="1055819001126053318">"फिंगरप्रिंट संचयित केले जाऊ शकत नाही. कृपया विद्यमान फिंगरप्रिंट काढा."</string> + <string name="fingerprint_error_no_space" msgid="1055819001126053318">"फिंगरप्रिंट स्टोअर केले जाऊ शकत नाही. कृपया विद्यमान फिंगरप्रिंट काढा."</string> <string name="fingerprint_error_timeout" msgid="3927186043737732875">"फिंगरप्रिंट टाइमआउट झाले. पुन्हा प्रयत्न करा."</string> <string name="fingerprint_error_canceled" msgid="4402024612660774395">"फिंगरप्रिंट ऑपरेशन रद्द झाले."</string> <string name="fingerprint_error_lockout" msgid="5536934748136933450">"खूप प्रयत्न केले. नंतर पुन्हा प्रयत्न करा."</string> @@ -487,7 +487,7 @@ <string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g> बोट"</string> <string-array name="fingerprint_error_vendor"> </string-array> - <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"फिंगरप्रिंट चिन्ह"</string> + <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"फिंगरप्रिंट आयकन"</string> <string name="permlab_readSyncSettings" msgid="6201810008230503052">"संकालन सेटिंग्ज वाचा"</string> <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"खात्याच्या संकालन सेटिंग्ज वाचण्यासाठी अॅप ला अनुमती देते. उदाहरणार्थ, हे खात्यासह लोकांचा अॅप संकालित केला आहे किंवा नाही हे निर्धारित करू शकते."</string> <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"संकालन चालू आणि बंद करा टॉगल करा"</string> @@ -536,7 +536,7 @@ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"अनु्प्रयोगाला नेटवर्क स्थितींवरील निरीक्षणे ऐकण्यासाठी अनुमती देते. सामान्य अॅप्ससाठी कधीही आवश्यक नसावे."</string> <string name="permlab_setInputCalibration" msgid="4902620118878467615">"इनपुट डीव्हाइस कॅलिब्रेशन बदला"</string> <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"स्पर्श स्क्रीनची कॅलिब्रेशन प्राचले सुधारित करण्यासाठी अॅप ला अनुमती देते. सामान्य अॅप्स साठी कधीही आवश्यक नसते."</string> - <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM प्रमाणपत्रांवर प्रवेश करा"</string> + <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM प्रमाणपत्रे अॅक्सेस करा"</string> <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"DRM प्रमाणपत्रांची तरतूद करण्यासाठी आणि वापरण्यासाठी अनुप्रयोगास अनुमती देते. सामान्य अॅप्सकरिता कधीही आवश्यकता नसते."</string> <string name="permlab_handoverStatus" msgid="7820353257219300883">"Android बीम स्थानांतरण स्थिती प्राप्त करा"</string> <string name="permdesc_handoverStatus" msgid="4788144087245714948">"वर्तमान Android बीम स्थानांतरणांविषयी माहिती प्राप्त करण्यासाठी या अनुप्रयोगास अनुमती देते"</string> @@ -546,10 +546,10 @@ <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"वाहक मेसेजिंग सेवेचा शीर्ष-स्तर इंटरफेस बाइंड करण्यासाठी होल्डरला अनुमती देतो. सामान्य अॅप्सकरिता हे कधीही आवश्यक नसते."</string> <string name="permlab_bindCarrierServices" msgid="3233108656245526783">"वाहक सेवांवर प्रतिबद्ध करा"</string> <string name="permdesc_bindCarrierServices" msgid="1391552602551084192">"वाहक सेवांवर प्रतिबद्ध करण्यासाठी होल्डरला अनुमती देते. सामान्य अॅप्ससाठी कधीही आवश्यकता नसावी."</string> - <string name="permlab_access_notification_policy" msgid="4247510821662059671">"व्यत्यय आणू नका मध्ये प्रवेश करा"</string> + <string name="permlab_access_notification_policy" msgid="4247510821662059671">"व्यत्यय आणू नका अॅक्सेस करा"</string> <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"व्यत्यय आणू नका कॉन्फिगरेशन वाचण्यासाठी आणि लिहिण्यासाठी अॅपला अनुमती देते."</string> <string name="policylab_limitPassword" msgid="4497420728857585791">"संकेतशब्द नियम सेट करा"</string> - <string name="policydesc_limitPassword" msgid="2502021457917874968">"स्क्रीन लॉक संकेतशब्द आणि पिन मध्ये अनुमती दिलेली लांबी आणि वर्ण नियंत्रित करा."</string> + <string name="policydesc_limitPassword" msgid="2502021457917874968">"स्क्रीन लॉक पासवर्ड आणि पिन मध्ये अनुमती दिलेले लांबी आणि वर्ण नियंत्रित करा."</string> <string name="policylab_watchLogin" msgid="5091404125971980158">"स्क्रीन अनलॉक प्रयत्नांचे परीक्षण करा"</string> <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"टाइप केलेल्या अयोग्य संकेतशब्दांच्या अंकांचे परीक्षण करा. स्क्रीन अनलॉक केली जाते, तेव्हा टॅबलेट लॉक करा किंवा बरेच संकेतशब्द टाइप केले असल्यास टॅबलेटचा सर्व डेटा मिटवा."</string> <string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"स्क्रीन अनलॉक करताना टाइप केलेल्या चुकीच्या संकेतशब्दांच्या संख्येचे परीक्षण करा आणि टीव्ही लॉक करा किंवा अनेक चुकीचे संकेतशब्द टाइप केले असल्यास टीव्हीचा सर्व डेटा मिटवा."</string> @@ -573,8 +573,8 @@ <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"धोरण सक्षम असताना वापरण्यासाठी डीव्हाइस समग्र प्रॉक्सी सेट करा. फक्त डीव्हाइस मालक समग्र प्रॉक्सी सेट करु शकतो."</string> <string name="policylab_expirePassword" msgid="5610055012328825874">"स्क्रीन लॉक संकेतशब्द कालबाह्यता सेट करा"</string> <string name="policydesc_expirePassword" msgid="5367525762204416046">"लॉक-स्क्रीन संकेतशब्द किती वारंवार बदलणे आवश्यक आहे ते बदला."</string> - <string name="policylab_encryptedStorage" msgid="8901326199909132915">"संचयन कूटबद्धीकरण सेट करा"</string> - <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"संचयित अॅप डेटा कूटबद्ध केला जाणे आवश्यक आहे."</string> + <string name="policylab_encryptedStorage" msgid="8901326199909132915">"स्टोरेज एंक्रिप्शन सेट करा"</string> + <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"स्टोअर केलेला अॅप डेटा एंक्रिप्ट केला जाणे आवश्यक आहे."</string> <string name="policylab_disableCamera" msgid="6395301023152297826">"कॅमेरे अक्षम करा"</string> <string name="policydesc_disableCamera" msgid="2306349042834754597">"सर्व डीव्हाइस कॅमेर्यांचा वापर प्रतिबंधित करा."</string> <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"काही स्क्रीन लॉक वैशिष्ट्ये अक्षम करा"</string> @@ -756,7 +756,7 @@ <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"वापरकर्तानाव (ईमेल)"</string> <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"संकेतशब्द"</string> <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"साइन इन करा"</string> - <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"अवैध वापरकर्तानाव किंवा संकेतशब्द."</string> + <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"अवैध वापरकर्तानाव किंवा पासवर्ड."</string> <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"आपले वापरकर्तानाव किंवा संकेतशब्द विसरलात?\n "<b>"google.com/accounts/recovery"</b>" ला भेट द्या."</string> <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"तपासत आहे..."</string> <string name="lockscreen_unlock_label" msgid="737440483220667054">"अनलॉक करा"</string> @@ -794,10 +794,10 @@ <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string> <string name="granularity_label_character" msgid="7336470535385009523">"वर्ण"</string> <string name="granularity_label_word" msgid="7075570328374918660">"शब्द"</string> - <string name="granularity_label_link" msgid="5815508880782488267">"दुवा"</string> + <string name="granularity_label_link" msgid="5815508880782488267">"लिंक"</string> <string name="granularity_label_line" msgid="5764267235026120888">"रेखा"</string> <string name="factorytest_failed" msgid="5410270329114212041">"फॅक्टरी चाचणी अयशस्वी"</string> - <string name="factorytest_not_system" msgid="4435201656767276723">"FACTORY_TEST क्रिया फक्त /सिस्टम/अॅप मध्ये स्थापित केलेल्या पॅकेजसाठी समर्थित आहे."</string> + <string name="factorytest_not_system" msgid="4435201656767276723">"FACTORY_TEST क्रिया फक्त /सिस्टम/अॅप मध्ये इंस्टॉल केलेल्या पॅकेजसाठी समर्थित आहे."</string> <string name="factorytest_no_action" msgid="872991874799998561">"FACTORY_TEST क्रिया प्रदान करणारे कोणतेही पॅकेज आढळले नाही."</string> <string name="factorytest_reboot" msgid="6320168203050791643">"रीबूट करा"</string> <string name="js_dialog_title" msgid="1987483977834603872">"\"<xliff:g id="TITLE">%s</xliff:g>\" वरील पृष्ठ हे म्हणते:"</string> @@ -829,9 +829,9 @@ <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"आपले वेब बुकमार्क आणि इतिहास वाचा"</string> <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"ब्राउझरने भेट दिलेल्या सर्व URL चा इतिहास आणि ब्राउझरचे सर्व बुकमार्क वाचण्यास अॅप ला अनुमती देते. टीप: या परवानगीची तृतीय-पक्ष ब्राउझरद्वारे किंवा वेब ब्राउझिंग क्षमता असलेल्या अन्य अनुप्रयोगांद्वारे अंमलबजावणी करू शकत नाही."</string> <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"वेब बुकमार्क आणि इतिहास लिहा"</string> - <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"आपल्या टॅब्लेटवर संचयित केलेला ब्राउझरचा इतिहास किंवा बुकमार्क सुधारित करण्यासाठी अॅप ला अनुमती देते. हे ब्राउझर डेटा मिटविण्यासाठी किंवा सुधारित करण्यासाठी अॅप ला अनुमती देते. टीप: ही परवानगी तृतीय पक्ष ब्राउझरद्वारे किंवा वेब ब्राउझिंग क्षमतांसह अन्य अनुप्रयोगांद्वारे अंमलबजावणी करण्याची टीप देऊ शकते."</string> - <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"आपल्या टीव्हीवर संचयित केलेला ब्राउझरचा इतिहास किंवा बुकमार्क सुधारित करण्यासाठी अॅपला अनुमती देते. हे ब्राउझर डेटा मिटविण्यासाठी किंवा सुधारित करण्यासाठी अॅपला अनुमती देऊ शकते. टीप: या परवानगीची अंमलबजावणी वेब ब्राउझिंग क्षमता असलेल्या तृतीय-पक्ष ब्राउझरद्वारे किंवा इतर अनुप्रयोगांद्वारे केली जाऊ शकत नाही."</string> - <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"आपल्या फोनवर संचयित केलेला ब्राउझरचा इतिहास किंवा बुकमार्क सुधारित करण्यासाठी अॅप ला अनुमती देते. हे ब्राउझर डेटा मिटविण्यासाठी किंवा सुधारित करण्यासाठी अॅप ला अनुमती देते. टीप: ही परवानगी तृतीय पक्ष ब्राउझरद्वारे किंवा वेब ब्राउझिंग क्षमतांसह अन्य अनुप्रयोगांद्वारे अंमलबजावणी करण्याची टीप देऊ शकते."</string> + <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"तुमच्या टॅब्लेटवर संचयित केलेला ब्राउझरचा इतिहास किंवा बुकमार्क सुधारित करण्यासाठी अॅप ला अनुमती देते. हे ब्राउझर डेटा मिटविण्यासाठी किंवा सुधारित करण्यासाठी अॅप ला अनुमती देते. टीप: ही परवानगी तृतीय पक्ष ब्राउझरद्वारे किंवा वेब ब्राउझिंग क्षमतांसह अन्य अॅप्लिकेशनद्वारे अंमलबजावणी करण्याची टीप देऊ शकते."</string> + <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"तुमच्या टीव्हीवर संचयित केलेला ब्राउझरचा इतिहास किंवा बुकमार्क सुधारित करण्यासाठी अॅपला अनुमती देते. हे ब्राउझर डेटा मिटविण्यासाठी किंवा सुधारित करण्यासाठी अॅपला अनुमती देऊ शकते. टीप: या परवानगीची अंमलबजावणी वेब ब्राउझिंग क्षमता असलेल्या तृतीय-पक्ष ब्राउझरद्वारे किंवा इतर अॅप्लिकेशनद्वारे केली जाऊ शकत नाही."</string> + <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"तुमच्या फोनवर संचयित केलेला ब्राउझरचा इतिहास किंवा बुकमार्क सुधारित करण्यासाठी अॅप ला अनुमती देते. हे ब्राउझर डेटा मिटविण्यासाठी किंवा सुधारित करण्यासाठी अॅप ला अनुमती देते. टीप: ही परवानगी तृतीय पक्ष ब्राउझरद्वारे किंवा वेब ब्राउझिंग क्षमतांसह अन्य अॅप्लिकेशनद्वारे अंमलबजावणी करण्याची टीप देऊ शकते."</string> <string name="permlab_setAlarm" msgid="1379294556362091814">"अलार्म सेट करा"</string> <string name="permdesc_setAlarm" msgid="316392039157473848">"इंस्टॉल केलेल्या अलार्म घड्याळ अॅपमध्ये अलार्म सेट करण्यासाठी अॅपला अनुमती देते. काही अलार्म घड्याळ अॅप्समध्ये हे वैशिष्ट्य नसू शकते."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"व्हॉइसमेल जोडा"</string> @@ -1010,10 +1010,10 @@ <string name="whichSendToApplicationLabel" msgid="8878962419005813500">"पाठवा"</string> <string name="whichHomeApplication" msgid="4307587691506919691">"होम अॅप निवडा"</string> <string name="whichHomeApplicationNamed" msgid="4493438593214760979">"होम म्हणून %1$s वापरा"</string> - <string name="whichHomeApplicationLabel" msgid="809529747002918649">"प्रतिमा कॅप्चर करा"</string> - <string name="whichImageCaptureApplication" msgid="3680261417470652882">"यासह प्रतिमा कॅप्चर करा"</string> - <string name="whichImageCaptureApplicationNamed" msgid="8619384150737825003">"%1$s सह प्रतिमा कॅप्चर करा"</string> - <string name="whichImageCaptureApplicationLabel" msgid="6390303445371527066">"प्रतिमा कॅप्चर करा"</string> + <string name="whichHomeApplicationLabel" msgid="809529747002918649">"इमेज कॅप्चर करा"</string> + <string name="whichImageCaptureApplication" msgid="3680261417470652882">"यासह इमेज कॅप्चर करा"</string> + <string name="whichImageCaptureApplicationNamed" msgid="8619384150737825003">"%1$s सह इमेज कॅप्चर करा"</string> + <string name="whichImageCaptureApplicationLabel" msgid="6390303445371527066">"इमेज कॅप्चर करा"</string> <string name="alwaysUse" msgid="4583018368000610438">"या क्रियेसाठी डीफॉल्टनुसार वापरा."</string> <string name="use_a_different_app" msgid="8134926230585710243">"एक भिन्न अॅप वापरा"</string> <string name="clearDefaultHintMsg" msgid="3252584689512077257">"डाउनलोड केलेल्या सिस्टीम सेटिंग्ज > Apps > मधील डीफॉल्ट साफ करा."</string> @@ -1045,7 +1045,7 @@ <string name="screen_compat_mode_scale" msgid="3202955667675944499">"स्केल"</string> <string name="screen_compat_mode_show" msgid="4013878876486655892">"नेहमी दर्शवा"</string> <string name="screen_compat_mode_hint" msgid="1064524084543304459">"सिस्टीम सेटिंग्ज > Apps > डाउनलोड केलेले मध्ये हे पुन्हा-सक्षम करा."</string> - <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> वर्तमान प्रदर्शन आकार सेटिंगला समर्थन देत नाही आणि अनपेक्षित वर्तन करू शकते."</string> + <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> वर्तमान डिस्प्ले आकार सेटिंगला समर्थन देत नाही आणि अनपेक्षित वर्तन करू शकते."</string> <string name="unsupported_display_size_show" msgid="7969129195360353041">"नेहमी दर्शवा"</string> <string name="smv_application" msgid="3307209192155442829">"अॅप <xliff:g id="APPLICATION">%1$s</xliff:g> (प्रक्रिया <xliff:g id="PROCESS">%2$s</xliff:g>) ने तिच्या स्वयं-लागू केलेल्या StrictMode धोरणाचे उल्लंघन केले आहे."</string> <string name="smv_process" msgid="5120397012047462446">"<xliff:g id="PROCESS">%1$s</xliff:g> प्रक्रियेने तिच्या स्वतः-लागू केलेल्या StrictMode धोरणाचे उल्लंघन केले."</string> @@ -1065,23 +1065,23 @@ <string name="heavy_weight_switcher_text" msgid="7022631924534406403">"आपण एक नवीन प्रारंभ करण्यापूर्वी आधीपासून चालणारा दुसरा अॅप थांबविणे आवश्यक आहे."</string> <string name="old_app_action" msgid="493129172238566282">"<xliff:g id="OLD_APP">%1$s</xliff:g> कडे परत"</string> <string name="old_app_description" msgid="2082094275580358049">"नवीन अॅप प्रारंभ करू नका."</string> - <string name="new_app_action" msgid="5472756926945440706">"<xliff:g id="OLD_APP">%1$s</xliff:g> प्रारंभ करा"</string> + <string name="new_app_action" msgid="5472756926945440706">"<xliff:g id="OLD_APP">%1$s</xliff:g> सुरू करा"</string> <string name="new_app_description" msgid="1932143598371537340">"जतन न करता जुना अॅप थांबवा."</string> <string name="dump_heap_notification" msgid="2618183274836056542">"<xliff:g id="PROC">%1$s</xliff:g> ने मेमेरी मर्यादा वाढविली"</string> <string name="dump_heap_notification_detail" msgid="6901391084243999274">"हीप डंप संकलित केला गेला आहे; सामायिक करण्यासाठी टॅप करा"</string> <string name="dump_heap_title" msgid="5864292264307651673">"हीप डंप सामायिक करायचे?"</string> - <string name="dump_heap_text" msgid="4809417337240334941">"<xliff:g id="PROC">%1$s</xliff:g> प्रक्रियेने त्याची <xliff:g id="SIZE">%2$s</xliff:g> ची प्रक्रिया मेमरी मर्यादा ओलांडली आहे. त्याच्या विकासकासह सामायिक करण्यासाठी आपल्याकरिता हीप डंप उपलब्ध आहे. सावधगिरी बाळगा: या हीप डंपमध्ये आपली कोणतीही वैयक्तिक माहिती असू शकते ज्यात अनुप्रयोग प्रवेश करू शकतो."</string> + <string name="dump_heap_text" msgid="4809417337240334941">"<xliff:g id="PROC">%1$s</xliff:g> प्रक्रियेने त्याची <xliff:g id="SIZE">%2$s</xliff:g> ची प्रक्रिया मेमरी मर्यादा ओलांडली आहे. त्याच्या विकासकासह सामायिक करण्यासाठी आपल्याकरिता हीप डंप उपलब्ध आहे. सावधगिरी बाळगा: या हीप डंपमध्ये आपली कोणतीही वैयक्तिक माहिती असू शकते ज्यात अॅप्लिकेशन प्रवेश करू शकतो."</string> <string name="sendText" msgid="5209874571959469142">"मजकुरासाठी क्रिया निवडा"</string> <string name="volume_ringtone" msgid="6885421406845734650">"रिंगर व्हॉल्यूम"</string> <string name="volume_music" msgid="5421651157138628171">"मीडिया व्हॉल्यूम"</string> - <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"ब्लूटुथ द्वारे प्ले करत आहे"</string> + <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"ब्लूटूथ द्वारे प्ले करत आहे"</string> <string name="volume_music_hint_silent_ringtone_selected" msgid="8310739960973156272">"मूक रिंगटोन सेट केला"</string> <string name="volume_call" msgid="3941680041282788711">"कॉल-मधील व्हॉल्यूम"</string> - <string name="volume_bluetooth_call" msgid="2002891926351151534">"ब्लूटुथ कॉल-मधील व्हॉल्यूम"</string> + <string name="volume_bluetooth_call" msgid="2002891926351151534">"ब्लूटूथ कॉल-मधील व्हॉल्यूम"</string> <string name="volume_alarm" msgid="1985191616042689100">"अलार्म व्हॉल्यूम"</string> <string name="volume_notification" msgid="2422265656744276715">"सूचना व्हॉल्यूम"</string> <string name="volume_unknown" msgid="1400219669770445902">"व्हॉल्यूम"</string> - <string name="volume_icon_description_bluetooth" msgid="6538894177255964340">"ब्लूटुथ व्हॉल्यूम"</string> + <string name="volume_icon_description_bluetooth" msgid="6538894177255964340">"ब्लूटूथ व्हॉल्यूम"</string> <string name="volume_icon_description_ringer" msgid="3326003847006162496">"रिंगटोन व्हॉल्यूम"</string> <string name="volume_icon_description_incall" msgid="8890073218154543397">"कॉल व्हॉल्यूम"</string> <string name="volume_icon_description_media" msgid="4217311719665194215">"मीडिया व्हॉल्यूम"</string> @@ -1112,15 +1112,15 @@ <string name="network_available_sign_in" msgid="1848877297365446605">"नेटवर्कवर साइन इन करा"</string> <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) --> <skip /> - <string name="wifi_no_internet" msgid="8451173622563841546">"वाय-फायवरून इंटरनेटवर प्रवेश नाही"</string> + <string name="wifi_no_internet" msgid="8451173622563841546">"वाय-फायवरून इंटरनेटवर अॅक्सेस नाही"</string> <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"पर्यायांसाठी टॅप करा"</string> <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> वर स्विच केले"</string> - <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> कडे इंटरनेट अॅक्सेस नसताना डीव्हाइस <xliff:g id="NEW_NETWORK">%1$s</xliff:g> वापरतो. शुल्क लागू शकेल."</string> + <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> कडे इंटरनेट अॅक्सेस नसताना डीव्हाइस <xliff:g id="NEW_NETWORK">%1$s</xliff:g> वापरते. शुल्क लागू शकेल."</string> <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> वरून <xliff:g id="NEW_NETWORK">%2$s</xliff:g> वर स्विच केले"</string> <string-array name="network_switch_type_name"> <item msgid="3979506840912951943">"मोबाइल डेटा"</item> <item msgid="75483255295529161">"वाय-फाय"</item> - <item msgid="6862614801537202646">"ब्लूटुथ"</item> + <item msgid="6862614801537202646">"ब्लूटूथ"</item> <item msgid="5447331121797802871">"इथरनेट"</item> <item msgid="8257233890381651999">"VPN"</item> </string-array> @@ -1128,12 +1128,12 @@ <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"वाय-फाय ला कनेक्ट करू शकलो नाही"</string> <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" खराब इंटरनेट कनेक्शन आहे."</string> <string name="wifi_connect_alert_title" msgid="8455846016001810172">"कनेक्शनला अनुमती द्यायची?"</string> - <string name="wifi_connect_alert_message" msgid="6451273376815958922">"%1$s अनुप्रयोग %2$s वायफाय नेटवर्कशी कनेक्ट करू इच्छित आहे"</string> - <string name="wifi_connect_default_application" msgid="7143109390475484319">"अनुप्रयोग"</string> - <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"वाय-फाय थेट"</string> - <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"वाय-फाय थेट प्रारंभ करा. हे वाय-फाय क्लायंट/हॉटस्पॉट बंद करेल."</string> - <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"वाय-फाय थेट प्रारंभ करू शकलो नाही."</string> - <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"वाय-फाय थेट चालू आहे"</string> + <string name="wifi_connect_alert_message" msgid="6451273376815958922">"%1$s अॅप्लिकेशन %2$s वायफाय नेटवर्कशी कनेक्ट करू इच्छित आहे"</string> + <string name="wifi_connect_default_application" msgid="7143109390475484319">"अॅप्लिकेशन"</string> + <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"वाय-फाय डिरेक्ट"</string> + <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"वाय-फाय थेट सुरू करा. हे वाय-फाय क्लायंट/हॉटस्पॉट बंद करेल."</string> + <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"वाय-फाय डिरेक्ट कनेक्ट करू शकलो नाही."</string> + <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"वाय-फाय डिरेक्ट चालू आहे"</string> <string name="wifi_p2p_enabled_notification_message" msgid="8064677407830620023">"सेटिंग्जसाठी टॅप करा"</string> <string name="accept" msgid="1645267259272829559">"स्वीकार करा"</string> <string name="decline" msgid="2112225451706137894">"नकार द्या"</string> @@ -1143,12 +1143,12 @@ <string name="wifi_p2p_to_message" msgid="248968974522044099">"प्रति:"</string> <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"आवश्यक पिन टाइप करा:"</string> <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"पिन:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"टॅब्लेट <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ला कनेक्ट केलेले असताना तात्पुरते वाय-फाय वरून डिस्कनेक्ट होईल"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="3087858235069421128">"टीव्ही <xliff:g id="DEVICE_NAME">%1$s</xliff:g> शी कनेक्ट केलेला असताना वाय-फायवरून तो तात्पुरता डिस्कनेक्ट होईल"</string> + <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"टॅबलेट <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ला कनेक्ट केलेले असताना तात्पुरते वाय-फाय वरून डिस्कनेक्ट होईल"</string> + <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="3087858235069421128">"टीव्ही <xliff:g id="DEVICE_NAME">%1$s</xliff:g> शी कनेक्ट केलेला असताना वाय-फायवरून तात्पुरता डिस्कनेक्ट होईल"</string> <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> वर फोन कनेक्ट केलेला असताना तो वाय-फाय वरून तात्पुरता डिस्कनेक्ट केला जाईल"</string> <string name="select_character" msgid="3365550120617701745">"वर्ण घाला"</string> <string name="sms_control_title" msgid="7296612781128917719">"SMS संदेश पाठवत आहे"</string> - <string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> मोठ्या संख्येने SMS संदेश पाठवत आहे. आपण या अॅप ला संदेश पाठविणे सुरु ठेवण्याची अनुमती देऊ इच्छिता?"</string> + <string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> मोठ्या संख्येने SMS संदेश पाठवत आहे. तुम्ही या अॅप ला संदेश पाठविणे सुरु ठेवण्याची अनुमती देऊ इच्छिता?"</string> <string name="sms_control_yes" msgid="3663725993855816807">"अनुमती द्या"</string> <string name="sms_control_no" msgid="625438561395534982">"नकार द्या"</string> <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> हा <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b>वर एक संदेश पाठवू इच्छितो."</string> @@ -1156,7 +1156,7 @@ <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"यामुळे आपल्या मोबाईल खात्यावर शुल्क आकारले जाऊ शकते."</b></string> <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"पाठवा"</string> <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"रद्द करा"</string> - <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"माझी आवड लक्षात ठेवा"</string> + <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"माझी वड लक्षात ठेवा"</string> <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"आपण हे नंतर सेटिंग्ज आणि अॅप्स मध्ये बदलू शकता"</string> <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"नेहमी अनुमती द्या"</string> <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"कधीही अनुमती देऊ नका"</string> @@ -1166,7 +1166,7 @@ <string name="sim_added_title" msgid="3719670512889674693">"सिम कार्ड जोडले"</string> <string name="sim_added_message" msgid="6599945301141050216">"मोबाईल नेटवर्कवर अॅक्सेस करण्यासाठी तुमचे डीव्हाइस रीस्टार्ट करा."</string> <string name="sim_restart_button" msgid="4722407842815232347">"रीस्टार्ट"</string> - <string name="carrier_app_dialog_message" msgid="7066156088266319533">"आपल्या नवीन सिमने योग्यरित्या कार्य करण्यासाठी, आपल्याला अॅप स्थापित करण्याची आणि तो आपल्या वाहकामधून उघडण्याची आवश्यकता असेल."</string> + <string name="carrier_app_dialog_message" msgid="7066156088266319533">"आपल्या नवीन सिमने योग्यरित्या कार्य करण्यासाठी, आपल्याला अॅप इंस्टॉल करण्याची आणि तो आपल्या वाहकामधून उघडण्याची आवश्यकता असेल."</string> <string name="carrier_app_dialog_button" msgid="7900235513678617329">"अॅप मिळवा"</string> <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"आता नाही"</string> <string name="carrier_app_notification_title" msgid="8921767385872554621">"नवीन सिम घाला"</string> @@ -1192,9 +1192,9 @@ <string name="adb_active_notification_title" msgid="6729044778949189918">"USB डीबग करणे कनेक्ट केले"</string> <string name="adb_active_notification_message" msgid="4948470599328424059">"USB डीबग करणे अक्षम करण्यासाठी टॅप करा."</string> <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB डीबगिंग बंद करण्यासाठी निवडा."</string> - <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"दोष अहवाल घेत आहे..."</string> + <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"बग रीपोर्ट घेत आहे..."</string> <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"बग अहवाल सामायिक करायचा?"</string> - <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"दोष अहवाल सामायिक करीत आहे..."</string> + <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"बग रीपोर्ट शेअर करत आहे..."</string> <string name="share_remote_bugreport_notification_message_finished" msgid="6029609949340992866">"आपल्या प्रशासकाने या डिव्हाइसचे समस्या निवारण करण्यात मदत करण्यासाठी दोष अहवालाची विनंती केली. अॅप्स आणि डेटा शेअर केले जाऊ शकतात."</string> <string name="share_remote_bugreport_action" msgid="6249476773913384948">"सामायिक करा"</string> <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"नकार द्या"</string> @@ -1253,7 +1253,7 @@ <string name="permdesc_route_media_output" msgid="4932818749547244346">"अन्य बाह्य डिव्हाइसेसवरील रूट मीडिया आउटपुट वर अनुप्रयोगास अनुमती देते."</string> <string name="permlab_readInstallSessions" msgid="3713753067455750349">"स्थापना सत्र वाचा"</string> <string name="permdesc_readInstallSessions" msgid="2049771699626019849">"अनुप्रयोगास स्थापना सत्र वाचण्याची अनुमती देते. हे सक्रिय पॅकेज स्थापनांविषयी तपशील पाहाण्याची यास अनुमती देते."</string> - <string name="permlab_requestInstallPackages" msgid="5782013576218172577">"पॅकेज स्थापित करण्यासाठी विनंती करा"</string> + <string name="permlab_requestInstallPackages" msgid="5782013576218172577">"पॅकेज इंस्टॉल करण्यासाठी विनंती करा"</string> <string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"पॅकेजच्या स्थापना करण्यासाठी अनुप्रयोगास अनुमती देते."</string> <string name="permlab_requestDeletePackages" msgid="1703686454657781242">"पॅकेज हटवण्याची विनंती"</string> <string name="permdesc_requestDeletePackages" msgid="3406172963097595270">"अनुप्रयोगास पॅकेज हटवण्यासाठी विनंती करण्याची अनुमती देते."</string> @@ -1294,20 +1294,20 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> शी कनेक्ट केले. नेटवर्क व्यवस्थापित करण्यासाठी टॅप करा."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN कनेक्ट करणे नेहमी-चालू…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN कनेक्ट केलेले नेहमी-चालू"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"नेहमी-चालू असलेले VPN डिस्कनेक्ट केले"</string> - <string name="vpn_lockdown_error" msgid="6009249814034708175">"VPN त्रुटी नेहमी-चालू"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"सेट करण्यासाठी टॅप करा"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"कायम चालू असलेल्या VPN मधून डिस्कनेक्ट केले"</string> + <string name="vpn_lockdown_error" msgid="6009249814034708175">"VPN एरर नेहमी-चालू"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"नेटवर्क किंवा VPN सेटिंग्ज बदला"</string> <string name="upload_file" msgid="2897957172366730416">"फाईल निवडा"</string> <string name="no_file_chosen" msgid="6363648562170759465">"फाईल निवडली नाही"</string> <string name="reset" msgid="2448168080964209908">"रीसेट करा"</string> <string name="submit" msgid="1602335572089911941">"सबमिट करा"</string> <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"कार मोड सक्षम केला"</string> <string name="car_mode_disable_notification_message" msgid="6301524980144350051">"कार मोडमधून बाहेर पडण्यासाठी टॅप करा."</string> - <string name="tethered_notification_title" msgid="3146694234398202601">"टिथरिंग किंवा हॉटस्पॉट सक्रिय"</string> + <string name="tethered_notification_title" msgid="3146694234398202601">"टेदरिंग किंवा हॉटस्पॉट सक्रिय"</string> <string name="tethered_notification_message" msgid="2113628520792055377">"सेट करण्यासाठी टॅप करा."</string> <string name="disable_tether_notification_title" msgid="7526977944111313195">"टेदरिंग बंद आहे"</string> <string name="disable_tether_notification_message" msgid="2913366428516852495">"तपशीलांसाठी तुमच्या प्रशासकाशी संपर्क साधा"</string> - <string name="back_button_label" msgid="2300470004503343439">"परत"</string> + <string name="back_button_label" msgid="2300470004503343439">"मागे"</string> <string name="next_button_label" msgid="1080555104677992408">"पुढील"</string> <string name="skip_button_label" msgid="1275362299471631819">"वगळा"</string> <string name="no_matches" msgid="8129421908915840737">"कोणत्याही जुळण्या नाहीत"</string> @@ -1332,7 +1332,7 @@ <string name="sync_too_many_deletes" msgid="5296321850662746890">"ओलांडलेली मर्यादा हटवा"</string> <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"<xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> खात्यासाठी <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> हटविलेले आयटम आहेत. आपण काय करू इच्छिता?"</string> <string name="sync_really_delete" msgid="2572600103122596243">"आयटम हटवा"</string> - <string name="sync_undo_deletes" msgid="2941317360600338602">"हटविणे पूर्ववत करा"</string> + <string name="sync_undo_deletes" msgid="2941317360600338602">"हटवणे पूर्ववत करा"</string> <string name="sync_do_nothing" msgid="3743764740430821845">"सध्या काहीही करू नका"</string> <string name="choose_account_label" msgid="5655203089746423927">"एक खाते निवडा"</string> <string name="add_account_label" msgid="2935267344849993553">"एक खाते जोडा"</string> @@ -1404,7 +1404,7 @@ <string name="validity_period" msgid="8818886137545983110">"वैधता:"</string> <string name="issued_on" msgid="5895017404361397232">"रोजी जारी:"</string> <string name="expires_on" msgid="3676242949915959821">"रोजी मुदत संपेल:"</string> - <string name="serial_number" msgid="758814067660862493">"अनुक्रमांक:"</string> + <string name="serial_number" msgid="758814067660862493">"सीरीअल नंबर:"</string> <string name="fingerprints" msgid="4516019619850763049">"फिंगरप्रिंट:"</string> <string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 फिंगरप्रिंट:"</string> <string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 फिंगरप्रिंट:"</string> @@ -1424,7 +1424,7 @@ <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"स्पीकर डॉक करा"</string> <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"सिस्टम"</string> - <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"ब्लूटुथ ऑडिओ"</string> + <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"ब्लूटूथ ऑडिओ"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"वायरलेस डिस्प्ले"</string> <string name="media_route_button_content_description" msgid="591703006349356016">"कास्ट करा"</string> <string name="media_route_chooser_title" msgid="1751618554539087622">"डिव्हाइसला कनेक्ट करा"</string> @@ -1439,7 +1439,7 @@ <string name="media_route_status_in_use" msgid="4533786031090198063">"वापरात आहे"</string> <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"अंगभूत स्क्रीन"</string> <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI स्क्रीन"</string> - <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"आच्छादन #<xliff:g id="ID">%1$d</xliff:g>"</string> + <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"ओव्हरले #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", सुरक्षित"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"पॅटर्न विसरलात"</string> @@ -1447,7 +1447,7 @@ <string name="kg_wrong_password" msgid="2333281762128113157">"चुकीचा संकेतशब्द"</string> <string name="kg_wrong_pin" msgid="1131306510833563801">"चुकीचा पिन"</string> <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%1$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string> - <string name="kg_pattern_instructions" msgid="398978611683075868">"आपला पॅटर्न काढा"</string> + <string name="kg_pattern_instructions" msgid="398978611683075868">"तुमचा पॅटर्न काढा"</string> <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"सिम पिन प्रविष्ट करा"</string> <string name="kg_pin_instructions" msgid="2377242233495111557">"पिन प्रविष्ट करा"</string> <string name="kg_password_instructions" msgid="5753646556186936819">"संकेतशब्द प्रविष्ट करा"</string> @@ -1458,14 +1458,14 @@ <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"अयोग्य पिन कोड."</string> <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"4 ते 8 अंक असलेला पिन टाइप करा."</string> <string name="kg_invalid_sim_puk_hint" msgid="6025069204539532000">"PUK कोड 8 संख्येचा असावा."</string> - <string name="kg_invalid_puk" msgid="3638289409676051243">"योग्य PUK कोड पुन्हा-प्रविष्ट करा. परत प्रयत्न करणे सिम कायमचे अक्षम करेल."</string> + <string name="kg_invalid_puk" msgid="3638289409676051243">"योग्य PUK कोड पुन्हा एंटर करा. परत प्रयत्न करणे सिम कायमचे अक्षम करेल."</string> <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"पिन कोड जुळत नाहीत"</string> <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"बरेच पॅटर्न प्रयत्न"</string> <string name="kg_login_instructions" msgid="1100551261265506448">"अनलॉक करण्यासाठी, आपल्या Google खात्यासह साइन इन करा."</string> <string name="kg_login_username_hint" msgid="5718534272070920364">"वापरकर्तानाव (ईमेल)"</string> <string name="kg_login_password_hint" msgid="9057289103827298549">"संकेतशब्द"</string> <string name="kg_login_submit_button" msgid="5355904582674054702">"साइन इन करा"</string> - <string name="kg_login_invalid_input" msgid="5754664119319872197">"अवैध वापरकर्तानाव किंवा संकेतशब्द."</string> + <string name="kg_login_invalid_input" msgid="5754664119319872197">"अवैध वापरकर्तानाव किंवा पासवर्ड."</string> <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"आपले वापरकर्तानाव किंवा संकेतशब्द विसरलात?\n "<b>"google.com/accounts/recovery"</b>" ला भेट द्या."</string> <string name="kg_login_checking_password" msgid="1052685197710252395">"खाते तपासत आहे…"</string> <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"आपण आपला पिन <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यरितीने टाइप केला आहे. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string> @@ -1496,9 +1496,9 @@ <string name="user_switching_message" msgid="2871009331809089783">"<xliff:g id="NAME">%1$s</xliff:g> वर स्विच करत आहे…"</string> <string name="user_logging_out_message" msgid="8939524935808875155">"<xliff:g id="NAME">%1$s</xliff:g> लॉग आउट करीत आहे…"</string> <string name="owner_name" msgid="2716755460376028154">"मालक"</string> - <string name="error_message_title" msgid="4510373083082500195">"त्रुटी"</string> + <string name="error_message_title" msgid="4510373083082500195">"एरर"</string> <string name="error_message_change_not_allowed" msgid="1238035947357923497">"या बदलास आपल्या प्रशासकाद्वारे अनुमती नाही"</string> - <string name="app_not_found" msgid="3429141853498927379">"ही क्रिया हाताळण्यासाठी कोणताही अनुप्रयोग आढळला नाही"</string> + <string name="app_not_found" msgid="3429141853498927379">"ही क्रिया हाताळण्यासाठी कोणताही अॅप्लिकेशन आढळला नाही"</string> <string name="revoke" msgid="5404479185228271586">"मागे घ्या"</string> <string name="mediasize_iso_a0" msgid="1994474252931294172">"ISO A0"</string> <string name="mediasize_iso_a1" msgid="3333060421529791786">"ISO A1"</string> @@ -1584,12 +1584,12 @@ <string name="mediasize_unknown_portrait" msgid="3088043641616409762">"अज्ञात पोट्रेट"</string> <string name="mediasize_unknown_landscape" msgid="4876995327029361552">"अज्ञात लँडस्केप"</string> <string name="write_fail_reason_cancelled" msgid="7091258378121627624">"रद्द केले"</string> - <string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"सामग्री लिहिण्यात त्रुटी"</string> + <string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"आशय लिहिण्यात एरर"</string> <string name="reason_unknown" msgid="6048913880184628119">"अज्ञात"</string> <string name="reason_service_unavailable" msgid="7824008732243903268">"मुद्रण सेवा सक्षम केली नाही"</string> <string name="print_service_installed_title" msgid="2246317169444081628">"<xliff:g id="NAME">%s</xliff:g> सेवा स्थापित केली"</string> <string name="print_service_installed_message" msgid="5897362931070459152">"सक्षम करण्यासाठी टॅप करा"</string> - <string name="restr_pin_enter_admin_pin" msgid="8641662909467236832">"प्रशासक पिन प्रविष्ट करा"</string> + <string name="restr_pin_enter_admin_pin" msgid="8641662909467236832">"प्रशासक पिन एंटर करा"</string> <string name="restr_pin_enter_pin" msgid="3395953421368476103">"पिन प्रविष्ट करा"</string> <string name="restr_pin_incorrect" msgid="8571512003955077924">"चुकीचा"</string> <string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"वर्तमान पिन"</string> @@ -1624,11 +1624,11 @@ <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"अनपिन करण्यापूर्वी पिन साठी विचारा"</string> <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"अनपिन करण्यापूर्वी अनलॉक नमुन्यासाठी विचारा"</string> <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"अनपिन करण्यापूर्वी संकेतशब्दासाठी विचारा"</string> - <string name="package_installed_device_owner" msgid="6875717669960212648">"आपल्या प्रशासकाने स्थापित केले"</string> - <string name="package_updated_device_owner" msgid="1847154566357862089">"आपल्या प्रशासकाने अद्यतनित केले"</string> + <string name="package_installed_device_owner" msgid="6875717669960212648">"आपल्या प्रशासकाने इंस्टॉल केले"</string> + <string name="package_updated_device_owner" msgid="1847154566357862089">"आपल्या प्रशासकाने अपडेट केले"</string> <string name="package_deleted_device_owner" msgid="2307122077550236438">"आपल्या प्रशासकाने हटवले"</string> <string name="battery_saver_description" msgid="1960431123816253034">"बॅटरी लाइफ सुधारित करण्यासाठी, बॅटरी सेव्हर तुमच्या डीव्हाइस ची कामगिरी कमी करतो आणि कंपन, स्थान सेवा आणि बराच पार्श्वभूमी डेटा मर्यादित करतो. सिंकवर अवलंबून असणारे ईमेल, मेसेजिंग आणि इतर अॅप्स तुम्ही उघडल्याशिवाय अपडेट होऊ शकत नाहीत.\n\nतुमचे डीव्हाइस चार्ज होत असते तेव्हा बॅटरी सेव्हर आपोआप बंद होतो."</string> - <string name="data_saver_description" msgid="6015391409098303235">"डेटा वापर कमी करण्यात मदत करण्यासाठी, डेटा सर्व्हर काही अॅप्सना पार्श्वभूमीमध्ये डेटा पाठविण्यास किंवा प्राप्त करण्यास प्रतिबंधित करतो. आपण सध्या वापरत असलेला अॅप डेटामध्ये प्रवेश करू शकतो परंतु तसे तो खूप कमी वेळा करू शकतो. याचा अर्थ, उदाहरणार्थ, आपण प्रतिमा टॅप करेपर्यंत त्या प्रदर्शित करणार नाहीत असा असू शकतो."</string> + <string name="data_saver_description" msgid="6015391409098303235">"डेटा वापर कमी करण्यात मदत करण्यासाठी, डेटा सर्व्हर काही अॅप्सना पार्श्वभूमीमध्ये डेटा पाठविण्यास किंवा प्राप्त करण्यास प्रतिबंधित करतो. आपण सध्या वापरत असलेला अॅप डेटामध्ये प्रवेश करू शकतो परंतु तसे तो खूप कमी वेळा करू शकतो. याचा अर्थ, उदाहरणार्थ, आपण इमेज टॅप करेपर्यंत त्या प्रदर्शित करणार नाहीत असा असू शकतो."</string> <string name="data_saver_enable_title" msgid="4674073932722787417">"डेटा बचतकर्ता चालू करायचा?"</string> <string name="data_saver_enable_button" msgid="7147735965247211818">"चालू करा"</string> <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848"> @@ -1735,7 +1735,7 @@ <string name="app_category_game" msgid="5431836943981492993">"गेम"</string> <string name="app_category_audio" msgid="1659853108734301647">"संगीत आणि ऑडिओ"</string> <string name="app_category_video" msgid="2728726078629384196">"चित्रपट आणि व्हिडिओ"</string> - <string name="app_category_image" msgid="4867854544519846048">"फोटो आणि प्रतिमा"</string> + <string name="app_category_image" msgid="4867854544519846048">"फोटो आणि इमेज"</string> <string name="app_category_social" msgid="5842783057834965912">"सामाजिक आणि संप्रेषण"</string> <string name="app_category_news" msgid="7496506240743986873">"बातम्या आणि मासिके"</string> <string name="app_category_maps" msgid="5878491404538024367">"नकाशे आणि नेव्हिगेशन"</string> @@ -1761,7 +1761,7 @@ <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<b><xliff:g id="LABEL">%2$s</xliff:g></b>मध्ये <xliff:g id="TYPE">%1$s</xliff:g> सेव्ह करायची?"</string> <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<b><xliff:g id="LABEL">%3$s</xliff:g></b>मध्ये <xliff:g id="TYPE_0">%1$s</xliff:g> आणि <xliff:g id="TYPE_1">%2$s</xliff:g> सेव्ह करायची?"</string> <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<b><xliff:g id="LABEL">%4$s</xliff:g></b>मध्ये <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> आणि <xliff:g id="TYPE_2">%3$s</xliff:g> सेव्ह करायची?"</string> - <string name="autofill_save_yes" msgid="6398026094049005921">"जतन करा"</string> + <string name="autofill_save_yes" msgid="6398026094049005921">"सेव्ह करा"</string> <string name="autofill_save_no" msgid="2625132258725581787">"नाही धन्यवाद"</string> <string name="autofill_save_type_password" msgid="5288448918465971568">"संकेतशब्द"</string> <string name="autofill_save_type_address" msgid="4936707762193009542">"पत्ता"</string> diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml index d398facbb967..d8734907865d 100644 --- a/core/res/res/values-ms/strings.xml +++ b/core/res/res/values-ms/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Makluman"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Tunjuk cara runcit"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Sambungan USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Apl yang berjalan di latar belakang"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang berjalan di latar belakang"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> apl sedang berjalan di latar belakang"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Apl yang menggunakan bateri"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang menggunakan bateri"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> apl sedang menggunakan bateri"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Ketik untuk mendapatkan butiran tentang penggunaan kuasa bateri dan data"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Mod selamat"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Bersambung kepada <xliff:g id="SESSION">%s</xliff:g>. Ketik untuk mengurus rangkaian."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN sentiasa hidup sedang disambungkan..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN sentiasa hidup telah disambungkan"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"VPN sentiasa hidup diputuskan sambungannya"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Diputuskan sambungan daripada VPN sentiasa hidup"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Ralat VPN sentiasa hidup"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Ketik untuk menyediakan"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Tukar tetapan rangkaian atau VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Pilih fail"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Tiada fail dipilih"</string> <string name="reset" msgid="2448168080964209908">"Tetapkan semula"</string> diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml index 48be1d53ef3f..bc7a65c1aed8 100644 --- a/core/res/res/values-my/strings.xml +++ b/core/res/res/values-my/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"သတိပေးချက်များ"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"လက်လီအရောင်းဆိုင် သရုပ်ပြမှု"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB ချိတ်ဆက်မှု"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"နောက်ခံတွင် ပွင့်နေသော အက်ပ်များ"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် နောက်ခံတွင် ပွင့်နေပါသည်"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"အက်ပ် <xliff:g id="NUMBER">%1$d</xliff:g> ခုသည် နောက်ခံတွင် ပွင့်နေပါသည်"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"အက်ပ်များက ဘက်ထရီကုန်စေသည်"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> က ဘက်ထရီကို အသုံးပြုနေသည်"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"အက်ပ် <xliff:g id="NUMBER">%1$d</xliff:g> ခုက ဘက်ထရီကို အသုံးပြုနေသည်"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"ဘက်ထရီနှင့် ဒေတာအသုံးပြုမှု အသေးစိတ်ကို ကြည့်ရန် တို့ပါ"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>၊ <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"အန္တရာယ်ကင်းမှု စနစ်(Safe mode)"</string> @@ -580,7 +580,7 @@ <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"ဖန်သားပြင်သော့ခတ်နိုင်သည့်အင်္ဂါရပ် အချို့အား ပိတ်ထားပါ"</string> <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"ဖန်သားပြင်သော့ခတ်နိုင်သည့်အင်္ဂါရပ် အချို့ အသုံးပြုမှုအား ကာကွယ်ပါ။"</string> <string-array name="phoneTypes"> - <item msgid="8901098336658710359">"ပင်မစာမျက်နှာ"</item> + <item msgid="8901098336658710359">"အိမ်"</item> <item msgid="869923650527136615">"မိုဘိုင်း"</item> <item msgid="7897544654242874543">"အလုပ်"</item> <item msgid="1103601433382158155">"အလုပ်ဖက်စ်"</item> @@ -590,19 +590,19 @@ <item msgid="9192514806975898961">"မိမိစိတ်ကြိုက်"</item> </string-array> <string-array name="emailAddressTypes"> - <item msgid="8073994352956129127">"ပင်မစာမျက်နှာ"</item> + <item msgid="8073994352956129127">"အိမ်"</item> <item msgid="7084237356602625604">"အလုပ်"</item> <item msgid="1112044410659011023">"တခြား"</item> <item msgid="2374913952870110618">"မိမိစိတ်ကြိုက်"</item> </string-array> <string-array name="postalAddressTypes"> - <item msgid="6880257626740047286">"ပင်မစာမျက်နှာ"</item> + <item msgid="6880257626740047286">"အိမ်"</item> <item msgid="5629153956045109251">"အလုပ်"</item> <item msgid="4966604264500343469">"တခြား"</item> <item msgid="4932682847595299369">"မိမိစိတ်ကြိုက်"</item> </string-array> <string-array name="imAddressTypes"> - <item msgid="1738585194601476694">"ပင်မစာမျက်နှာ"</item> + <item msgid="1738585194601476694">"အိမ်"</item> <item msgid="1359644565647383708">"အလုပ်"</item> <item msgid="7868549401053615677">"တခြား"</item> <item msgid="3145118944639869809">"မိမိစိတ်ကြိုက်"</item> @@ -645,7 +645,7 @@ <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string> <string name="eventTypeCustom" msgid="7837586198458073404">"မိမိစိတ်ကြိုက်"</string> <string name="eventTypeBirthday" msgid="2813379844211390740">"မွေးနေ့"</string> - <string name="eventTypeAnniversary" msgid="3876779744518284000">"အထိမ်းအမှတ်"</string> + <string name="eventTypeAnniversary" msgid="3876779744518284000">"နှစ်ပတ်လည်နေ့"</string> <string name="eventTypeOther" msgid="7388178939010143077">"တခြား"</string> <string name="emailTypeCustom" msgid="8525960257804213846">"မိမိစိတ်ကြိုက်"</string> <string name="emailTypeHome" msgid="449227236140433919">"အိမ်"</string> @@ -653,11 +653,11 @@ <string name="emailTypeOther" msgid="2923008695272639549">"တခြား"</string> <string name="emailTypeMobile" msgid="119919005321166205">"မိုဘိုင်း"</string> <string name="postalTypeCustom" msgid="8903206903060479902">"မိမိစိတ်ကြိုက်"</string> - <string name="postalTypeHome" msgid="8165756977184483097">"ပင်မစာမျက်နှာ"</string> + <string name="postalTypeHome" msgid="8165756977184483097">"အိမ်"</string> <string name="postalTypeWork" msgid="5268172772387694495">"အလုပ်"</string> <string name="postalTypeOther" msgid="2726111966623584341">"တခြား"</string> <string name="imTypeCustom" msgid="2074028755527826046">"မိမိစိတ်ကြိုက်"</string> - <string name="imTypeHome" msgid="6241181032954263892">"ပင်မစာမျက်နှာ"</string> + <string name="imTypeHome" msgid="6241181032954263892">"အိမ်"</string> <string name="imTypeWork" msgid="1371489290242433090">"အလုပ်"</string> <string name="imTypeOther" msgid="5377007495735915478">"တခြား"</string> <string name="imProtocolCustom" msgid="6919453836618749992">"မိမိစိတ်ကြိုက်"</string> @@ -689,7 +689,7 @@ <string name="relationTypeSister" msgid="1735983554479076481">"ညီအမ"</string> <string name="relationTypeSpouse" msgid="394136939428698117">"အိမ်ထောင်ဖက်"</string> <string name="sipAddressTypeCustom" msgid="2473580593111590945">"မိမိစိတ်ကြိုက်"</string> - <string name="sipAddressTypeHome" msgid="6093598181069359295">"ပင်မစာမျက်နှာ"</string> + <string name="sipAddressTypeHome" msgid="6093598181069359295">"အိမ်"</string> <string name="sipAddressTypeWork" msgid="6920725730797099047">"အလုပ်"</string> <string name="sipAddressTypeOther" msgid="4408436162950119849">"တခြား"</string> <string name="quick_contacts_not_available" msgid="746098007828579688">"ဤအဆက်အသွယ်အား ကြည့်ရှုရန် အပလီကေးရှင်းမတွေ့ပါ"</string> @@ -755,7 +755,7 @@ <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"သော့ဖွင့်ရန် Google အကောင့်ဖြင့် ဝင်ပါ"</string> <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"သုံးစွဲသူ အမှတ် (အီးမေးလ်)"</string> <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"စကားဝှက်"</string> - <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"ဝင်ရန်"</string> + <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"လက်မှတ်ထိုးဝင်ရန်"</string> <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"အသုံးပြုသူအမည် သို့မဟုတ် လျို့ဝှက် နံပါတ် မှားယွင်းနေသည်"</string> <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"သုံးစွဲသူ အမည် သို့ စကားဝှင်ကို မေ့နေပါသလား။ \n"<b>"google.com/accounts/recovery"</b>" ကို သွားရောက်ပါ။"</string> <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"စစ်ဆေးနေပါသည်…"</string> @@ -978,7 +978,7 @@ <string name="editTextMenuTitle" msgid="4909135564941815494">"စာတို လုပ်ဆောင်ချက်"</string> <string name="email" msgid="4560673117055050403">"အီးမေးလ်"</string> <string name="dial" msgid="4204975095406423102">"ဖုန်း"</string> - <string name="map" msgid="6068210738233985748">"မြေပုံများ"</string> + <string name="map" msgid="6068210738233985748">"Maps"</string> <string name="browse" msgid="6993590095938149861">"ဘရောင်ဇာ"</string> <string name="low_internal_storage_view_title" msgid="5576272496365684834">"သိမ်းဆည်သော နေရာ နည်းနေပါသည်"</string> <string name="low_internal_storage_view_text" msgid="6640505817617414371">"တချို့ စနစ်လုပ်ငန်းများ အလုပ် မလုပ်ခြင်း ဖြစ်နိုင်ပါသည်"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> သို့ ချိတ်ဆက်ထားသည်။ ကွန်ရက်ကို စီမံခန့်ခွဲရန် တို့ပါ။"</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"အမြဲတမ်းဖွင့်ထား VPN ဆက်သွယ်နေစဉ်…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"အမြဲတမ်းဖွင့်ထား VPN ဆက်သွယ်မှုရှိ"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"အမြဲတမ်းဖွင့်ထားရသော VPN ပြတ်တောက်နေသည်"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"အမြဲပွင့်နေသော VPN မှ ချိတ်ဆက်မှုပြုတ်သွားပါပြီ"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"အမြဲတမ်းဖွင့်ထား VPN အမှား"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"ပြင်ဆင်သတ်မှတ်ရန် တို့ပါ"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"ကွန်ရက် သို့မဟုတ် VPN ဆက်တင်များကို ပြောင်းပါ"</string> <string name="upload_file" msgid="2897957172366730416">"ဖိုင်ရွေးချယ်ရန်"</string> <string name="no_file_chosen" msgid="6363648562170759465">"မည်သည့်ဖိုင်ကိုမှမရွေးပါ"</string> <string name="reset" msgid="2448168080964209908">"ပြန်လည်သတ်မှတ်ရန်"</string> @@ -1464,7 +1464,7 @@ <string name="kg_login_instructions" msgid="1100551261265506448">"သော့ဖွင့်ရန် သင့်ရဲ့ Google အကောင့်ဖြင့် ဝင်ပါ"</string> <string name="kg_login_username_hint" msgid="5718534272070920364">"သုံးစွဲသူအမည် (အီးမေးလ်)"</string> <string name="kg_login_password_hint" msgid="9057289103827298549">"စကားဝှက်"</string> - <string name="kg_login_submit_button" msgid="5355904582674054702">"ဝင်ပါ"</string> + <string name="kg_login_submit_button" msgid="5355904582674054702">"လက်မှတ်ထိုးဝင်ရန်"</string> <string name="kg_login_invalid_input" msgid="5754664119319872197">"အသုံးပြုသူ အမည် သို့ စကားဝှက်မမှန်ကန်ပါ"</string> <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"သင် သုံးစွဲသူ အမည် သို့ စကားဝှက်အားမေ့နေပါသလား။\n"<b>"google.com/accounts/recovery"</b>" သို့ သွားရောက်ပါ"</string> <string name="kg_login_checking_password" msgid="1052685197710252395">"အကောင့်ကို စစ်ဆေးနေစဉ်..."</string> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index ca6b62a3478b..61417ef70f13 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Varsler"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Butikkdemo"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB-tilkobling"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Apper kjører i bakgrunnen"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> kjører i bakgrunnen"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> apper kjører i bakgrunnen"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Apper bruker batteri"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> bruker batteri"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> apper bruker batteri"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Trykk for detaljer om batteri- og databruk"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Sikkermodus"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Koblet til <xliff:g id="SESSION">%s</xliff:g>. Trykk for å administrere nettverket."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Alltid-på VPN kobler til ..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Alltid-på VPN er tilkoblet"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Alltid på-VPN er frakoblet"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Koble fra alltid på-VPN"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Alltid-på VPN-feil"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Trykk for å konfigurere"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Endre nettverks- eller VPN-innstillingene"</string> <string name="upload_file" msgid="2897957172366730416">"Velg fil"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Ingen fil er valgt"</string> <string name="reset" msgid="2448168080964209908">"Tilbakestill"</string> diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index 2221da907a8d..24279c700657 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"अलर्टहरू"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"खुद्रा बिक्री सम्बन्धी डेमो"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB जडान"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"पृष्ठभूमिमा चल्ने अनुप्रयोगहरू"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> पृष्ठभूमिमा चल्दैछ"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> अनुप्रयोगहरू पृष्ठभूमिमा चल्दैछन्"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"अनुप्रयोगहरूले ब्याट्री खपत गर्दै छन्"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> ले ब्याट्री प्रयोग गर्दै छ"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> अनुप्रयोगहरूले ब्याट्री प्रयोग गर्दै छन्"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"ब्याट्री र डेटाका प्रयोग सम्बन्धी विवरणहरूका लागि ट्याप गर्नुहोस्"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string> @@ -1300,9 +1300,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g>सँग जोडिएको। नेटवर्क प्रबन्ध गर्न हान्नुहोस्।"</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN जडान सधै जोड्दै…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"सधैँ खुल्ला हुने VPN जोडिएको"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"सधैँ-सक्रिय VPN लाई विच्छेद गरियो"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"सधैँ-सक्रिय रहने VPN सेवाबाट विच्छेद गरियो"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"सधैँ भरि VPN त्रुटिमा"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"सेट अप गर्न ट्याप गर्नुहोस्"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"नेटवर्क वा VPN सम्बन्धी सेटिङहरू परिवर्तन गर्नुहोस्"</string> <string name="upload_file" msgid="2897957172366730416">"फाइल छान्नुहोस्"</string> <string name="no_file_chosen" msgid="6363648562170759465">"कुनै फाइल छानिएको छैन"</string> <string name="reset" msgid="2448168080964209908">"रिसेट गर्नुहोस्"</string> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 3798fff44e5e..c57763be6e29 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Meldingen"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demo voor de detailhandel"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB-verbinding"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Apps uitgevoerd op achtergrond"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> is op de achtergrond actief"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> apps worden uitgevoerd op de achtergrond"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Apps die de batterij gebruiken"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> gebruikt de batterij"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> apps gebruiken de batterij"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Tik voor batterij- en datagebruik"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Veilige modus"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Verbonden met <xliff:g id="SESSION">%s</xliff:g>. Tik om het netwerk te beheren."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Always-on VPN-verbinding maken…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Always-on VPN-verbinding"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Always-on VPN-verbinding ontkoppeld"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Verbinding met Always-on VPN verbroken"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Fout met Always-on VPN"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tik om in te stellen"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Netwerk- of VPN-instellingen wijzigen"</string> <string name="upload_file" msgid="2897957172366730416">"Bestand kiezen"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Geen bestand geselecteerd"</string> <string name="reset" msgid="2448168080964209908">"Resetten"</string> diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index ba0276d9fb71..326cc99f8c28 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -80,12 +80,12 @@ <string name="RestrictedStateContent" msgid="4278821484643362350">"ਤੁਹਾਡੇ ਟਿਕਾਣੇ \'ਤੇ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਵੱਲੋਂ ਉਪਲਬਧ ਨਹੀਂ ਕਰਵਾਈ ਗਈ"</string> <string name="NetworkPreferenceSwitchTitle" msgid="4008877505368566980">"ਨੈੱਟਵਰਕ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ"</string> <string name="NetworkPreferenceSwitchSummary" msgid="1203771446683319957">"ਸਿਗਨਲ ਪ੍ਰਾਪਤੀ ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਣ ਲਈ, ਸੈਟਿੰਗਾਂ > ਨੈੱਟਵਰਕ ਅਤੇ ਇੰਟਰਨੈੱਟ > ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ > ਤਰਜੀਹੀ ਨੈੱਟਵਰਕ ਦੀ ਕਿਸਮ \'ਤੇ ਜਾਓ ਅਤੇ ਚੁਣੀ ਗਈ ਕਿਸਮ ਨੂੰ ਬਦਲਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> - <string name="EmergencyCallWarningTitle" msgid="4790413876281901612">"Wi‑Fi ਕਾਲਿੰਗ ਕਿਰਿਆਸ਼ੀਲ ਹੈ"</string> + <string name="EmergencyCallWarningTitle" msgid="4790413876281901612">"ਵਾਈ-ਫਾਈ ਕਾਲਿੰਗ ਕਿਰਿਆਸ਼ੀਲ ਹੈ"</string> <string name="EmergencyCallWarningSummary" msgid="8973232888021643293">"ਸੰਕਟਕਾਲੀਨ ਕਾਲਾਂ ਲਈ ਕਿਸੇ ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ।"</string> <string name="notification_channel_network_alert" msgid="4427736684338074967">"ਸੁਚੇਤਨਾਵਾਂ"</string> <string name="notification_channel_call_forward" msgid="2419697808481833249">"ਕਾਲ ਫਾਰਵਰਡਿੰਗ"</string> <string name="notification_channel_emergency_callback" msgid="6686166232265733921">"ਸੰਕਟਕਾਲੀਨ ਕਾਲਬੈਕ ਮੋਡ"</string> - <string name="notification_channel_mobile_data_status" msgid="4575131690860945836">"ਮੋਬਾਈਲ ਡੈਟੇ ਦੀ ਅਵਸਥਾ"</string> + <string name="notification_channel_mobile_data_status" msgid="4575131690860945836">"ਮੋਬਾਈਲ ਡਾਟੇ ਦੀ ਸਥਿਤੀ"</string> <string name="notification_channel_sms" msgid="3441746047346135073">"SMS ਸੁਨੇਹੇ"</string> <string name="notification_channel_voice_mail" msgid="3954099424160511919">"ਵੌਇਸਮੇਲ ਸੁਨੇਹੇ"</string> <string name="notification_channel_wfc" msgid="2130802501654254801">"ਵਾਈ-ਫਾਈ ਕਾਲਿੰਗ"</string> @@ -117,7 +117,7 @@ <string name="roamingTextSearching" msgid="8360141885972279963">"ਸੇਵਾ ਦੀ ਖੋਜ ਕਰ ਰਿਹਾ ਹੈ"</string> <string name="wfcRegErrorTitle" msgid="2301376280632110664">"ਵਾਈ-ਫਾਈ ਕਾਲਿੰਗ"</string> <string-array name="wfcOperatorErrorAlertMessages"> - <item msgid="3910386316304772394">"ਵਾਈ-ਫਾਈ ਤੋਂ ਕਾਲਾਂ ਕਰਨ ਅਤੇ ਸੁਨੇਹੇ ਭੇਜਣ ਦੇ ਲਈ, ਸਭ ਤੋਂ ਪਹਿਲਾਂ ਆਪਣੇ ਕੈਰੀਅਰ ਨੂੰ ਇਸ ਸੇਵਾ ਦੀ ਸਥਾਪਨਾ ਕਰਨ ਲਈ ਕਹੋ। ਫਿਰ ਸੈਟਿੰਗਾਂ ਵਿੱਚੋਂ ਵਾਈ-ਫਾਈ ਕਾਲਿੰਗ ਨੂੰ ਦੁਬਾਰਾ ਚਾਲੂ ਕਰੋ। (ਗੜਬੜੀ ਕੋਡ: <xliff:g id="CODE">%1$s</xliff:g>)"</item> + <item msgid="3910386316304772394">"ਵਾਈ-ਫਾਈ ਤੋਂ ਕਾਲਾਂ ਕਰਨ ਅਤੇ ਸੁਨੇਹੇ ਭੇਜਣ ਲਈ, ਸਭ ਤੋਂ ਪਹਿਲਾਂ ਆਪਣੇ ਕੈਰੀਅਰ ਨੂੰ ਇਸ ਸੇਵਾ ਦੀ ਸਥਾਪਨਾ ਕਰਨ ਲਈ ਕਹੋ। ਫਿਰ ਸੈਟਿੰਗਾਂ ਵਿੱਚੋਂ ਵਾਈ-ਫਾਈ ਕਾਲਿੰਗ ਨੂੰ ਦੁਬਾਰਾ ਚਾਲੂ ਕਰੋ। (ਗੜਬੜੀ ਕੋਡ: <xliff:g id="CODE">%1$s</xliff:g>)"</item> </string-array> <string-array name="wfcOperatorErrorNotificationMessages"> <item msgid="7472393097168811593">"ਆਪਣੇ ਕੈਰੀਅਰ ਨਾਲ ਪੰਜੀਕਰਨ ਕਰੋ (ਗੜਬੜ ਕੋਡ: <xliff:g id="CODE">%1$s</xliff:g>)"</item> @@ -127,9 +127,9 @@ <item msgid="4397097370387921767">"%s ਵਾਈ-ਫਾਈ ਕਾਲਿੰਗ"</item> </string-array> <string name="wifi_calling_off_summary" msgid="8720659586041656098">"ਬੰਦ"</string> - <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"ਤਰਜੀਹੀ Wi-Fi"</string> + <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"ਤਰਜੀਹੀ ਵਾਈ-ਫਾਈ"</string> <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"ਮੋਬਾਈਲ ਨੂੰ ਤਰਜੀਹ ਹੈ"</string> - <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"ਕੇਵਲ Wi-Fi"</string> + <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"ਸਿਰਫ਼ ਵਾਈ-ਫਾਈ"</string> <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ਅੱਗੇ ਨਹੀਂ ਭੇਜਿਆ ਗਿਆ"</string> <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string> <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> ਸਕਿੰਟਾਂ ਬਾਅਦ"</string> @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"ਸੁਚੇਤਨਾਵਾਂ"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"ਪ੍ਰਚੂਨ ਸਟੋਰਾਂ ਲਈ ਡੈਮੋ"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB ਕਨੈਕਸ਼ਨ"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲ ਰਹੀਆਂ ਐਪਾਂ"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਐਪ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲ ਰਹੀ ਹੈ"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> ਐਪਾਂ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲ ਰਹੀਆਂ ਹਨ"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"ਬੈਟਰੀ ਦੀ ਖਪਤ ਕਰਨ ਵਾਲੀਆਂ ਐਪਾਂ"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਵੱਲੋਂ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> ਐਪਾਂ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀਆਂ ਹਨ"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"ਬੈਟਰੀ ਅਤੇ ਡਾਟਾ ਵਰਤੋਂ ਸਬੰਧੀ ਵੇਰਵਿਆਂ ਲਈ ਟੈਪ ਕਰੋ"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"ਸੁਰੱਖਿਅਤ ਮੋਡ"</string> @@ -300,8 +300,8 @@ <string name="permdesc_statusBar" msgid="8434669549504290975">"ਐਪ ਨੂੰ ਸਥਿਤੀ ਬਾਰ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਉਣ ਜਾਂ ਸਿਸਟਮ ਆਈਕਨਾਂ ਨੂੰ ਜੋੜਨ ਅਤੇ ਹਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string> <string name="permlab_statusBarService" msgid="4826835508226139688">"ਸਥਿਤੀ ਪੱਟੀ ਬਣਨ ਦਿਓ"</string> <string name="permdesc_statusBarService" msgid="716113660795976060">"ਐਪ ਨੂੰ ਸਥਿਤੀ ਬਾਰ ਹੋਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string> - <string name="permlab_expandStatusBar" msgid="1148198785937489264">"ਸਥਿਤੀ ਬਾਰ ਦਾ ਵਿਸਤਾਰ/ਨਸ਼ਟ ਕਰੋ"</string> - <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"ਐਪ ਨੂੰ ਸਥਿਤੀ ਬਾਰ ਦਾ ਵਿਸਤਾਰ ਕਰਨ ਜਾਂ ਨਸ਼ਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string> + <string name="permlab_expandStatusBar" msgid="1148198785937489264">"ਸਥਿਤੀ ਪੱਟੀ ਦਾ ਵਿਸਤਾਰ/ਸੰਖਿਪਤ ਕਰੋ"</string> + <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"ਐਪ ਨੂੰ ਸਥਿਤੀ ਪੱਟੀ ਦਾ ਵਿਸਤਾਰ ਕਰਨ ਜਾਂ ਨਸ਼ਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string> <string name="permlab_install_shortcut" msgid="4279070216371564234">"ਸ਼ਾਰਟਕੱਟ ਇੰਸਟੌਲ ਕਰੋ"</string> <string name="permdesc_install_shortcut" msgid="8341295916286736996">"ਇੱਕ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਉਪਭੋਗਤਾ ਦੇ ਦਖ਼ਲ ਤੋਂ ਬਿਨਾਂ ਹੋਮਸਕ੍ਰੀਨ ਸ਼ਾਰਟਕੱਟ ਜੋੜਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string> <string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"ਸ਼ਾਰਟਕੱਟ ਅਣਇੰਸਟੌਲ ਕਰੋ"</string> @@ -385,11 +385,11 @@ <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"ਵਾਧੂ ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਪ੍ਰਦਾਤਾ ਕਮਾਂਡਾਂ ਤੱਕ ਪਹੁੰਚ"</string> <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"ਐਪ ਨੂੰ ਵਾਧੂ ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਪ੍ਰਦਾਤਾ ਕਮਾਂਡਾਂ ਤੱਕ ਪਹੁੰਚ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਐਪ ਨੂੰ GPS ਜਾਂ ਹੋਰ ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਸਰੋਤਾਂ ਦੇ ਓਪਰੇਸ਼ਨ ਵਿੱਚ ਵਿਘਨ ਪਾਉਣ ਦੀ ਆਗਿਆ ਦੇ ਸਕਦਾ ਹੈ।"</string> <string name="permlab_accessFineLocation" msgid="251034415460950944">"ਸਟੀਕ ਟਿਕਾਣੇ \'ਤੇ ਪਹੁੰਚ ਕਰੋ (GPS ਅਤੇ ਨੈੱਟਵਰਕ-ਆਧਾਰਿਤ)"</string> - <string name="permdesc_accessFineLocation" msgid="5821994817969957884">"ਇਹ ਐਪ GPS ਜਾਂ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ Wi-Fi ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਦੁਆਰਾ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ। ਇਸ ਨਾਲ ਬੈਟਰੀ ਦੀ ਖਪਤ ਵਧ ਸਕਦੀ ਹੈ।"</string> + <string name="permdesc_accessFineLocation" msgid="5821994817969957884">"ਇਹ ਐਪ GPS ਜਾਂ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਵੱਲੋਂ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ। ਇਸ ਨਾਲ ਬੈਟਰੀ ਦੀ ਖਪਤ ਵਧ ਸਕਦੀ ਹੈ।"</string> <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"ਅੰਦਾਜ਼ਨ ਟਿਕਾਣੇ \'ਤੇ ਪਹੁੰਚ ਕਰੋ (ਨੈੱਟਵਰਕ-ਆਧਾਰਿਤ)"</string> - <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"ਇਹ ਐਪ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ Wi-Fi ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਦੁਆਰਾ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ।"</string> - <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"ਇਹ ਐਪ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ Wi-Fi ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਦੁਆਰਾ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਟੀਵੀ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ।"</string> - <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"ਇਹ ਐਪ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ Wi-Fi ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਦੁਆਰਾ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ।"</string> + <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"ਇਹ ਐਪ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਵੱਲੋਂ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ।"</string> + <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"ਇਹ ਐਪ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਵੱਲੋਂ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਟੀਵੀ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ।"</string> + <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"ਇਹ ਐਪ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਵੱਲੋਂ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ।"</string> <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ਆਪਣੀਆਂ ਔਡੀਓ ਸੈਟਿੰਗਾਂ ਬਦਲੋ"</string> <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ਔਪ ਨੂੰ ਗਲੋਬਲ ਔਡੀਓ ਸੈਟਿੰਗਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ ਜਿਵੇਂ ਵੌਲਿਊਮ ਅਤੇ ਆਊਟਪੁਟ ਲਈ ਕਿਹੜਾ ਸਪੀਕਰ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ।"</string> <string name="permlab_recordAudio" msgid="3876049771427466323">"ਔਡੀਓ ਰਿਕਾਰਡ ਕਰਨ"</string> @@ -440,14 +440,14 @@ <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"ਐਪ ਨੂੰ ਨੈੱਟਵਰਕ ਕਨੈਕਟੀਵਿਟੀ ਦੀ ਸਥਿਤੀ ਬਦਲਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string> <string name="permlab_changeTetherState" msgid="5952584964373017960">"ਟੀਥਰ ਕੀਤੀ ਕਨੈਕਟੀਵਿਟੀ ਬਦਲੋ"</string> <string name="permdesc_changeTetherState" msgid="1524441344412319780">"ਐਪ ਨੂੰ ਟੀਥਰ ਕੀਤੀ ਨੈੱਟਵਰਕ ਕਨੈਕਟੀਵਿਟੀ ਦੀ ਸਥਿਤੀ ਬਦਲਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string> - <string name="permlab_accessWifiState" msgid="5202012949247040011">"Wi-Fi ਕਨੈਕਸ਼ਨ ਦੇਖੋ"</string> - <string name="permdesc_accessWifiState" msgid="5002798077387803726">"ਐਪ ਨੂੰ Wi-Fi ਨੈਟਵਰਕਿੰਗ ਬਾਰੇ ਜਾਣਕਾਰੀ ਦੇਖਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਜਿਵੇਂ Wi-Fi ਸਮਰਥਿਤ ਹੈ ਜਾਂ ਨਹੀਂ ਅਤੇ ਕਨੈਕਟ ਕੀਤੀਆਂ Wi-Fi ਡਿਵਾਈਸਾਂ ਦਾ ਨਾਮ।"</string> - <string name="permlab_changeWifiState" msgid="6550641188749128035">"Wi-Fi ਤੋਂ ਕਨੈਕਟ ਅਤੇ ਡਿਸਕਨੈਕਟ ਕਰੋ"</string> - <string name="permdesc_changeWifiState" msgid="7137950297386127533">"ਐਪ ਨੂੰ ਵਾਈ-ਫਾਈ ਪਹੁੰਚ ਬਿੰਦੂਆਂ ਤੇ ਕਨੈਕਟ ਅਤੇ ਇਹਨਾਂ ਤੋਂ ਡਿਸਕਨੈਕਟ ਕਰਨ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈਟਵਰਕਾਂ ਲਈ ਡੀਵਾਈਸ ਸੰਰੂਪਣ ਵਿੱਚ ਬਦਲਾਵ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string> - <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"Wi-Fi ਮਲਟੀਕਾਸਟ ਰਿਸੈਪਸ਼ਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string> - <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"ਐਪ ਨੂੰ ਮਲਟੀਕਾਸਟ ਪਤੇ ਵਰਤਦੇ ਹੋਏ ਇੱਕ Wi-Fi ਨੈੱਟਵਰਕ ਤੇ ਸਾਰੀਆਂ ਡਿਵਾਈਸਾਂ ਤੇ ਭੇਜੇ ਗਏ ਪੈਕੇਟ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਕੇਵਲ ਤੁਹਾਡੀ ਟੈਬਲੇਟ ਨਹੀਂ। ਇਹ ਗ਼ੈਰ-ਮਲਟੀਕਾਸਟ ਮੋਡ ਦੇ ਮੁਕਾਬਲੇ ਵੱਧ ਪਾਵਰ ਵਰਤਦਾ ਹੈ।"</string> - <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"ਐਪ ਨੂੰ ਮਲਟੀਕਾਸਟ ਪਤੇ ਵਰਤਦੇ ਹੋਏ ਇੱਕ Wi-Fi ਨੈੱਟਵਰਕ ਤੇ ਸਾਰੀਆਂ ਡਿਵਾਈਸਾਂ ਤੇ ਭੇਜੇ ਗਏ ਪੈਕੇਟ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਕੇਵਲ ਤੁਹਾਡਾ TV ਨਹੀਂ। ਇਹ ਗ਼ੈਰ-ਮਲਟੀਕਾਸਟ ਮੋਡ ਦੇ ਮੁਕਾਬਲੇ ਵੱਧ ਪਾਵਰ ਵਰਤਦਾ ਹੈ।"</string> - <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"ਐਪ ਨੂੰ ਮਲਟੀਕਾਸਟ ਪਤੇ, ਵਰਤਦੇ ਹੋਏ ਇੱਕ Wi-Fi ਨੈੱਟਵਰਕ ਤੇ ਸਾਰੀਆਂ ਡਿਵਾਈਸਾਂ ਤੇ ਭੇਜੇ ਗਏ ਪੈਕੇਟ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਕੇਵਲ ਤੁਹਾਡਾ ਫੋਨ ਨਹੀਂ। ਇਹ ਗ਼ੈਰ-ਮਲਟੀਕਾਸਟ ਮੋਡ ਦੇ ਮੁਕਾਬਲੇ ਵੱਧ ਪਾਵਰ ਵਰਤਦਾ ਹੈ।"</string> + <string name="permlab_accessWifiState" msgid="5202012949247040011">"ਵਾਈ-ਫਾਈ ਕਨੈਕਸ਼ਨ ਦੇਖੋ"</string> + <string name="permdesc_accessWifiState" msgid="5002798077387803726">"ਐਪ ਨੂੰ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਿੰਗ ਬਾਰੇ ਜਾਣਕਾਰੀ ਦੇਖਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਜਿਵੇਂ ਵਾਈ-ਫਾਈ ਸਮਰਥਿਤ ਹੈ ਜਾਂ ਨਹੀਂ ਅਤੇ ਕਨੈਕਟ ਕੀਤੇ ਵਾਈ-ਫਾਈ ਡੀਵਾਈਸਾਂ ਦਾ ਨਾਮ।"</string> + <string name="permlab_changeWifiState" msgid="6550641188749128035">"ਵਾਈ-ਫਾਈ ਤੋਂ ਕਨੈਕਟ ਅਤੇ ਡਿਸਕਨੈਕਟ ਕਰੋ"</string> + <string name="permdesc_changeWifiState" msgid="7137950297386127533">"ਐਪ ਨੂੰ ਵਾਈ-ਫਾਈ ਪਹੁੰਚ ਬਿੰਦੂਆਂ ਤੇ ਕਨੈਕਟ ਅਤੇ ਇਹਨਾਂ ਤੋਂ ਡਿਸਕਨੈਕਟ ਕਰਨ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ ਲਈ ਡੀਵਾਈਸ ਸੰਰੂਪਣ ਵਿੱਚ ਬਦਲਾਵ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string> + <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"ਵਾਈ-ਫਾਈ ਮਲਟੀਕਾਸਟ ਰਿਸੈਪਸ਼ਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string> + <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"ਐਪ ਨੂੰ ਮਲਟੀਕਾਸਟ ਪਤੇ ਵਰਤਦੇ ਹੋਏ ਇੱਕ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਤੇ ਸਾਰੇ ਡੀਵਾਈਸਾਂ ਤੇ ਭੇਜੇ ਗਏ ਪੈਕੇਟ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਸਿਰਫ਼ ਤੁਹਾਡਾ ਟੈਬਲੈੱਟ ਨਹੀਂ। ਇਹ ਗ਼ੈਰ-ਮਲਟੀਕਾਸਟ ਮੋਡ ਦੇ ਮੁਕਾਬਲੇ ਵੱਧ ਪਾਵਰ ਵਰਤਦਾ ਹੈ।"</string> + <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"ਐਪ ਨੂੰ ਮਲਟੀਕਾਸਟ ਪਤੇ ਵਰਤਦੇ ਹੋਏ ਇੱਕ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਤੇ ਸਾਰੇ ਡੀਵਾਈਸਾਂ ਤੇ ਭੇਜੇ ਗਏ ਪੈਕੇਟ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਸਿਰਫ਼ ਤੁਹਾਡਾ ਟੀਵੀ ਨਹੀਂ। ਇਹ ਗ਼ੈਰ-ਮਲਟੀਕਾਸਟ ਮੋਡ ਦੇ ਮੁਕਾਬਲੇ ਵੱਧ ਪਾਵਰ ਵਰਤਦਾ ਹੈ।"</string> + <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"ਐਪ ਨੂੰ ਮਲਟੀਕਾਸਟ ਪਤੇ, ਵਰਤਦੇ ਹੋਏ ਇੱਕ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਤੇ ਸਾਰੇ ਡੀਵਾਈਸਾਂ ਤੇ ਭੇਜੇ ਗਏ ਪੈਕੇਟ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਸਿਰਫ਼ ਤੁਹਾਡਾ ਫ਼ੋਨ ਨਹੀਂ। ਇਹ ਗ਼ੈਰ-ਮਲਟੀਕਾਸਟ ਮੋਡ ਦੇ ਮੁਕਾਬਲੇ ਵੱਧ ਪਾਵਰ ਵਰਤਦਾ ਹੈ।"</string> <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"Bluetooth ਸੈਟਿੰਗਾਂ ਤੱਕ ਪਹੁੰਚ"</string> <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"ਐਪ ਨੂੰ ਸਥਾਨਕ Bluetooth ਟੈਬਲੇਟ ਨੂੰ ਕੌਂਫਿਗਰ ਕਰਨ ਅਤੇ ਰਿਮੋਟ ਡਿਵਾਈਸਾਂ ਨੂੰ ਖੋਜਣ ਅਤੇ ਉਹਨਾਂ ਨਾਲ ਪੇਅਰ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string> <string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"ਐਪ ਨੂੰ ਸਥਾਨਕ Bluetooth TV ਨੂੰ ਕੌਂਫਿਗਰ ਕਰਨ ਅਤੇ ਰਿਮੋਟ ਡਿਵਾਈਸਾਂ ਨੂੰ ਖੋਜਣ ਅਤੇ ਉਹਨਾਂ ਨਾਲ ਪੇਅਰ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string> @@ -477,7 +477,7 @@ <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"ਉਂਗਲ ਕਾਫ਼ੀ ਹੌਲੀ ਮੂਵ ਹੋਈ। ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> <string-array name="fingerprint_acquired_vendor"> </string-array> - <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਾਰਡਵੇਅਰ ਉਪਲਬਧ ਨਹੀਂ."</string> + <string name="fingerprint_error_hw_not_available" msgid="7955921658939936596">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਾਰਡਵੇਅਰ ਉਪਲਬਧ ਨਹੀਂ।"</string> <string name="fingerprint_error_no_space" msgid="1055819001126053318">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸਟੋਰ ਨਹੀਂ ਕੀਤਾ ਸਕਦਾ। ਕਿਰਪਾ ਕਰਕੇ ਇੱਕ ਮੌਜੂਦਾ ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਟਾਓ।"</string> <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਸਮਾਂ ਸਮਾਪਤ ਹੋ ਗਿਆ ਹੈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ਫਿੰਗਰ"</string> @@ -705,7 +705,7 @@ <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"ਐਮਰਜੈਂਸੀ ਨੰਬਰ"</string> <string name="lockscreen_carrier_default" msgid="6169005837238288522">"ਕੋਈ ਸੇਵਾ ਨਹੀਂ"</string> <string name="lockscreen_screen_locked" msgid="7288443074806832904">"ਸਕ੍ਰੀਨ ਲੌਕ ਕੀਤੀ।"</string> - <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"ਅਨਲੌਕ ਕਰਨ ਲਈ ਮੀਨੂ ਦਬਾਓ ਜਾਂ ਐਮਰਜੈਂਸੀ ਕਾਲ ਕਰੋ।"</string> + <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"ਅਨਲੌਕ ਕਰਨ ਲਈ ਮੀਨੂ ਦਬਾਓ ਜਾਂ ਸੰਕਟਕਾਲੀਨ ਕਾਲ ਕਰੋ।"</string> <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"ਅਨਲੌਕ ਕਰਨ ਲਈ ਮੀਨੂ ਦਬਾਓ।"</string> <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"ਅਨਲੌਕ ਕਰਨ ਲਈ ਪੈਟਰਨ ਡ੍ਰਾ ਕਰੋ"</string> <string name="lockscreen_emergency_call" msgid="5298642613417801888">"ਸੰਕਟਕਾਲ"</string> @@ -826,18 +826,18 @@ <string name="autofill_parish" msgid="8202206105468820057">"ਪੈਰਿਸ਼"</string> <string name="autofill_area" msgid="3547409050889952423">"ਖੇਤਰ"</string> <string name="autofill_emirate" msgid="2893880978835698818">"ਅਮੀਰਾਤ"</string> - <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"ਆਪਣੇ ਵੈਬ ਬੁੱਕਮਾਰਕਸ ਅਤੇ ਇਤਿਹਾਸ ਪੜ੍ਹੋ"</string> - <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"ਐਪ ਨੂੰ ਸਾਰੇ URL ਜਿਨ੍ਹਾਂ ਤੇ ਬ੍ਰਾਊਜ਼ਰ ਨੇ ਵਿਜਿਟ ਕੀਤਾ ਹੈ ਅਤੇ ਬ੍ਰਾਊਜ਼ਰ ਦੇ ਸਾਰੇ ਬੁੱਕਮਾਰਕਾਂ, ਦਾ ਇਤਿਹਾਸ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਨੋਟ: ਇਹ ਅਨੁਮਤੀ ਤੀਜੀ-ਪਾਰਟੀ ਬ੍ਰਾਊਜ਼ਰਾਂ ਜਾਂ ਵੈਬ ਬ੍ਰਾਊਜ਼ਿੰਗ ਸਮਰੱਥਾ ਵਾਲੀਆਂ ਹੋਰਾਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਵੱਲੋਂ ਲਾਗੂ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ।"</string> - <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"ਵੈਬ ਬੁੱਕਮਾਰਕਸ ਅਤੇ ਇਤਿਹਾਸ ਲਿਖੋ"</string> - <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"ਐਪ ਨੂੰ ਬ੍ਰਾਊਜ਼ਰ ਦਾ ਇਤਿਹਾਸ ਅਤੇ ਤੁਹਾਡੀ ਟੈਬਲੇਟ ਤੇ ਸਟੋਰ ਕੀਤੇ ਬੁੱਕਮਾਰਕਾਂ ਨੂੰ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਐਪ ਨੂੰ ਬ੍ਰਾਊਜ਼ਰ ਡੈਟਾ ਮਿਟਾਉਣ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇ ਸਕਦਾ ਹੈ। ਨੋਟ: ਇਹ ਅਨੁਮਤੀ ਤੀਜੀ-ਪਾਰਟੀ ਬ੍ਰਾਊਜ਼ਰਾਂ ਜਾਂ ਵੈਬ ਬ੍ਰਾਊਜ਼ਿੰਗ ਸਮਰੱਥਤਾਵਂ ਵਾਲੀਆਂ ਹੋਰਾਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਵੱਲੋਂ ਲਾਗੂ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ।"</string> - <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"ਐਪ ਨੂੰ ਬ੍ਰਾਊਜ਼ਰ ਦਾ ਇਤਿਹਾਸ ਅਤੇ ਤੁਹਾਡੇ TV ਤੇ ਸਟੋਰ ਕੀਤੇ ਬੁੱਕਮਾਰਕਾਂ ਨੂੰ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਐਪ ਨੂੰ ਬ੍ਰਾਊਜ਼ਰ ਡੈਟਾ ਮਿਟਾਉਣ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇ ਸਕਦਾ ਹੈ। ਨੋਟ: ਇਹ ਅਨੁਮਤੀ ਤੀਜੀ-ਪਾਰਟੀ ਬ੍ਰਾਊਜ਼ਰਾਂ ਜਾਂ ਵੈਬ ਬ੍ਰਾਊਜ਼ਿੰਗ ਸਮਰੱਥਤਾਵਂ ਵਾਲੀਆਂ ਹੋਰਾਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਵੱਲੋਂ ਲਾਗੂ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ।"</string> - <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"ਐਪ ਨੂੰ ਬ੍ਰਾਊਜ਼ਰ ਦਾ ਇਤਿਹਾਸ ਅਤੇ ਤੁਹਾਡੇ ਫੋਨ ਤੇ ਸਟੋਰ ਕੀਤੇ ਬੁੱਕਮਾਰਕਾਂ ਨੂੰ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਐਪ ਨੂੰ ਬ੍ਰਾਊਜ਼ਰ ਡੈਟਾ ਮਿਟਾਉਣ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇ ਸਕਦਾ ਹੈ। ਨੋਟ: ਇਹ ਅਨੁਮਤੀ ਤੀਜੀ-ਪਾਰਟੀ ਬ੍ਰਾਊਜ਼ਰਾਂ ਜਾਂ ਵੈਬ ਬ੍ਰਾਊਜ਼ਿੰਗ ਸਮਰੱਥਤਾਵਂ ਵਾਲੀਆਂ ਹੋਰਾਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਵੱਲੋਂ ਲਾਗੂ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ।"</string> + <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"ਆਪਣੇ ਵੈੱਬ ਬੁੱਕਮਾਰਕ ਅਤੇ ਇਤਿਹਾਸ ਪੜ੍ਹੋ"</string> + <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"ਐਪ ਨੂੰ ਸਾਰੇ URL ਜਿਨ੍ਹਾਂ \'ਤੇ ਬ੍ਰਾਊਜ਼ਰ ਨੇ ਵਿਜਿਟ ਕੀਤਾ ਹੈ ਅਤੇ ਬ੍ਰਾਊਜ਼ਰ ਦੇ ਸਾਰੇ ਬੁੱਕਮਾਰਕਾਂ ਦਾ ਇਤਿਹਾਸ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਨੋਟ: ਇਹ ਇਜਾਜ਼ਤ ਤੀਜੀ-ਪਾਰਟੀ ਬ੍ਰਾਊਜ਼ਰਾਂ ਜਾਂ ਵੈੱਬ ਬ੍ਰਾਊਜ਼ਿੰਗ ਸਮਰੱਥਾ ਵਾਲੀਆਂ ਹੋਰਾਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਵੱਲੋਂ ਲਾਗੂ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ।"</string> + <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"ਵੈੱਬ ਬੁੱਕਮਾਰਕ ਅਤੇ ਇਤਿਹਾਸ ਲਿਖੋ"</string> + <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"ਐਪ ਨੂੰ ਬ੍ਰਾਊਜ਼ਰ ਦਾ ਇਤਿਹਾਸ ਅਤੇ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਬੁੱਕਮਾਰਕਾਂ ਨੂੰ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਐਪ ਨੂੰ ਬ੍ਰਾਊਜ਼ਰ ਡਾਟਾ ਸਾਫ਼ ਕਰਨ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇ ਸਕਦਾ ਹੈ। ਨੋਟ: ਇਹ ਇਜਾਜ਼ਤ ਤੀਜੀ-ਪਾਰਟੀ ਬ੍ਰਾਊਜ਼ਰਾਂ ਜਾਂ ਵੈੱਬ ਬ੍ਰਾਊਜ਼ਿੰਗ ਸਮਰੱਥਾ ਵਾਲੀਆਂ ਹੋਰਾਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਵੱਲੋਂ ਲਾਗੂ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ।"</string> + <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"ਐਪ ਨੂੰ ਬ੍ਰਾਊਜ਼ਰ ਦਾ ਇਤਿਹਾਸ ਅਤੇ ਤੁਹਾਡੇ TV \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਬੁੱਕਮਾਰਕਾਂ ਨੂੰ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਐਪ ਨੂੰ ਬ੍ਰਾਊਜ਼ਰ ਡਾਟਾ ਸਾਫ਼ ਕਰਨ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇ ਸਕਦਾ ਹੈ। ਨੋਟ: ਇਹ ਇਜਾਜ਼ਤ ਤੀਜੀ-ਪਾਰਟੀ ਬ੍ਰਾਊਜ਼ਰਾਂ ਜਾਂ ਵੈੱਬ ਬ੍ਰਾਊਜ਼ਿੰਗ ਸਮਰੱਥਾ ਵਾਲੀਆਂ ਹੋਰਾਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਵੱਲੋਂ ਲਾਗੂ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ।"</string> + <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"ਐਪ ਨੂੰ ਬ੍ਰਾਊਜ਼ਰ ਦਾ ਇਤਿਹਾਸ ਅਤੇ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਬੁੱਕਮਾਰਕਾਂ ਨੂੰ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਐਪ ਨੂੰ ਬ੍ਰਾਊਜ਼ਰ ਡਾਟਾ ਸਾਫ਼ ਕਰਨ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇ ਸਕਦਾ ਹੈ। ਨੋਟ: ਇਹ ਇਜਾਜ਼ਤ ਤੀਜੀ-ਪਾਰਟੀ ਬ੍ਰਾਊਜ਼ਰਾਂ ਜਾਂ ਵੈੱਬ ਬ੍ਰਾਊਜ਼ਿੰਗ ਸਮਰੱਥਾ ਵਾਲੀਆਂ ਹੋਰਾਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਵੱਲੋਂ ਲਾਗੂ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ।"</string> <string name="permlab_setAlarm" msgid="1379294556362091814">"ਇੱਕ ਅਲਾਰਮ ਸੈੱਟ ਕਰੋ"</string> <string name="permdesc_setAlarm" msgid="316392039157473848">"ਐਪ ਨੂੰ ਇੱਕ ਇੰਸਟੌਲ ਕੀਤੀ ਅਲਾਰਮ ਘੜੀ ਐਪ ਵਿੱਚ ਇੱਕ ਅਲਾਰਮ ਸੈਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਕੁਝ ਅਲਾਰਮ ਘੜੀ ਐਪਲ ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਲਾਗੂ ਨਹੀਂ ਵੀ ਕਰ ਸਕਦੇ।"</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"ਵੌਇਸਮੇਲ ਜੋੜੋ"</string> <string name="permdesc_addVoicemail" msgid="6604508651428252437">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਵੌਇਸਮੇਲ ਇਨਬੌਕਸ ਵਿੱਚ ਸੁਨੇਹੇ ਜੋੜਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ਬ੍ਰਾਊਜ਼ਰ ਜਿਓਲੋਕੇਸ਼ਨ ਅਨੁਮਤੀਆਂ ਸੰਸ਼ੋਧਿਤ ਕਰੋ"</string> - <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"ਐਪ ਨੂੰ ਬ੍ਰਾਊਜ਼ਰ ਦੀਆਂ ਜਿਓਲੋਕੇਸ਼ਨ ਅਨੁਮਤੀਆਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਖ਼ਰਾਬ ਐਪਸ ਇਸਦੀ ਵਰਤੋਂ ਆਰਬਿਟਰੇਰੀ ਵੈਬ ਸਾਈਟਾਂ ਨੂੰ ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਜਾਣਕਾਰੀ ਭੇਜਣ ਦੀ ਆਗਿਆ ਦੇਣ ਲਈ ਕਰ ਸਕਦੇ ਹਨ।"</string> + <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"ਐਪ ਨੂੰ ਬ੍ਰਾਊਜ਼ਰ ਦੀਆਂ ਜਿਓਲੋਕੇਸ਼ਨ ਇਜਾਜ਼ਤਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਖਰਾਬ ਐਪਾਂ ਇਸਦੀ ਵਰਤੋਂ ਆਰਬਿਟਰੇਰੀ ਵੈੱਬ ਸਾਈਟਾਂ ਨੂੰ ਟਿਕਾਣਾ ਜਾਣਕਾਰੀ ਭੇਜਣ ਦੀ ਆਗਿਆ ਦੇਣ ਲਈ ਕਰ ਸਕਦੀਆਂ ਹਨ।"</string> <string name="save_password_message" msgid="767344687139195790">"ਕੀ ਤੁਸੀਂ ਚਾਹੁੰਦੇ ਹੋ ਕਿ ਬ੍ਰਾਊਜ਼ਰ ਇਹ ਪਾਸਵਰਡ ਯਾਦ ਰੱਖੇ?"</string> <string name="save_password_notnow" msgid="6389675316706699758">"ਅਜੇ ਨਹੀਂ"</string> <string name="save_password_remember" msgid="6491879678996749466">"ਯਾਦ ਰੱਖੋ"</string> @@ -948,8 +948,8 @@ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ਸਾਲ ਵਿੱਚ</item> </plurals> <string name="VideoView_error_title" msgid="3534509135438353077">"ਵੀਡੀਓ ਸਮੱਸਿਆ"</string> - <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"ਇਹ ਵੀਡੀਓ ਇਸ ਡੀਵਾਈਸ ਤੇ ਸਟ੍ਰੀਮਿੰਗ ਲਈ ਪ੍ਰਮਾਣਿਕ ਨਹੀਂ ਹੈ।"</string> - <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"ਇਹ ਵੀਡੀਓ ਪਲੇ ਨਹੀਂ ਕਰ ਸਕਦਾ।"</string> + <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"ਇਹ ਵੀਡੀਓ ਇਸ ਡੀਵਾਈਸ ਤੇ ਸਟ੍ਰੀਮਿੰਗ ਲਈ ਵੈਧ ਨਹੀਂ ਹੈ।"</string> + <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"ਇਹ ਵੀਡੀਓ ਪਲੇ ਨਹੀਂ ਕਰ ਸਕਦੇ।"</string> <string name="VideoView_error_button" msgid="2822238215100679592">"ਠੀਕ"</string> <string name="relative_time" msgid="1818557177829411417">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="noon" msgid="7245353528818587908">"ਦੁਪਹਿਰ"</string> @@ -1094,46 +1094,46 @@ <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"ਸੂਚਨਾ ਧੁਨੀਆਂ"</string> <string name="ringtone_unknown" msgid="3914515995813061520">"ਅਗਿਆਤ"</string> <plurals name="wifi_available" formatted="false" msgid="7900333017752027322"> - <item quantity="one">Wi-Fi ਨੈੱਟਵਰਕਸ ਉਪਲਬਧ</item> - <item quantity="other">Wi-Fi ਨੈੱਟਵਰਕਸ ਉਪਲਬਧ</item> + <item quantity="one">ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਉਪਲਬਧ</item> + <item quantity="other">ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਉਪਲਬਧ</item> </plurals> <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606"> - <item quantity="one">ਉਪਲਬਧ Wi-Fi ਨੈੱਟਵਰਕ ਖੋਲ੍ਹੋ</item> - <item quantity="other">ਉਪਲਬਧ Wi-Fi ਨੈੱਟਵਰਕ ਖੋਲ੍ਹੋ</item> + <item quantity="one">ਉਪਲਬਧ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਖੋਲ੍ਹੋ</item> + <item quantity="other">ਉਪਲਬਧ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਖੋਲ੍ਹੋ</item> </plurals> - <string name="wifi_available_title" msgid="3817100557900599505">"ਖੁੱਲ੍ਹੇ Wi‑Fi ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਹੋਵੋ"</string> - <string name="wifi_available_title_connecting" msgid="1557292688310330032">"ਖੁੱਲ੍ਹੇ Wi‑Fi ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string> - <string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string> - <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string> + <string name="wifi_available_title" msgid="3817100557900599505">"ਖੁੱਲ੍ਹੇ ਵਾਈ‑ਫਾਈ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਹੋਵੋ"</string> + <string name="wifi_available_title_connecting" msgid="1557292688310330032">"ਖੁੱਲ੍ਹੇ ਵਾਈ‑ਫਾਈ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string> + <string name="wifi_available_title_connected" msgid="7542672851522241548">"ਵਾਈ‑ਫਾਈ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string> + <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"ਵਾਈ‑ਫਾਈ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string> <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"ਸਾਰੇ ਨੈੱਟਵਰਕਾਂ ਨੂੰ ਦੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string> <string name="wifi_available_action_connect" msgid="2635699628459488788">"ਕਨੈਕਟ ਕਰੋ"</string> <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"ਸਾਰੇ ਨੈੱਟਵਰਕ"</string> - <string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi ਨੈੱਟਵਰਕ ਵਿੱਚ ਸਾਈਨ ਇਨ ਕਰੋ"</string> + <string name="wifi_available_sign_in" msgid="9157196203958866662">"ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਵਿੱਚ ਸਾਈਨ-ਇਨ ਕਰੋ"</string> <string name="network_available_sign_in" msgid="1848877297365446605">"ਨੈੱਟਵਰਕ ਤੇ ਸਾਈਨ ਇਨ ਕਰੋ"</string> <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) --> <skip /> - <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi ਦੀ ਕੋਈ ਇੰਟਰਨੈਟ ਪਹੁੰਚ ਨਹੀਂ ਹੈ"</string> + <string name="wifi_no_internet" msgid="8451173622563841546">"ਵਾਈ-ਫਾਈ ਦੀ ਕੋਈ ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ ਨਹੀਂ ਹੈ"</string> <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"ਵਿਕਲਪਾਂ ਲਈ ਟੈਪ ਕਰੋ"</string> <string name="network_switch_metered" msgid="4671730921726992671">"ਬਦਲਕੇ <xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ਲਿਆਂਦਾ ਗਿਆ"</string> <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ਦੀ ਇੰਟਰਨੈੱਟ \'ਤੇ ਪਹੁੰਚ ਨਾ ਹੋਣ \'ਤੇ ਡੀਵਾਈਸ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰਦਾ ਹੈ। ਖਰਚੇ ਲਾਗੂ ਹੋ ਸਕਦੇ ਹਨ।"</string> <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ਤੋਂ ਬਦਲਕੇ <xliff:g id="NEW_NETWORK">%2$s</xliff:g> \'ਤੇ ਕੀਤਾ ਗਿਆ"</string> <string-array name="network_switch_type_name"> - <item msgid="3979506840912951943">"ਮੋਬਾਈਲ ਡੈਟਾ"</item> - <item msgid="75483255295529161">"Wi-Fi"</item> + <item msgid="3979506840912951943">"ਮੋਬਾਈਲ ਡਾਟਾ"</item> + <item msgid="75483255295529161">"ਵਾਈ-ਫਾਈ"</item> <item msgid="6862614801537202646">"ਬਲੂਟੁੱਥ"</item> <item msgid="5447331121797802871">"ਈਥਰਨੈੱਟ"</item> <item msgid="8257233890381651999">"VPN"</item> </string-array> <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"ਇੱਕ ਅਗਿਆਤ ਨੈੱਟਵਰਕ ਕਿਸਮ"</string> - <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਕਰ ਸਕਿਆ"</string> + <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"ਵਾਈ-ਫਾਈ ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਹੋ ਸਕਿਆ"</string> <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ਇਸਦਾ ਇੱਕ ਖ਼ਰਾਬ ਇੰਟਰਨੈਟ ਕਨੈਕਸ਼ਨ ਹੈ।"</string> <string name="wifi_connect_alert_title" msgid="8455846016001810172">"ਕੀ ਕਨੈਕਸ਼ਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string> - <string name="wifi_connect_alert_message" msgid="6451273376815958922">"ਐਪਲੀਕੇਸ਼ਨ %1$s Wifi ਨੈੱਟਵਰਕ %2$s ਨਾਲ ਕਨੈਕਟ ਕਰਨਾ ਚਾਹੁੰਦਾ ਹੈ"</string> + <string name="wifi_connect_alert_message" msgid="6451273376815958922">"ਐਪਲੀਕੇਸ਼ਨ %1$s ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ %2$s ਨਾਲ ਕਨੈਕਟ ਕਰਨਾ ਚਾਹੁੰਦੀ ਹੈ"</string> <string name="wifi_connect_default_application" msgid="7143109390475484319">"ਇੱਕ ਐਪਲੀਕੇਸ਼ਨ"</string> - <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi ਡਾਇਰੈਕਟ"</string> - <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi ਡਾਇਰੈਕਟ ਚਾਲੂ ਕਰੋ। ਇਹ Wi-Fi ਕਲਾਈਂਟ/ਹੌਟਸਪੌਟ ਨੂੰ ਬੰਦ ਕਰ ਦੇਵੇਗਾ।"</string> - <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Wi-Fi ਡਾਇਰੈਕਟ ਚਾਲੂ ਨਹੀਂ ਕਰ ਸਕਿਆ।"</string> - <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi ਡਾਇਰੈਕਟ ਚਾਲੂ ਹੈ।"</string> + <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"ਵਾਈ-ਫਾਈ ਡਾਇਰੈਕਟ"</string> + <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"ਵਾਈ-ਫਾਈ ਡਾਇਰੈਕਟ ਚਾਲੂ ਕਰੋ। ਇਹ ਵਾਈ-ਫਾਈ ਕਲਾਈਂਟ/ਹੌਟਸਪੌਟ ਨੂੰ ਬੰਦ ਕਰ ਦੇਵੇਗਾ।"</string> + <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"ਵਾਈ-ਫਾਈ ਡਾਇਰੈਕਟ ਚਾਲੂ ਨਹੀਂ ਹੋ ਸਕਿਆ।"</string> + <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"ਵਾਈ-ਫਾਈ ਡਾਇਰੈਕਟ ਚਾਲੂ ਹੈ।"</string> <string name="wifi_p2p_enabled_notification_message" msgid="8064677407830620023">"ਸੈਟਿੰਗਾਂ ਲਈ ਟੈਪ ਕਰੋ"</string> <string name="accept" msgid="1645267259272829559">"ਸਵੀਕਾਰ ਕਰੋ"</string> <string name="decline" msgid="2112225451706137894">"ਅਸਵੀਕਾਰ ਕਰੋ"</string> @@ -1143,15 +1143,15 @@ <string name="wifi_p2p_to_message" msgid="248968974522044099">"ਵੱਲ:"</string> <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"ਲੋੜੀਂਦਾ ਪਿੰਨ ਟਾਈਪ ਕਰੋ:"</string> <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"ਪਿੰਨ:"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"ਟੈਬਲੇਟ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤੇ ਜਾਣ ਤੇ Wi-Fi ਤੋਂ ਅਸਥਾਈ ਤੌਰ ਤੇ ਡਿਸਕਨੈਕਟ ਹੋ ਜਾਏਗੀ"</string> - <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="3087858235069421128">"TV <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤੇ ਜਾਣ ਤੇ Wi-Fi ਤੋਂ ਅਸਥਾਈ ਤੌਰ ਤੇ ਡਿਸਕਨੈਕਟ ਹੋ ਜਾਏਗਾ"</string> - <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"ਫੋਨ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤੇ ਜਾਣ ਤੇ Wi-Fi ਤੋਂ ਅਸਥਾਈ ਤੌਰ ਤੇ ਡਿਸਕਨੈਕਟ ਹੋ ਜਾਏਗਾ"</string> + <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"ਟੈਬਲੈੱਟ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤੇ ਜਾਣ ਤੇ ਵਾਈ-ਫਾਈ ਤੋਂ ਅਸਥਾਈ ਤੌਰ ਤੇ ਡਿਸਕਨੈਕਟ ਹੋ ਜਾਏਗਾ"</string> + <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="3087858235069421128">"TV <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤੇ ਜਾਣ ਤੇ ਵਾਈ-ਫਾਈ ਤੋਂ ਅਸਥਾਈ ਤੌਰ ਤੇ ਡਿਸਕਨੈਕਟ ਹੋ ਜਾਏਗਾ"</string> + <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"ਫ਼ੋਨ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤੇ ਜਾਣ ਤੇ ਵਾਈ-ਫਾਈ ਤੋਂ ਅਸਥਾਈ ਤੌਰ ਤੇ ਡਿਸਕਨੈਕਟ ਹੋ ਜਾਏਗਾ"</string> <string name="select_character" msgid="3365550120617701745">"ਅੱਖਰ ਦਾਖਲ ਕਰੋ"</string> <string name="sms_control_title" msgid="7296612781128917719">"SMS ਸੁਨੇਹੇ ਭੇਜ ਰਿਹਾ ਹੈ"</string> <string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ਵੱਡੀ ਸੰਖਿਆ ਵਿੱਚ SMS ਸੁਨੇਹੇ ਭੇਜ ਰਿਹਾ ਹੈ। ਕੀ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ ਸੁਨੇਹੇ ਭੇਜਣਾ ਜਾਰੀ ਰੱਖਣ ਦੀ ਆਗਿਆ ਦੇਣਾ ਚਾਹੁੰਦੇ ਹੋ?"</string> <string name="sms_control_yes" msgid="3663725993855816807">"ਆਗਿਆ ਦਿਓ"</string> <string name="sms_control_no" msgid="625438561395534982">"ਅਸਵੀਕਾਰ ਕਰੋ"</string> - <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ਇਹ <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b> ਨੂੰ ਇੱਕ ਸੁਨੇਹਾ ਭੇਜਣਾ ਚਾਹੁੰਦਾ ਹੈ।"</string> + <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ਇਹ <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b> ਨੂੰ ਇੱਕ ਸੁਨੇਹਾ ਭੇਜਣਾ ਚਾਹੁੰਦੀ ਹੈ।"</string> <string name="sms_short_code_details" msgid="5873295990846059400">"ਇਸ ਨਾਲ "<b>"ਤੁਹਾਡੇ ਮੋਬਾਈਲ ਖਾਤੇ ਤੇ ਖ਼ਰਚੇ"</b>" ਪੈ ਸਕਦੇ ਹਨ।"</string> <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"ਇਸ ਨਾਲ ਤੁਹਾਡੇ ਮੋਬਾਈਲ ਖਾਤੇ ਤੇ ਖ਼ਰਚੇ ਪੈਣਗੇ।"</b></string> <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"ਭੇਜੋ"</string> @@ -1161,7 +1161,7 @@ <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"ਹਮੇਸ਼ਾਂ ਆਗਿਆ ਦਿਓ"</string> <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"ਕਦੇ ਵੀ ਆਗਿਆ ਨਾ ਦਿਓ"</string> <string name="sim_removed_title" msgid="6227712319223226185">"SIM ਕਾਰਡ ਹਟਾਇਆ ਗਿਆ"</string> - <string name="sim_removed_message" msgid="2333164559970958645">"ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਅਣਉਪਲਬਧ ਹੋਵੇਗਾ ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਇੱਕ ਪ੍ਰਮਾਣਿਕ SIM ਕਾਰਡ ਪਾ ਕੇ ਰੀਸਟਾਰਟ ਨਹੀਂ ਕਰਦੇ।"</string> + <string name="sim_removed_message" msgid="2333164559970958645">"ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਅਣਉਪਲਬਧ ਹੋਵੇਗਾ ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਇੱਕ ਪ੍ਰਮਾਣਿਕ ਸਿਮ ਕਾਰਡ ਪਾ ਕੇ ਰੀਸਟਾਰਟ ਨਹੀਂ ਕਰਦੇ।"</string> <string name="sim_done_button" msgid="827949989369963775">"ਹੋ ਗਿਆ"</string> <string name="sim_added_title" msgid="3719670512889674693">"SIM ਕਾਰਡ ਜੋੜਿਆ ਗਿਆ"</string> <string name="sim_added_message" msgid="6599945301141050216">"ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਤੱਕ ਪਹੁੰਚ ਲਈ ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਮੁੜ-ਚਾਲੂ ਕਰੋ।"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ। ਨੈੱਟਵਰਕ ਦੇ ਪ੍ਰਬੰਧਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"ਹਮੇਸ਼ਾਂ-ਚਾਲੂ VPN ਕਨੈਕਟ ਕਰ ਰਿਹਾ ਹੈ..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"ਹਮੇਸ਼ਾਂ-ਚਾਲੂ VPN ਕਨੈਕਟ ਕੀਤਾ"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"ਹਮੇਸ਼ਾ-ਚਾਲੂ VPN ਡਿਸਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"ਹਮੇਸ਼ਾਂ-ਚਾਲੂ VPN ਤੋਂ ਡਿਸਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"ਹਮੇਸ਼ਾਂ-ਚਾਲੂ VPN ਅਸ਼ੁੱਧੀ"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"ਸਥਾਪਤ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"ਨੈੱਟਵਰਕ ਜਾਂ VPN ਸੈਟਿੰਗਾਂ ਬਦਲੋ"</string> <string name="upload_file" msgid="2897957172366730416">"ਫਾਈਲ ਚੁਣੋ"</string> <string name="no_file_chosen" msgid="6363648562170759465">"ਕੋਈ ਫਾਈਲ ਨਹੀਂ ਚੁਣੀ ਗਈ"</string> <string name="reset" msgid="2448168080964209908">"ਰੀਸੈੱਟ ਕਰੋ"</string> @@ -1321,7 +1321,7 @@ <string name="progress_erasing" product="default" msgid="6596988875507043042">"SD ਕਾਰਡ ਮਿਟਾ ਰਿਹਾ ਹੈ…"</string> <string name="share" msgid="1778686618230011964">"ਸਾਂਝਾ ਕਰੋ"</string> <string name="find" msgid="4808270900322985960">"ਲੱਭੋ"</string> - <string name="websearch" msgid="4337157977400211589">"ਵੈਬ ਖੋਜ"</string> + <string name="websearch" msgid="4337157977400211589">"ਵੈੱਬ ਖੋਜ"</string> <string name="find_next" msgid="5742124618942193978">"ਅਗਲਾ ਲੱਭੋ"</string> <string name="find_previous" msgid="2196723669388360506">"ਪਿਛਲਾ ਲੱਭੋ"</string> <string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g> ਵੱਲੋਂ ਟਿਕਾਣਾ ਬੇਨਤੀ"</string> @@ -1363,7 +1363,7 @@ <string name="keyboardview_keycode_shift" msgid="2270748814315147690">"ਸ਼ਿਫ਼ਟ"</string> <string name="keyboardview_keycode_enter" msgid="2985864015076059467">"ਦਾਖਲ ਕਰੋ"</string> <string name="activitychooserview_choose_application" msgid="2125168057199941199">"ਇੱਕ ਐਪ ਚੁਣੋ"</string> - <string name="activitychooserview_choose_application_error" msgid="8624618365481126668">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> ਨੂੰ ਲੌਂਚ ਨਹੀਂ ਕਰ ਸਕਿਆ"</string> + <string name="activitychooserview_choose_application_error" msgid="8624618365481126668">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> ਨੂੰ ਲਾਂਚ ਨਹੀਂ ਕਰ ਸਕਿਆ"</string> <string name="shareactionprovider_share_with" msgid="806688056141131819">"ਇਸ ਨਾਲ ਸਾਂਝਾ ਕਰੋ"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> ਨਾਲ ਸਾਂਝਾ ਕਰੋ"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"ਹੈਂਡਲ ਸਲਾਈਡ ਕਰ ਰਿਹਾ ਹੈ। ਸਪੱਰਸ਼ ਕਰੋ & ਹੋਲਡ ਕਰੋ।"</string> @@ -1384,13 +1384,13 @@ <string name="data_usage_warning_body" msgid="6660692274311972007">"ਵਰਤੋਂ ਅਤੇ ਸੈਟਿੰਗਾਂ ਨੂੰ ਵੇਖਣ ਲਈ ਟੈਪ ਕਰੋ।"</string> <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G ਡੈਟਾ ਸੀਮਾ ਪੂਰੀ ਹੋ ਗਈ"</string> <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"4G ਡੈਟਾ ਸੀਮਾ ਪੂਰੀ ਹੋਈ"</string> - <string name="data_usage_mobile_limit_title" msgid="6561099244084267376">"ਮੋਬਾਈਲ ਡੈਟਾ ਸੀਮਾ ਸਮਾਪਤ ਹੋਈ"</string> - <string name="data_usage_wifi_limit_title" msgid="5803363779034792676">"Wi-Fi ਡੈਟਾ ਸੀਮਾ ਪੂਰੀ ਹੋ ਗਈ"</string> + <string name="data_usage_mobile_limit_title" msgid="6561099244084267376">"ਮੋਬਾਈਲ ਡਾਟਾ ਸੀਮਾ ਸਮਾਪਤ ਹੋਈ"</string> + <string name="data_usage_wifi_limit_title" msgid="5803363779034792676">"ਵਾਈ-ਫਾਈ ਡਾਟਾ ਸੀਮਾ ਪੂਰੀ ਹੋ ਗਈ"</string> <string name="data_usage_limit_body" msgid="291731708279614081">"ਬਾਕੀ ਸਾਇਕਲ ਲਈ ਡੈਟਾ ਰੁਕ ਗਿਆ"</string> <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"2G-3G ਡੈਟਾ ਸੀਮਾ ਵਧ ਗਈ"</string> <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"4G ਡੈਟਾ ਸੀਮਾ ਵਧੀ"</string> - <string name="data_usage_mobile_limit_snoozed_title" msgid="279240572165412168">"ਮੋਬਾਈਲ ਡੈਟਾ ਦੀ ਸੀਮਾ ਵਧ ਗਈ"</string> - <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Wi-Fi ਡੈਟਾ ਸੀਮਾ ਵਧ ਗਈ"</string> + <string name="data_usage_mobile_limit_snoozed_title" msgid="279240572165412168">"ਮੋਬਾਈਲ ਡਾਟਾ ਦੀ ਸੀਮਾ ਵਧ ਗਈ"</string> + <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"ਵਾਈ-ਫਾਈ ਡਾਟਾ ਸੀਮਾ ਵਧ ਗਈ"</string> <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> ਤੋਂ ਵੱਧ ਨਿਰਦਿਸ਼ਟ ਸੀਮਾ।"</string> <string name="data_usage_restricted_title" msgid="5965157361036321914">"ਪਿਛੋਕੜ ਡੈਟਾ ਪ੍ਰਤਿਬੰਧਿਤ"</string> <string name="data_usage_restricted_body" msgid="469866376337242726">"ਪਾਬੰੰਦੀ ਹਟਾਉਣ ਲਈ ਟੈਪ ਕਰੋ।"</string> @@ -1412,7 +1412,7 @@ <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"ਗਤੀਵਿਧੀ ਚੁਣੋ"</string> <string name="share_action_provider_share_with" msgid="5247684435979149216">"ਇਸ ਨਾਲ ਸਾਂਝਾ ਕਰੋ"</string> <string name="sending" msgid="3245653681008218030">"ਭੇਜ ਰਿਹਾ ਹੈ..."</string> - <string name="launchBrowserDefault" msgid="2057951947297614725">"ਕੀ ਬ੍ਰਾਊਜ਼ਰ ਲੌਂਚ ਕਰਨਾ ਹੈ?"</string> + <string name="launchBrowserDefault" msgid="2057951947297614725">"ਕੀ ਬ੍ਰਾਊਜ਼ਰ ਲਾਂਚ ਕਰਨਾ ਹੈ?"</string> <string name="SetupCallDefault" msgid="5834948469253758575">"ਕੀ ਕਾਲ ਸਵੀਕਾਰ ਕਰਨੀ ਹੈ?"</string> <string name="activity_resolver_use_always" msgid="8017770747801494933">"ਹਮੇਸ਼ਾਂ"</string> <string name="activity_resolver_use_once" msgid="2404644797149173758">"ਕੇਵਲ ਇੱਕ ਵਾਰ"</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index ba1cefae3d28..d5bcdfb51c4a 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -254,9 +254,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerty"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Tryb demo dla sklepów"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Połączenie USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Aplikacje działające w tle"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> działa w tle"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"Aplikacje (<xliff:g id="NUMBER">%1$d</xliff:g>) działają w tle"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Aplikacje zużywające baterię"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> zużywa baterię"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"Liczba aplikacji zużywających baterię: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Kliknij, by wyświetlić szczegóły wykorzystania baterii i transmisji danych"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Tryb awaryjny"</string> @@ -1338,9 +1338,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Nawiązano połączenie: <xliff:g id="SESSION">%s</xliff:g>. Dotknij, aby zarządzać siecią."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Łączę ze stałą siecią VPN…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Połączono ze stałą siecią VPN"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Rozłączono ze stałą siecią VPN"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Rozłączono ze stałą siecią VPN"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Błąd stałej sieci VPN"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Kliknij, by skonfigurować"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Zmień ustawienia sieciowe lub ustawienia sieci VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Wybierz plik"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Nie wybrano pliku"</string> <string name="reset" msgid="2448168080964209908">"Resetuj"</string> @@ -1651,7 +1651,7 @@ <item quantity="one">Spróbuj ponownie za sekundę</item> </plurals> <string name="restr_pin_try_later" msgid="973144472490532377">"Spróbuj ponownie później"</string> - <string name="immersive_cling_title" msgid="8394201622932303336">"Widok na pełnym ekranie"</string> + <string name="immersive_cling_title" msgid="8394201622932303336">"Włączony pełny ekran"</string> <string name="immersive_cling_description" msgid="3482371193207536040">"Aby wyjść, przesuń palcem z góry na dół."</string> <string name="immersive_cling_positive" msgid="5016839404568297683">"OK"</string> <string name="done_label" msgid="2093726099505892398">"Gotowe"</string> diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index 45b0fced8890..a7dafde96821 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demonstração na loja"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Conexão USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Apps sendo executados em segundo plano"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está sendo executado em segundo plano"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> apps estão sendo executados em segundo plano"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Apps que estão consumindo a bateria"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está consumindo a bateria"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> apps estão consumindo a bateria"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Tocar para ver detalhes sobre a bateria e o uso de dados"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string> @@ -331,7 +331,7 @@ <string name="permlab_manageProfileAndDeviceOwners" msgid="7918181259098220004">"gerenciar proprietários de perfis e de dispositivos"</string> <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"Permitir que os apps definam os proprietários de perfis e de dispositivos."</string> <string name="permlab_reorderTasks" msgid="2018575526934422779">"reordenar os apps em execução"</string> - <string name="permdesc_reorderTasks" msgid="7734217754877439351">"Permite que o app mova tarefas para o primeiro plano e o plano de fundo, sem sua intervenção."</string> + <string name="permdesc_reorderTasks" msgid="7734217754877439351">"Permite que o app mova tarefas para o primeiro e o segundo plano, sem sua intervenção."</string> <string name="permlab_enableCarMode" msgid="5684504058192921098">"ativar o modo carro"</string> <string name="permdesc_enableCarMode" msgid="4853187425751419467">"Permite que o app ative o modo Carro."</string> <string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"fechar outros apps"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Conectado a <xliff:g id="SESSION">%s</xliff:g>. Toque para gerenciar a rede."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN sempre ativa conectando..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN sempre ativa conectada"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"VPN sempre ativa desconectada"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Desconectado da VPN sempre ativa"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Erro na VPN sempre ativa"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Toque para configurar"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Alterar configurações de VPN ou rede"</string> <string name="upload_file" msgid="2897957172366730416">"Escolher arquivo"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Nenhum arquivo escolhido"</string> <string name="reset" msgid="2448168080964209908">"Redefinir"</string> @@ -1309,7 +1309,7 @@ <string name="disable_tether_notification_message" msgid="2913366428516852495">"Fale com seu administrador para saber detalhes"</string> <string name="back_button_label" msgid="2300470004503343439">"Voltar"</string> <string name="next_button_label" msgid="1080555104677992408">"Avançar"</string> - <string name="skip_button_label" msgid="1275362299471631819">"Ignorar"</string> + <string name="skip_button_label" msgid="1275362299471631819">"Pular"</string> <string name="no_matches" msgid="8129421908915840737">"Não encontrado"</string> <string name="find_on_page" msgid="1946799233822820384">"Localizar na página"</string> <plurals name="matches_found" formatted="false" msgid="1210884353962081884"> @@ -1696,7 +1696,7 @@ <string name="close_button_text" msgid="3937902162644062866">"Fechar"</string> <string name="notification_messaging_title_template" msgid="3452480118762691020">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string> <plurals name="selected_count" formatted="false" msgid="7187339492915744615"> - <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item> + <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionado</item> <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item> </plurals> <string name="default_notification_channel_label" msgid="5929663562028088222">"Sem classificação"</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index f9f81a5f2dd1..95f7828f6f27 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demonstração para retalho"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Ligação USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Aplicações em execução em segundo plano"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"A aplicação <xliff:g id="APP_NAME">%1$s</xliff:g> está a ser executada em segundo plano"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicações estão a ser executadas em segundo plano"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Aplicações que estão a consumir bateria"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"A aplicação <xliff:g id="APP_NAME">%1$s</xliff:g> está a consumir bateria."</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicações estão a consumir bateria."</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Toque para obter detalhes acerca da utilização da bateria e dos dados"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Ligado a <xliff:g id="SESSION">%s</xliff:g>. Toque para gerir a rede."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"A ligar VPN sempre ativa..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN sempre ativa ligada"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"VPN sempre ativa desligada"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Desligado da VPN sempre ativada"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Erro da VPN sempre ativa"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tocar para configurar"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Alterar as notificações da rede ou da VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Escolher ficheiro"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Não foi selecionado nenhum ficheiro"</string> <string name="reset" msgid="2448168080964209908">"Repor"</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index 45b0fced8890..a7dafde96821 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demonstração na loja"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Conexão USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Apps sendo executados em segundo plano"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está sendo executado em segundo plano"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> apps estão sendo executados em segundo plano"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Apps que estão consumindo a bateria"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está consumindo a bateria"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> apps estão consumindo a bateria"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Tocar para ver detalhes sobre a bateria e o uso de dados"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string> @@ -331,7 +331,7 @@ <string name="permlab_manageProfileAndDeviceOwners" msgid="7918181259098220004">"gerenciar proprietários de perfis e de dispositivos"</string> <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"Permitir que os apps definam os proprietários de perfis e de dispositivos."</string> <string name="permlab_reorderTasks" msgid="2018575526934422779">"reordenar os apps em execução"</string> - <string name="permdesc_reorderTasks" msgid="7734217754877439351">"Permite que o app mova tarefas para o primeiro plano e o plano de fundo, sem sua intervenção."</string> + <string name="permdesc_reorderTasks" msgid="7734217754877439351">"Permite que o app mova tarefas para o primeiro e o segundo plano, sem sua intervenção."</string> <string name="permlab_enableCarMode" msgid="5684504058192921098">"ativar o modo carro"</string> <string name="permdesc_enableCarMode" msgid="4853187425751419467">"Permite que o app ative o modo Carro."</string> <string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"fechar outros apps"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Conectado a <xliff:g id="SESSION">%s</xliff:g>. Toque para gerenciar a rede."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN sempre ativa conectando..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN sempre ativa conectada"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"VPN sempre ativa desconectada"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Desconectado da VPN sempre ativa"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Erro na VPN sempre ativa"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Toque para configurar"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Alterar configurações de VPN ou rede"</string> <string name="upload_file" msgid="2897957172366730416">"Escolher arquivo"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Nenhum arquivo escolhido"</string> <string name="reset" msgid="2448168080964209908">"Redefinir"</string> @@ -1309,7 +1309,7 @@ <string name="disable_tether_notification_message" msgid="2913366428516852495">"Fale com seu administrador para saber detalhes"</string> <string name="back_button_label" msgid="2300470004503343439">"Voltar"</string> <string name="next_button_label" msgid="1080555104677992408">"Avançar"</string> - <string name="skip_button_label" msgid="1275362299471631819">"Ignorar"</string> + <string name="skip_button_label" msgid="1275362299471631819">"Pular"</string> <string name="no_matches" msgid="8129421908915840737">"Não encontrado"</string> <string name="find_on_page" msgid="1946799233822820384">"Localizar na página"</string> <plurals name="matches_found" formatted="false" msgid="1210884353962081884"> @@ -1696,7 +1696,7 @@ <string name="close_button_text" msgid="3937902162644062866">"Fechar"</string> <string name="notification_messaging_title_template" msgid="3452480118762691020">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string> <plurals name="selected_count" formatted="false" msgid="7187339492915744615"> - <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item> + <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionado</item> <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item> </plurals> <string name="default_notification_channel_label" msgid="5929663562028088222">"Sem classificação"</string> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 011c0b64935a..efc946c21b4a 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -251,9 +251,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerte"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demonstrație comercială"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Conexiune USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Aplicațiile rulează în fundal"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> rulează în fundal"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicații rulează în fundal"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Aplicațiile consumă bateria"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> folosește bateria"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicații folosesc bateria"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Atingeți pentru mai multe detalii privind bateria și utilizarea datelor"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Mod sigur"</string> @@ -1316,9 +1316,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Conectat la <xliff:g id="SESSION">%s</xliff:g>. Apăsați pentru a gestiona rețeaua."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Se efectuează conectarea la rețeaua VPN activată permanent…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Conectat(ă) la rețeaua VPN activată permanent"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Rețeaua VPN activată permanent a fost deconectată"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Deconectat de la rețeaua VPN activată permanent"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Eroare de rețea VPN activată permanent"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Atingeți pentru a configura"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Modificați setările de rețea sau VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Alegeți un fișier"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Nu au fost găsite fișiere"</string> <string name="reset" msgid="2448168080964209908">"Resetați"</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index f16d76c9d4dd..2ba3c6ea903c 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -254,9 +254,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Уведомления"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Деморежим для магазина"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB-подключение"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Приложения, работающие в фоновом режиме"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> в фоновом режиме"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"Несколько приложений (<xliff:g id="NUMBER">%1$d</xliff:g>) работает в фоновом режиме"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Приложения, расходующие заряд"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" расходует заряд"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"Несколько приложений (<xliff:g id="NUMBER">%1$d</xliff:g>) расходуют заряд"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Нажмите, чтобы проверить энергопотребление и трафик"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Безопасный режим"</string> @@ -1338,9 +1338,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Подключено: \"<xliff:g id="SESSION">%s</xliff:g>\". Нажмите здесь, чтобы изменить настройки сети."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Подключение…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Подключено"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Отключено"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Отключено от постоянной VPN"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Ошибка"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Нажмите, чтобы настроить"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Изменить настройки сети или VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Выбрать файл"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Не выбран файл"</string> <string name="reset" msgid="2448168080964209908">"Сбросить"</string> diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml index c4ce3bdf597a..1c3b2ebb294f 100644 --- a/core/res/res/values-si/strings.xml +++ b/core/res/res/values-si/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"ඇඟවීම්"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"සිල්ලර ආදර්ශනය"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB සම්බන්ධතාවය"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"පසුබිමින් ධාවනය වන යෙදුම්"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> පසුබිමින් ධාවනය වේ"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"යෙදුම් <xliff:g id="NUMBER">%1$d</xliff:g>ක් පසුබිමින් ධාවනය වේ"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"බැටරිය භාවිත කරන යෙදුම්"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> බැටරිය භාවිත කරයි"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"යෙදුම් <xliff:g id="NUMBER">%1$d</xliff:g>ක් බැටරිය භාවිත කරයි"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"බැටරි හා දත්ත භාවිතය පිළිබඳව විස්තර සඳහා තට්ටු කරන්න"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"ආරක්ෂිත ආකාරය"</string> @@ -1296,9 +1296,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> වෙත සම්බන්ධිතයි. ජාලය කළමනාකරණය කිරීමට තට්ටු කරන්න."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"සැමවිටම VPN සම්බන්ධ වෙමින්…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"නිරතුරුවම VPN සම්බන්ධ කර ඇත"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"සැමවිට ක්රියාත්මක VPN විසන්ධි කරන ලදී"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"සැම විට ක්රියාත්මක VPN වෙතින් විසන්ධි විය"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"සැමවිට සක්රිය VPN දෝෂය"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"පිහිටුවීමට තට්ටු කරන්න"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"ජාලය හෝ VPN සැකසීම් වෙනස් කරන්න"</string> <string name="upload_file" msgid="2897957172366730416">"ගොනුව තෝරන්න"</string> <string name="no_file_chosen" msgid="6363648562170759465">"ගොනුවක් තෝරාගෙන නැත"</string> <string name="reset" msgid="2448168080964209908">"යළි පිහිටුවන්න"</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index a728d97210ea..04e70cdcbd5e 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -254,9 +254,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozornenia"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Predajná ukážka"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Pripojenie USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Aplikácie sú spustené na pozadí"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> je spustená na pozadí"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"Niekoľko aplikácií (<xliff:g id="NUMBER">%1$d</xliff:g>) je spustených na pozadí"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Aplikácie spotrebúvajú batériu"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> používa batériu"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"Aplikácie (<xliff:g id="NUMBER">%1$d</xliff:g>) používajú batériu"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Klepnutím zobrazíte podrobnosti o batérii a spotrebe dát"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Núdzový režim"</string> @@ -1338,9 +1338,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Pripojené k relácii <xliff:g id="SESSION">%s</xliff:g>. Po klepnutí môžete sieť spravovať."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Pripájanie k vždy zapnutej sieti VPN…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Pripojenie k vždy zapnutej sieti VPN"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Vždy zapnutá sieť VPN bola odpojená"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Odpojené od vždy zapnutej siete VPN"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Chyba vždy zapnutej siete VPN"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Klepnutím prejdete do Nastavení"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Zmeniť sieť alebo nastavenia VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Zvoliť súbor"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Nie je vybratý žiadny súbor"</string> <string name="reset" msgid="2448168080964209908">"Obnoviť"</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index b410b28233ce..fe433065bbf1 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -254,9 +254,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Opozorila"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Predstavitev za maloprodajo"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Povezava USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Aplikacije se izvajajo v ozadju"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> se izvaja v ozadju"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"Več aplikacij (<xliff:g id="NUMBER">%1$d</xliff:g>) se izvaja v ozadju"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Aplikacije, ki porabljajo energijo akumulatorja"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> porablja energijo akumulatorja"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"Toliko aplikacij porablja energijo akumulatorja: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Dotaknite se za prikaz podrobnosti porabe akumulatorja in prenosa podatkov"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Varni način"</string> @@ -1338,9 +1338,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Povezan z mestom <xliff:g id="SESSION">%s</xliff:g>. Tapnite za upravljanje omrežja."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Povezovanje v stalno vklopljeno navidezno zasebno omrežje ..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Vzpostavljena povezava v stalno vklopljeno navidezno zasebno omrežje"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Povezava s stalno vklopljenim VPN-jem je prekinjena"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Prekinjena povezava s stalno vklopljenim VPN-jem"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Napaka stalno vklopljenega navideznega zasebnega omrežja"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Dotaknite se, če želite nastaviti"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Spremenite omrežne nastavitve ali nastavitve omrežja VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Izberi datoteko"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Nobena datoteka ni izbrana"</string> <string name="reset" msgid="2448168080964209908">"Ponastavi"</string> diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml index e822b46ff280..6a66805d7dde 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Sinjalizimet"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demonstrimi i shitjes me pakicë"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Lidhja USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Aplikacionet që ekzekutohen në sfond"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> po ekzekutohet në sfond"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikacione po ekzekutohen në sfond"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Aplikacionet që konsumojnë baterinë"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> po përdor baterinë"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikacione po përdorin baterinë"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Trokit për detaje mbi baterinë dhe përdorimin e të dhënave"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Modaliteti i sigurisë"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Lidhur me <xliff:g id="SESSION">%s</xliff:g>. Trokit për të menaxhuar rrjetin."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Po lidh VPN-në për aktivizim të përhershëm…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN e lidhur në mënyrë të përhershme"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Rrjeti VPN gjithmonë aktiv u shkëput"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Shkëputur nga VPN-ja gjithmonë e aktivizuar"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Gabimi VPN-je për aktivizimin e përhershëm"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Trokit për ta konfiguruar"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Ndrysho rrjetin ose cilësimet e VPN-së"</string> <string name="upload_file" msgid="2897957172366730416">"Zgjidh skedarin"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Nuk u zgjodh asnjë skedar"</string> <string name="reset" msgid="2448168080964209908">"Rivendos"</string> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index 962b337b7373..aef07ac1451e 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -251,9 +251,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Обавештења"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Режим демонстрације за малопродајне објекте"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB веза"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Апликације покренуте у позадини"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> ради у позадини"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"Апликације (<xliff:g id="NUMBER">%1$d</xliff:g>) су покренуте у позадини"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Апликације које троше батерију"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> користи батерију"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"Апликације (<xliff:g id="NUMBER">%1$d</xliff:g>) користе батерију"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Додирните за детаље о батерији и потрошњи података"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Безбедни режим"</string> @@ -1316,9 +1316,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Повезано са сесијом <xliff:g id="SESSION">%s</xliff:g>. Додирните да бисте управљали мрежом."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Повезивање стално укљученог VPN-а..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Стално укључени VPN је повезан"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Веза са стално укљученим VPN-ом је прекинута"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Веза са увек укљученим VPN-ом је прекинута"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Грешка стално укљученог VPN-а"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Додирните да бисте подесили"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Промените подешавања VPN-а"</string> <string name="upload_file" msgid="2897957172366730416">"Одабери датотеку"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Није изабрана ниједна датотека"</string> <string name="reset" msgid="2448168080964209908">"Ресетуј"</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index 3175c362abb3..d45d94a077cb 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Varningar"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demo för återförsäljare"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB-anslutning"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Appar körs i bakgrunden"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> körs i bakgrunden"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> appar körs i bakgrunden"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Appar som drar batteri"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> drar batteri"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> appar drar batteri"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Tryck för information om batteri- och dataanvändning"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Säkert läge"</string> @@ -1131,7 +1131,7 @@ <string name="wifi_connect_alert_message" msgid="6451273376815958922">"Appen %1$s vill ansluta till Wi-Fi-nätverket %2$s"</string> <string name="wifi_connect_default_application" msgid="7143109390475484319">"En app"</string> <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi direkt"</string> - <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Starta direkt Wi-Fi-användning. Detta inaktiverar Wi-Fi-användning med klient/trådlös surfzon."</string> + <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Starta direkt Wi-Fi-användning. Detta inaktiverar Wi-Fi-användning med klient/surfzon."</string> <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Det gick inte att starta Wi-Fi direkt."</string> <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct är aktiverat"</string> <string name="wifi_p2p_enabled_notification_message" msgid="8064677407830620023">"Tryck för inställningar"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Ansluten till <xliff:g id="SESSION">%s</xliff:g>. Knacka lätt för att hantera nätverket."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Ansluter till Always-on VPN ..."</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Ansluten till Always-on VPN"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Always-on VPN har kopplats från"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Frånkopplad från Always-on VPN"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Fel på Always-on VPN"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tryck för att konfigurera"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Ändra inställningarna för nätverk eller VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Välj fil"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Ingen fil har valts"</string> <string name="reset" msgid="2448168080964209908">"Återställ"</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index 79cb30cc2aa6..8e6b345056a0 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -246,9 +246,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Arifa"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Onyesho la duka la rejareja"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Muunganisho wa USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Programu zinatumika chinichini"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> inatumika chinichini"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"Programu <xliff:g id="NUMBER">%1$d</xliff:g> zinatumika chinichini"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Programu zinazotumia betri"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> inatumia betri"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"Programu <xliff:g id="NUMBER">%1$d</xliff:g> zinatumia betri"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Gonga ili upate maelezo kuhusu betri na matumizi ya data"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Mtindo salama"</string> @@ -978,7 +978,7 @@ <string name="dial" msgid="4204975095406423102">"Simu"</string> <string name="map" msgid="6068210738233985748">"Ramani"</string> <string name="browse" msgid="6993590095938149861">"Kivinjari"</string> - <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Nafasi ya kuhafadhi inakwisha"</string> + <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Nafasi ya kuhifadhi inakaribia kujaa"</string> <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Baadhi ya vipengee vya mfumo huenda visifanye kazi"</string> <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Hifadhi haitoshi kwa ajili ya mfumo. Hakikisha una MB 250 za nafasi ya hifadhi isiyotumika na uanzishe upya."</string> <string name="app_running_notification_title" msgid="8718335121060787914">"<xliff:g id="APP_NAME">%1$s</xliff:g> inatumiwa"</string> @@ -1292,9 +1292,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Imeunganishwa kwa <xliff:g id="SESSION">%s</xliff:g>. Gonga ili kudhibiti mtandao"</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Kila mara VPN iliyowashwa inaunganishwa…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Kila mara VPN iliyowashwa imeunganishwa"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Iwe imeondoa VPN kila wakati"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Imeondolewa kwenye VPN iliyowashwa kila wakati"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Kila mara kuna hitilafu ya VPN iliyowashwa"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Gonga ili uweke mipangilio"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Badilisha mipangilio ya VPN au mtandao"</string> <string name="upload_file" msgid="2897957172366730416">"Chagua faili"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Hakuna faili iliyochaguliwa"</string> <string name="reset" msgid="2448168080964209908">"Weka upya"</string> diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml index 9c45c12ce109..02ed848fc7f1 100644 --- a/core/res/res/values-sw600dp/dimens.xml +++ b/core/res/res/values-sw600dp/dimens.xml @@ -104,9 +104,6 @@ <dimen name="kg_runway_lights_top_margin">-10dp</dimen> <!-- Margin around the various security views --> - <dimen name="keyguard_security_view_margin">12dp</dimen> - - <!-- Margin around the various security views --> <dimen name="keyguard_muliuser_selector_margin">12dp</dimen> <!-- width of ImmersiveModeConfirmation (-1 for match_parent) --> diff --git a/core/res/res/values-sw720dp/dimens.xml b/core/res/res/values-sw720dp/dimens.xml index 2317d1f6909c..ac48ad76d43d 100644 --- a/core/res/res/values-sw720dp/dimens.xml +++ b/core/res/res/values-sw720dp/dimens.xml @@ -111,10 +111,4 @@ <!-- Size of the text under the avator on the multiuser lockscreen. --> <dimen name="keyguard_avatar_name_size">12sp</dimen> - - <!-- Width of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) --> - <dimen name="keyguard_security_width">420dp</dimen> - - <!-- Height of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) --> - <dimen name="keyguard_security_height">420dp</dimen> </resources> diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml index 6a216fb5105a..a6998820466a 100644 --- a/core/res/res/values-ta/strings.xml +++ b/core/res/res/values-ta/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"விழிப்பூட்டல்கள்"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"விற்பனையாளர் டெமோ"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB இணைப்பு"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"பின்னணியில் இயங்கும் பயன்பாடுகள்"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> பின்னணியில் இயங்குகிறது"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> பயன்பாடுகள் பின்னணியில் இயங்குகின்றன"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"பேட்டரியைப் பயன்படுத்தும் பயன்பாடுகள்"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> பயன்பாடு பேட்டரியைப் பயன்படுத்துகிறது"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> பயன்பாடுகள் பேட்டரியைப் பயன்படுத்துகின்றன"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"பேட்டரி மற்றும் தரவு உபயோக விவரங்களைக் காண, தட்டவும்"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"பாதுகாப்பு பயன்முறை"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> உடன் இணைக்கப்பட்டது. நெட்வொர்க்கை நிர்வகிக்க, தட்டவும்."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"எப்போதும் இயங்கும் VPN உடன் இணைக்கிறது…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"எப்போதும் இயங்கும் VPN இணைக்கப்பட்டது"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"எப்போதும் இயங்கும் VPN துண்டிக்கப்பட்டது"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"எப்போதும் இயக்கத்தில் இருக்கும்படி அமைத்த VPN இலிருந்து துண்டிக்கப்பட்டது"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"எப்போதும் இயங்கும் VPN பிழை"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"அமைக்க, தட்டவும்"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"நெட்வொர்க் அல்லது VPN அமைப்புகளை மாற்றவும்"</string> <string name="upload_file" msgid="2897957172366730416">"கோப்பைத் தேர்வுசெய்"</string> <string name="no_file_chosen" msgid="6363648562170759465">"எந்தக் கோப்பும் தேர்வுசெய்யப்படவில்லை"</string> <string name="reset" msgid="2448168080964209908">"மீட்டமை"</string> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index 71496329a0e8..685622a99fdd 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -120,7 +120,7 @@ <item msgid="3910386316304772394">"Wi-Fiతో కాల్లను చేయడానికి మరియు సందేశాలను పంపించడానికి, మొదట ఈ సేవను సెటప్ చేయాల్సిందిగా మీ క్యారియర్కి చెప్పండి. ఆ తర్వాత సెట్టింగ్ల నుండి Wi-Fi కాలింగ్ని మళ్లీ ఆన్ చేయండి. (లోపం కోడ్: <xliff:g id="CODE">%1$s</xliff:g>)"</item> </string-array> <string-array name="wfcOperatorErrorNotificationMessages"> - <item msgid="7472393097168811593">"మీ క్యారియర్తో నమోదు చేయండి (లోపం కోడ్: <xliff:g id="CODE">%1$s</xliff:g>)"</item> + <item msgid="7472393097168811593">"మీ క్యారియర్తో నమోదు చేయండి (ఎర్రర్ కోడ్: <xliff:g id="CODE">%1$s</xliff:g>)"</item> </string-array> <string-array name="wfcSpnFormats"> <item msgid="6830082633573257149">"%s"</item> @@ -138,7 +138,7 @@ <string name="fcComplete" msgid="3118848230966886575">"లక్షణం కోడ్ పూర్తయింది."</string> <string name="fcError" msgid="3327560126588500777">"కనెక్షన్ సమస్య లేదా లక్షణం కోడ్ చెల్లదు."</string> <string name="httpErrorOk" msgid="1191919378083472204">"సరే"</string> - <string name="httpError" msgid="7956392511146698522">"నెట్వర్క్ లోపం ఏర్పడింది."</string> + <string name="httpError" msgid="7956392511146698522">"నెట్వర్క్ ఎర్రర్ ఏర్పడింది."</string> <string name="httpErrorLookup" msgid="4711687456111963163">"URLను కనుగొనడం సాధ్యపడలేదు."</string> <string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"సైట్ ప్రామాణీకరణ స్కీమ్కి మద్దతు లేదు."</string> <string name="httpErrorAuth" msgid="1435065629438044534">"ప్రామాణీకరించడం సాధ్యపడలేదు."</string> @@ -150,10 +150,10 @@ <string name="httpErrorUnsupportedScheme" msgid="5015730812906192208">"ప్రోటోకాల్కి మద్దతు లేదు."</string> <string name="httpErrorFailedSslHandshake" msgid="96549606000658641">"సురక్షిత కనెక్షన్ను వ్యవస్థాపించడం సాధ్యపడలేదు."</string> <string name="httpErrorBadUrl" msgid="3636929722728881972">"URL చెల్లనిది అయినందువలన పేజీని తెరవడం సాధ్యపడలేదు."</string> - <string name="httpErrorFile" msgid="2170788515052558676">"ఫైల్ను ప్రాప్యత చేయడం సాధ్యపడలేదు."</string> + <string name="httpErrorFile" msgid="2170788515052558676">"ఫైల్ను యాక్సెస్ చేయడం సాధ్యపడలేదు."</string> <string name="httpErrorFileNotFound" msgid="6203856612042655084">"అభ్యర్థించిన ఫైల్ను కనుగొనడం సాధ్యపడలేదు."</string> <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"చాలా ఎక్కువ అభ్యర్థనలు ప్రాసెస్ చేయబడుతున్నాయి. తర్వాత మళ్లీ ప్రయత్నించండి."</string> - <string name="notification_title" msgid="8967710025036163822">"<xliff:g id="ACCOUNT">%1$s</xliff:g>కు సైన్ఇన్ లోపం"</string> + <string name="notification_title" msgid="8967710025036163822">"<xliff:g id="ACCOUNT">%1$s</xliff:g>కు సైన్ఇన్ ఎర్రర్"</string> <string name="contentServiceSync" msgid="8353523060269335667">"సమకాలీకరణ"</string> <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"సమకాలీకరణ"</string> <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"చాలా ఎక్కువ <xliff:g id="CONTENT_TYPE">%s</xliff:g> తొలగింపులు."</string> @@ -239,7 +239,7 @@ <string name="notification_channel_car_mode" msgid="3553380307619874564">"కారు మోడ్"</string> <string name="notification_channel_account" msgid="7577959168463122027">"ఖాతా స్థితి"</string> <string name="notification_channel_developer" msgid="7579606426860206060">"డెవలపర్ సందేశాలు"</string> - <string name="notification_channel_updates" msgid="4794517569035110397">"నవీకరణలు"</string> + <string name="notification_channel_updates" msgid="4794517569035110397">"అప్డేట్లు"</string> <string name="notification_channel_network_status" msgid="5025648583129035447">"నెట్వర్క్ స్థితి"</string> <string name="notification_channel_network_alerts" msgid="2895141221414156525">"నెట్వర్క్ హెచ్చరికలు"</string> <string name="notification_channel_network_available" msgid="4531717914138179517">"నెట్వర్క్ అందుబాటులో ఉంది"</string> @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"హెచ్చరికలు"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"రిటైల్ డెమో"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB కనెక్షన్"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"నేపథ్యంలో అమలు అవుతున్న ఆప్లు"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> నేపథ్యంలో అమలు అవుతోంది"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> ఆప్లు నేపథ్యంలో అమలు అవుతున్నాయి"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"బ్యాటరీని ఉపయోగిస్తున్న యాప్లు"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> బ్యాటరీని ఉపయోగిస్తోంది"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> యాప్లు బ్యాటరీని ఉపయోగిస్తున్నాయి"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"బ్యాటరీ మరియు డేటా వినియోగ వివరాల కోసం నొక్కండి"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"సురక్షిత మోడ్"</string> @@ -258,20 +258,20 @@ <string name="user_owner_label" msgid="1119010402169916617">"వ్యక్తిగతానికి మార్చు"</string> <string name="managed_profile_label" msgid="5289992269827577857">"కార్యాలయానికి మార్చు"</string> <string name="permgrouplab_contacts" msgid="3657758145679177612">"పరిచయాలు"</string> - <string name="permgroupdesc_contacts" msgid="6951499528303668046">"మీ పరిచయాలను ప్రాప్యత చేయడానికి"</string> - <string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ని ఉపయోగించి, మీ పరిచయాలను ప్రాప్యత చేయండి"</string> + <string name="permgroupdesc_contacts" msgid="6951499528303668046">"మీ పరిచయాలను యాక్సెస్ చేయడానికి"</string> + <string name="permgrouprequest_contacts" msgid="1601591667800538208">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ని ఉపయోగించి, మీ పరిచయాలను యాక్సెస్ చేయండి"</string> <string name="permgrouplab_location" msgid="7275582855722310164">"స్థానం"</string> - <string name="permgroupdesc_location" msgid="1346617465127855033">"ఈ పరికర స్థానాన్ని ప్రాప్యత చేయడానికి"</string> - <string name="permgrouprequest_location" msgid="8903573681261610809">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ని ఉపయోగించి, ఈ పరికరం యొక్క స్థానాన్ని ప్రాప్యత చేయండి"</string> + <string name="permgroupdesc_location" msgid="1346617465127855033">"ఈ పరికర స్థానాన్ని యాక్సెస్ చేయడానికి"</string> + <string name="permgrouprequest_location" msgid="8903573681261610809">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ని ఉపయోగించి, ఈ పరికరం యొక్క స్థానాన్ని యాక్సెస్ చేయండి"</string> <string name="permgrouplab_calendar" msgid="5863508437783683902">"క్యాలెండర్"</string> - <string name="permgroupdesc_calendar" msgid="3889615280211184106">"మీ క్యాలెండర్ను ప్రాప్యత చేయడానికి"</string> - <string name="permgrouprequest_calendar" msgid="6704529828699071445">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ని ఉపయోగించి, మీ క్యాలెండర్ను ప్రాప్యత చేయండి"</string> + <string name="permgroupdesc_calendar" msgid="3889615280211184106">"మీ క్యాలెండర్ను యాక్సెస్ చేయడానికి"</string> + <string name="permgrouprequest_calendar" msgid="6704529828699071445">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ని ఉపయోగించి, మీ క్యాలెండర్ను యాక్సెస్ చేయండి"</string> <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string> <string name="permgroupdesc_sms" msgid="4656988620100940350">"SMS సందేశాలను పంపడం మరియు వీక్షించడం"</string> <string name="permgrouprequest_sms" msgid="605618939583628306">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ని ఉపయోగించి, SMS సందేశాలను పంపండి మరియు వీక్షించండి"</string> <string name="permgrouplab_storage" msgid="1971118770546336966">"నిల్వ"</string> - <string name="permgroupdesc_storage" msgid="637758554581589203">"మీ పరికరంలోని ఫోటోలు, మీడియా మరియు ఫైల్లను ప్రాప్యత చేయడానికి"</string> - <string name="permgrouprequest_storage" msgid="7429669910547860218">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ని ఉపయోగించి, మీ పరికరంలో ఫోటోలు, మీడియా మరియు ఫైల్లను ప్రాప్యత చేయండి"</string> + <string name="permgroupdesc_storage" msgid="637758554581589203">"మీ పరికరంలోని ఫోటోలు, మీడియా మరియు ఫైల్లను యాక్సెస్ చేయడానికి"</string> + <string name="permgrouprequest_storage" msgid="7429669910547860218">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ని ఉపయోగించి, మీ పరికరంలో ఫోటోలు, మీడియా మరియు ఫైల్లను యాక్సెస్ చేయండి"</string> <string name="permgrouplab_microphone" msgid="171539900250043464">"మైక్రోఫోన్"</string> <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ఆడియోను రికార్డ్ చేయడానికి"</string> <string name="permgrouprequest_microphone" msgid="8065941268709600606">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ని ఉపయోగించి, ఆడియోని రికార్డ్ చేయండి"</string> @@ -282,8 +282,8 @@ <string name="permgroupdesc_phone" msgid="6234224354060641055">"ఫోన్ కాల్లు చేయడం మరియు నిర్వహించడం"</string> <string name="permgrouprequest_phone" msgid="7084161459732093690">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ని ఉపయోగించి, ఫోన్ కాల్లను చేయండి మరియు నిర్వహించండి"</string> <string name="permgrouplab_sensors" msgid="416037179223226722">"శరీర సెన్సార్లు"</string> - <string name="permgroupdesc_sensors" msgid="7147968539346634043">"మీ అత్యంత కీలకమైన గుర్తుల గురించి సెన్సార్ డేటాని ప్రాప్యత చేస్తుంది"</string> - <string name="permgrouprequest_sensors" msgid="8631146669524259656">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ని ఉపయోగించి, మీ అత్యంత కీలకమైన గుర్తుల గురించి సెన్సార్ డేటాని ప్రాప్యత చేయండి"</string> + <string name="permgroupdesc_sensors" msgid="7147968539346634043">"మీ అత్యంత కీలకమైన గుర్తుల గురించి సెన్సార్ డేటాని యాక్సెస్ చేస్తుంది"</string> + <string name="permgrouprequest_sensors" msgid="8631146669524259656">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>ని ఉపయోగించి, మీ అత్యంత కీలకమైన గుర్తుల గురించి సెన్సార్ డేటాని యాక్సెస్ చేయండి"</string> <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"విండో కంటెంట్ను తిరిగి పొందుతుంది"</string> <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"మీరు పరస్పర చర్య చేస్తున్న విండో కంటెంట్ను పరిశీలిస్తుంది."</string> <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"తాకడం ద్వారా విశ్లేషణను ప్రారంభిస్తుంది"</string> @@ -297,11 +297,11 @@ <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"వేలిముద్ర సంజ్ఞలు"</string> <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"పరికరాల వేలిముద్ర సెన్సార్లో నిర్వహించిన సంజ్ఞలను క్యాప్చర్ చేయవచ్చు."</string> <string name="permlab_statusBar" msgid="7417192629601890791">"స్థితి బార్ను నిలిపివేయడం లేదా సవరించడం"</string> - <string name="permdesc_statusBar" msgid="8434669549504290975">"స్థితి బార్ను నిలిపివేయడానికి లేదా సిస్టమ్ చిహ్నాలను జోడించడానికి మరియు తీసివేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_statusBar" msgid="8434669549504290975">"స్థితి బార్ను నిలిపివేయడానికి లేదా సిస్టమ్ చిహ్నాలను జోడించడానికి మరియు తీసివేయడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_statusBarService" msgid="4826835508226139688">"స్థితి పట్టీగా ఉండటం"</string> - <string name="permdesc_statusBarService" msgid="716113660795976060">"స్థితి బార్ ఉండేలా చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_statusBarService" msgid="716113660795976060">"స్థితి బార్ ఉండేలా చేయడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_expandStatusBar" msgid="1148198785937489264">"స్థితి పట్టీని విస్తరింపజేయడం/కుదించడం"</string> - <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"స్థితి బార్ను విస్తరింపజేయడానికి లేదా కుదించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"స్థితి బార్ను విస్తరింపజేయడానికి లేదా కుదించడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_install_shortcut" msgid="4279070216371564234">"సత్వరమార్గాలను ఇన్స్టాల్ చేయడం"</string> <string name="permdesc_install_shortcut" msgid="8341295916286736996">"వినియోగదారు ప్రమేయం లేకుండానే హోమ్స్క్రీన్ సత్వరమార్గాలను జోడించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> <string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"సత్వరమార్గాలను అన్ఇన్స్టాల్ చేయడం"</string> @@ -315,65 +315,65 @@ <string name="permlab_receiveMms" msgid="1821317344668257098">"వచన సందేశాలను (MMS) స్వీకరించడం"</string> <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS సందేశాలను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. యాప్ మీ డివైజ్కు పంపబడిన సందేశాలను మీకు చూపకుండానే పర్యవేక్షించగలదని లేదా తొలగించగలదని దీని అర్థం."</string> <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"సెల్ ప్రసార సందేశాలను చదవడం"</string> - <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"మీ పరికరం స్వీకరించిన సెల్ ప్రసార సందేశాలను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది. సెల్ ప్రసార హెచ్చరికలు అత్యవసర పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని స్థానాల్లో అందించబడతాయి. అత్యవసర సెల్ ప్రసారం స్వీకరించినప్పుడు హానికరమైన అనువర్తనాలు మీ పరికరం యొక్క పనితీరు లేదా నిర్వహణకు అంతరాయం కలిగించవచ్చు."</string> + <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"మీ పరికరం స్వీకరించిన సెల్ ప్రసార సందేశాలను చదవడానికి యాప్ను అనుమతిస్తుంది. సెల్ ప్రసార హెచ్చరికలు అత్యవసర పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని స్థానాల్లో అందించబడతాయి. అత్యవసర సెల్ ప్రసారం స్వీకరించినప్పుడు హానికరమైన యాప్లు మీ పరికరం యొక్క పనితీరు లేదా నిర్వహణకు అంతరాయం కలిగించవచ్చు."</string> <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"చందా చేయబడిన ఫీడ్లను చదవడం"</string> - <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"ప్రస్తుతం సమకాలీకరించిన ఫీడ్ల గురించి వివరాలను పొందడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"ప్రస్తుతం సమకాలీకరించిన ఫీడ్ల గురించి వివరాలను పొందడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_sendSms" msgid="7544599214260982981">"SMS సందేశాలను పంపడం మరియు వీక్షించడం"</string> - <string name="permdesc_sendSms" msgid="7094729298204937667">"SMS సందేశాలు పంపడానికి అనువర్తనాన్ని అనుమతిస్తుంది. దీని వలన ఊహించని ఛార్జీలు విధించబడవచ్చు. హానికరమైన అనువర్తనాలు మీ నిర్ధారణ లేకుండానే సందేశాలను పంపడం ద్వారా మీకు డబ్బు ఖర్చయ్యేలా చేయవచ్చు."</string> + <string name="permdesc_sendSms" msgid="7094729298204937667">"SMS సందేశాలు పంపడానికి యాప్ను అనుమతిస్తుంది. దీని వలన ఊహించని ఛార్జీలు విధించబడవచ్చు. హానికరమైన యాప్లు మీ నిర్ధారణ లేకుండానే సందేశాలను పంపడం ద్వారా మీకు డబ్బు ఖర్చయ్యేలా చేయవచ్చు."</string> <string name="permlab_readSms" msgid="8745086572213270480">"మీ వచన సందేశాలు (SMS లేదా MMS) చదవడం"</string> <string name="permdesc_readSms" product="tablet" msgid="4741697454888074891">"ఈ యాప్ మీ టాబ్లెట్లో నిల్వ చేసిన అన్ని SMS (వచన) సందేశాలను చదవగలదు."</string> <string name="permdesc_readSms" product="tv" msgid="5796670395641116592">"ఈ యాప్ మీ టీవీలో నిల్వ చేసిన అన్ని SMS (వచన) సందేశాలను చదవగలదు."</string> <string name="permdesc_readSms" product="default" msgid="6826832415656437652">"ఈ యాప్ మీ ఫోన్లో నిల్వ చేసిన అన్ని SMS (వచన) సందేశాలను చదవగలదు."</string> <string name="permlab_receiveWapPush" msgid="5991398711936590410">"వచన సందేశాలను (WAP) స్వీకరించడం"</string> - <string name="permdesc_receiveWapPush" msgid="748232190220583385">"WAP సందేశాలను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఈ అనుమతి మీకు పంపబడిన సందేశాలను మీకు చూపకుండానే పర్యవేక్షించగల లేదా తొలగించగల సామర్థ్యాన్ని కలిగి ఉంటుంది."</string> + <string name="permdesc_receiveWapPush" msgid="748232190220583385">"WAP సందేశాలను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. ఈ అనుమతి మీకు పంపబడిన సందేశాలను మీకు చూపకుండానే పర్యవేక్షించగల లేదా తొలగించగల సామర్థ్యాన్ని కలిగి ఉంటుంది."</string> <string name="permlab_getTasks" msgid="6466095396623933906">"అమలవుతున్న అనువర్తనాలను పునరుద్ధరించడం"</string> - <string name="permdesc_getTasks" msgid="7454215995847658102">"ప్రస్తుతం మరియు ఇటీవల అమలవుతున్న విధుల గురించి వివరణాత్మక సమాచారాన్ని తిరిగి పొందడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఇది పరికరంలో ఉపయోగించబడిన అనువర్తనాల గురించి సమాచారాన్ని కనుగొనడానికి అనువర్తనాన్ని అనుమతించవచ్చు."</string> + <string name="permdesc_getTasks" msgid="7454215995847658102">"ప్రస్తుతం మరియు ఇటీవల అమలవుతున్న విధుల గురించి వివరణాత్మక సమాచారాన్ని తిరిగి పొందడానికి యాప్ను అనుమతిస్తుంది. ఇది పరికరంలో ఉపయోగించబడిన యాప్ల గురించి సమాచారాన్ని కనుగొనడానికి యాప్ను అనుమతించవచ్చు."</string> <string name="permlab_manageProfileAndDeviceOwners" msgid="7918181259098220004">"ప్రొఫైల్ మరియు పరికర యజమానులను నిర్వహించడం"</string> <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"ప్రొఫైల్ యజమానులను మరియు పరికరం యజమానిని సెట్ చేయడానికి అనువర్తనాలను అనుమతిస్తుంది."</string> <string name="permlab_reorderTasks" msgid="2018575526934422779">"అమలవుతున్న అనువర్తనాలను మళ్లీ క్రమం చేయడం"</string> <string name="permdesc_reorderTasks" msgid="7734217754877439351">"విధులను ముందుకు మరియు నేపథ్యానికి తరలించడానికి యాప్ను అనుమతిస్తుంది. యాప్ మీ ప్రమేయం లేకుండానే దీన్ని చేయవచ్చు."</string> <string name="permlab_enableCarMode" msgid="5684504058192921098">"కారు మోడ్ను ప్రారంభించడం"</string> - <string name="permdesc_enableCarMode" msgid="4853187425751419467">"కారు మోడ్ను ప్రారంభించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_enableCarMode" msgid="4853187425751419467">"కారు మోడ్ను ప్రారంభించడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"ఇతర అనువర్తనాలను మూసివేయడం"</string> - <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"ఇతర అనువర్తనాల నేపథ్య ప్రాసెస్లను ముగించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. దీని వలన ఇతర అనువర్తనాలు అమలు కాకుండా ఆపివేయబడవచ్చు."</string> + <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"ఇతర యాప్ల నేపథ్య ప్రాసెస్లను ముగించడానికి యాప్ను అనుమతిస్తుంది. దీని వలన ఇతర యాప్లు అమలు కాకుండా ఆపివేయబడవచ్చు."</string> <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"ఈ యాప్ ఇతర యాప్ల పైభాగాన కనిపించగలదు"</string> <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"ఈ యాప్ ఇతర యాప్ల పైభాగాన లేదా స్క్రీన్ యొక్క ఇతర భాగాలపైన కనిపించగలదు. ఇది సాధారణ యాప్ వినియోగానికి అంతరాయం కలిగించవచ్చు మరియు ఆ ఇతర యాప్లు కనిపించే విధానాన్ని మార్చవచ్చు."</string> <string name="permlab_runInBackground" msgid="7365290743781858803">"నేపథ్యంలో అమలు చేయండి"</string> <string name="permdesc_runInBackground" msgid="7370142232209999824">"ఈ యాప్ నేపథ్యంలో అమలు కావచ్చు. దీని వలన ఎక్కువ బ్యాటరీ శక్తి వినియోగం కావచ్చు."</string> <string name="permlab_useDataInBackground" msgid="8694951340794341809">"నేపథ్యంలో డేటాను ఉపయోగించండి"</string> <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"ఈ యాప్ నేపథ్యంలో డేటాను ఉపయోగించవచ్చు. దీని వలన డేటా వినియోగం అధికం కావచ్చు."</string> - <string name="permlab_persistentActivity" msgid="8841113627955563938">"అనువర్తనాన్ని ఎల్లప్పుడూ అమలు చేయడం"</string> + <string name="permlab_persistentActivity" msgid="8841113627955563938">"యాప్ను ఎల్లప్పుడూ అమలు చేయడం"</string> <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"యాప్, దాని భాగాలు మెమరీలో ఉండేలా చేయడానికి దానిని అనుమతిస్తుంది. ఇది ఇతర యాప్లకు అందుబాటులో ఉన్న మెమరీని ఆక్రమిస్తుంది, టాబ్లెట్ నెమ్మదిగా పని చేస్తుంది."</string> <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"యాప్ దానిలోని కొన్ని భాగాలను మెమరీలో ఉంచడానికి దాన్ని అనుమతిస్తుంది. ఇది టీవీ నెమ్మదిగా పని చేసేలా చేస్తూ ఇతర అనువర్తనాలకు అందుబాటులో ఉన్న మెమరీని పరిమితం చేయవచ్చు."</string> <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"యాప్, దాని భాగాలు మెమరీలో ఉండేలా చేయడానికి దానిని అనుమతిస్తుంది. ఇది ఇతర యాప్లకు అందుబాటులో ఉన్న మెమరీని ఆక్రమిస్తుంది, ఫోన్ నెమ్మదిగా పని చేస్తుంది."</string> - <string name="permlab_getPackageSize" msgid="7472921768357981986">"అనువర్తన నిల్వ స్థలాన్ని అంచనా వేయడం"</string> + <string name="permlab_getPackageSize" msgid="7472921768357981986">"యాప్ నిల్వ స్థలాన్ని అంచనా వేయడం"</string> <string name="permdesc_getPackageSize" msgid="3921068154420738296">"యాప్ కోడ్, డేటా మరియు కాష్ పరిమాణాలను తిరిగి పొందడానికి దాన్ని అనుమతిస్తుంది"</string> <string name="permlab_writeSettings" msgid="2226195290955224730">"సిస్టమ్ సెట్టింగ్లను సవరించడం"</string> - <string name="permdesc_writeSettings" msgid="7775723441558907181">"సిస్టమ్ యొక్క సెట్టింగ్ల డేటాను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. హానికరమైన అనువర్తనాలు మీ సిస్టమ్ యొక్క కాన్ఫిగరేషన్ను నాశనం చేయవచ్చు."</string> + <string name="permdesc_writeSettings" msgid="7775723441558907181">"సిస్టమ్ యొక్క సెట్టింగ్ల డేటాను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. హానికరమైన యాప్లు మీ సిస్టమ్ యొక్క కాన్ఫిగరేషన్ను నాశనం చేయవచ్చు."</string> <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"ప్రారంభంలో అమలు చేయడం"</string> - <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"సిస్టమ్ బూటింగ్ను పూర్తి చేసిన వెంటనే దానికదే ప్రారంభించబడటానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఇది టాబ్లెట్ను ప్రారంభించడానికి ఎక్కువ సమయం పట్టేలా చేయవచ్చు మరియు ఎల్లప్పుడూ అమలు చేయడం ద్వారా మొత్తం టాబ్లెట్ను నెమ్మదిగా పని చేయడానికి అనువర్తనాన్ని అనుమతించేలా చేయవచ్చు."</string> + <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"సిస్టమ్ బూటింగ్ను పూర్తి చేసిన వెంటనే దానికదే ప్రారంభించబడటానికి యాప్ను అనుమతిస్తుంది. ఇది టాబ్లెట్ను ప్రారంభించడానికి ఎక్కువ సమయం పట్టేలా చేయవచ్చు మరియు ఎల్లప్పుడూ అమలు చేయడం ద్వారా మొత్తం టాబ్లెట్ను నెమ్మదిగా పని చేయడానికి యాప్ను అనుమతించేలా చేయవచ్చు."</string> <string name="permdesc_receiveBootCompleted" product="tv" msgid="4525890122209673621">"సిస్టమ్ బూటింగ్ను పూర్తి చేసిన వెంటనే యాప్ దానికదే ప్రారంభం కావడానికి అనుమతిస్తుంది. ఇది టీవీ ప్రారంభం కావడానికి ఎక్కువ సమయం పట్టేలా చేయవచ్చు మరియు ఎల్లప్పుడూ అమలు కావడం ద్వారా మొత్తం టాబ్లెట్ పనితీరును నెమ్మది చేయడానికి యాప్ను అనుమతించవచ్చు."</string> - <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"సిస్టమ్ బూటింగ్ను పూర్తి చేసిన వెంటనే దానికదే ప్రారంభించబడటానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఇది ఫోన్ను ప్రారంభించడానికి ఎక్కువ సమయం పట్టేలా చేయవచ్చు మరియు ఎల్లప్పుడూ అమలు చేయడం ద్వారా మొత్తం ఫోన్ను నెమ్మదిగా పని చేయడానికి అనువర్తనాన్ని అనుమతించేలా చేయవచ్చు."</string> + <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"సిస్టమ్ బూటింగ్ను పూర్తి చేసిన వెంటనే దానికదే ప్రారంభించబడటానికి యాప్ను అనుమతిస్తుంది. ఇది ఫోన్ను ప్రారంభించడానికి ఎక్కువ సమయం పట్టేలా చేయవచ్చు మరియు ఎల్లప్పుడూ అమలు చేయడం ద్వారా మొత్తం ఫోన్ను నెమ్మదిగా పని చేయడానికి యాప్ను అనుమతించేలా చేయవచ్చు."</string> <string name="permlab_broadcastSticky" msgid="7919126372606881614">"స్టిక్కీ ప్రసారాన్ని పంపడం"</string> - <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"ప్రసారం ముగిసిన తర్వాత భద్రపరచబడే ప్రసారాలను పంపడానికి అనువర్తనాన్ని అనుమతిస్తుంది. అత్యధిక వినియోగం వలన టాబ్లెట్ నెమ్మదిగా పని చేయవచ్చు లేదా అధిక పరిమాణంలో మెమరీని ఉపయోగించడం వలన అస్థిరంగా మారవచ్చు."</string> + <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"ప్రసారం ముగిసిన తర్వాత భద్రపరచబడే ప్రసారాలను పంపడానికి యాప్ను అనుమతిస్తుంది. అత్యధిక వినియోగం వలన టాబ్లెట్ నెమ్మదిగా పని చేయవచ్చు లేదా అధిక పరిమాణంలో మెమరీని ఉపయోగించడం వలన అస్థిరంగా మారవచ్చు."</string> <string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"ప్రసారం ముగిసిన తర్వాత భద్రపరచబడే ప్రసారాలను పంపడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఎక్కువగా వినియోగిస్తే అధిక పరిమాణంలో మెమరీని ఉపయోగించడం వలన టీవీ నెమ్మదిగా పని చేయవచ్చు లేదా అస్థిరంగా మారవచ్చు."</string> - <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"ప్రసారం ముగిసిన తర్వాత భద్రపరచబడే ప్రసారాలను పంపడానికి అనువర్తనాన్ని అనుమతిస్తుంది. అత్యధిక వినియోగం వలన ఫోన్ నెమ్మదిగా పని చేయవచ్చు లేదా అధిక పరిమాణంలో మెమరీని ఉపయోగించడం వలన అస్థిరంగా మారవచ్చు."</string> + <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"ప్రసారం ముగిసిన తర్వాత భద్రపరచబడే ప్రసారాలను పంపడానికి యాప్ను అనుమతిస్తుంది. అత్యధిక వినియోగం వలన ఫోన్ నెమ్మదిగా పని చేయవచ్చు లేదా అధిక పరిమాణంలో మెమరీని ఉపయోగించడం వలన అస్థిరంగా మారవచ్చు."</string> <string name="permlab_readContacts" msgid="8348481131899886131">"మీ పరిచయాలను చదవడం"</string> - <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"మీరు నిర్దిష్ట వ్యక్తులకు కాల్ చేసిన, ఇమెయిల్ చేసిన లేదా ఇతర మార్గాల్లో కమ్యూనికేట్ చేసిన తరచుదనంతో సహా మీ టాబ్లెట్లో నిల్వ చేయబడిన మీ పరిచయాల గురించి డేటాను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఈ అనుమతి మీ పరిచయ డేటాను సేవ్ చేయడానికి అనువర్తనాలను అనుమతిస్తుంది మరియు హానికరమైన అనువర్తనాలు మీకు తెలియకుండానే పరిచయ డేటాను భాగస్వామ్యం చేయవచ్చు."</string> + <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"మీరు నిర్దిష్ట వ్యక్తులకు కాల్ చేసిన, ఇమెయిల్ చేసిన లేదా ఇతర మార్గాల్లో కమ్యూనికేట్ చేసిన తరచుదనంతో సహా మీ టాబ్లెట్లో నిల్వ చేయబడిన మీ పరిచయాల గురించి డేటాను చదవడానికి యాప్ను అనుమతిస్తుంది. ఈ అనుమతి మీ పరిచయ డేటాను సేవ్ చేయడానికి యాప్లను అనుమతిస్తుంది మరియు హానికరమైన యాప్లు మీకు తెలియకుండానే పరిచయ డేటాను షేర్ చేయవచ్చు."</string> <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"మీరు నిర్దిష్ట వ్యక్తులకు కాల్ చేసిన, ఇమెయిల్ చేసిన లేదా ఇతర మార్గాల్లో కమ్యూనికేట్ చేసిన తరచుదనంతో సహా మీ టీవీలో నిల్వ చేసిన మీ పరిచయాలకు సంబంధించిన డేటాను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఈ అనుమతి మీ పరిచయ డేటాను సేవ్ చేయడానికి అనువర్తనాలను అనుమతిస్తుంది మరియు హానికరమైన అనువర్తనాలు మీకు తెలియకుండానే పరిచయ డేటాను భాగస్వామ్యం చేయవచ్చు."</string> - <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"మీరు నిర్దిష్ట వ్యక్తులకు కాల్ చేసిన, ఇమెయిల్ చేసిన లేదా ఇతర మార్గాల్లో కమ్యూనికేట్ చేసిన తరచుదనంతో సహా మీ ఫోన్లో నిల్వ చేయబడిన మీ పరిచయాల గురించి డేటాను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఈ అనుమతి మీ పరిచయ డేటాను సేవ్ చేయడానికి అనువర్తనాలను అనుమతిస్తుంది మరియు హానికరమైన అనువర్తనాలు మీకు తెలియకుండానే పరిచయ డేటాను భాగస్వామ్యం చేయవచ్చు."</string> + <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"మీరు నిర్దిష్ట వ్యక్తులకు కాల్ చేసిన, ఇమెయిల్ చేసిన లేదా ఇతర మార్గాల్లో కమ్యూనికేట్ చేసిన తరచుదనంతో సహా మీ ఫోన్లో నిల్వ చేయబడిన మీ పరిచయాల గురించి డేటాను చదవడానికి యాప్ను అనుమతిస్తుంది. ఈ అనుమతి మీ పరిచయ డేటాను సేవ్ చేయడానికి యాప్లను అనుమతిస్తుంది మరియు హానికరమైన యాప్లు మీకు తెలియకుండానే పరిచయ డేటాను షేర్ చేయవచ్చు."</string> <string name="permlab_writeContacts" msgid="5107492086416793544">"మీ పరిచయాలను సవరించడం"</string> - <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"మీరు నిర్దిష్ట పరిచయాలకు కాల్ చేసిన, ఇమెయిల్ చేసిన లేదా ఇతర మార్గాల్లో కమ్యూనికేట్ చేసిన తరచుదనంతో సహా మీ టాబ్లెట్లో నిల్వ చేయబడిన మీ పరిచయాల గురించి డేటాను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఈ అనుమతి పరిచయ డేటాను తొలగించడానికి అనువర్తనాలను అనుమతిస్తుంది."</string> + <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"మీరు నిర్దిష్ట పరిచయాలకు కాల్ చేసిన, ఇమెయిల్ చేసిన లేదా ఇతర మార్గాల్లో కమ్యూనికేట్ చేసిన తరచుదనంతో సహా మీ టాబ్లెట్లో నిల్వ చేయబడిన మీ పరిచయాల గురించి డేటాను సవరించడానికి యాప్ను అనుమతిస్తుంది. ఈ అనుమతి పరిచయ డేటాను తొలగించడానికి యాప్లను అనుమతిస్తుంది."</string> <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"మీరు నిర్దిష్ట పరిచయాలకు కాల్ చేసిన, ఇమెయిల్ చేసిన లేదా ఇతర మార్గాల్లో కమ్యూనికేట్ చేసిన తరచుదనంతో సహా మీ టీవీలో నిల్వ చేసిన మీ పరిచయాలకు సంబంధించిన డేటాను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఈ అనుమతి పరిచయ డేటాను తొలగించడానికి అనువర్తనాలను అనుమతిస్తుంది."</string> - <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"మీరు నిర్దిష్ట పరిచయాలకు కాల్ చేసిన, ఇమెయిల్ చేసిన లేదా ఇతర మార్గాల్లో కమ్యూనికేట్ చేసిన తరచుదనంతో సహా మీ ఫోన్లో నిల్వ చేయబడిన మీ పరిచయాల గురించి డేటాను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఈ అనుమతి పరిచయ డేటాను తొలగించడానికి అనువర్తనాలను అనుమతిస్తుంది."</string> + <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"మీరు నిర్దిష్ట పరిచయాలకు కాల్ చేసిన, ఇమెయిల్ చేసిన లేదా ఇతర మార్గాల్లో కమ్యూనికేట్ చేసిన తరచుదనంతో సహా మీ ఫోన్లో నిల్వ చేయబడిన మీ పరిచయాల గురించి డేటాను సవరించడానికి యాప్ను అనుమతిస్తుంది. ఈ అనుమతి పరిచయ డేటాను తొలగించడానికి యాప్లను అనుమతిస్తుంది."</string> <string name="permlab_readCallLog" msgid="3478133184624102739">"కాల్ లాగ్ను చదవడం"</string> <string name="permdesc_readCallLog" msgid="3204122446463552146">"ఈ యాప్ మీ కాల్ చరిత్రను చదవగలదు."</string> <string name="permlab_writeCallLog" msgid="8552045664743499354">"కాల్ లాగ్ను వ్రాయడం"</string> - <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"ఇన్కమింగ్ మరియు అవుట్గోయింగ్ కాల్ల గురించిన డేటాతో సహా మీ టాబ్లెట్ యొక్క కాల్ లాగ్ను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. హానికరమైన అనువర్తనాలు మీ కాల్ లాగ్ను ఎరేజ్ చేయడానికి లేదా సవరించడానికి దీన్ని ఉపయోగించవచ్చు."</string> + <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"ఇన్కమింగ్ మరియు అవుట్గోయింగ్ కాల్ల గురించిన డేటాతో సహా మీ టాబ్లెట్ యొక్క కాల్ లాగ్ను సవరించడానికి యాప్ను అనుమతిస్తుంది. హానికరమైన యాప్లు మీ కాల్ లాగ్ను ఎరేజ్ చేయడానికి లేదా సవరించడానికి దీన్ని ఉపయోగించవచ్చు."</string> <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"ఇన్కమింగ్ మరియు అవుట్గోయింగ్ కాల్లకు సంబంధించిన డేటాతో సహా మీ టీవీ కాల్ లాగ్ను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. హానికరమైన అనువర్తనాలు మీ కాల్ లాగ్ను తీసివేయడానికి లేదా సవరించడానికి దీన్ని ఉపయోగించవచ్చు."</string> - <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"ఇన్కమింగ్ మరియు అవుట్గోయింగ్ కాల్ల గురించిన డేటాతో సహా మీ ఫోన్ యొక్క కాల్ లాగ్ను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. హానికరమైన అనువర్తనాలు మీ కాల్ లాగ్ను ఎరేజ్ చేయడానికి లేదా సవరించడానికి దీన్ని ఉపయోగించవచ్చు."</string> - <string name="permlab_bodySensors" msgid="4683341291818520277">"శరీర సెన్సార్లను (గుండె స్పందన రేటు మానిటర్ల వంటివి) ప్రాప్యత చేయడం"</string> - <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"మీ శారీరక పరిస్థితిని అనగా మీ గుండె స్పందన రేటు వంటి వాటిని పర్యవేక్షించే సెన్సార్ల నుండి డేటాను ప్రాప్యత చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"ఇన్కమింగ్ మరియు అవుట్గోయింగ్ కాల్ల గురించిన డేటాతో సహా మీ ఫోన్ యొక్క కాల్ లాగ్ను సవరించడానికి యాప్ను అనుమతిస్తుంది. హానికరమైన యాప్లు మీ కాల్ లాగ్ను ఎరేజ్ చేయడానికి లేదా సవరించడానికి దీన్ని ఉపయోగించవచ్చు."</string> + <string name="permlab_bodySensors" msgid="4683341291818520277">"శరీర సెన్సార్లను (గుండె స్పందన రేటు మానిటర్ల వంటివి) యాక్సెస్ చేయండి"</string> + <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"మీ శారీరక పరిస్థితిని అనగా మీ గుండె స్పందన రేటు వంటి వాటిని పర్యవేక్షించే సెన్సార్ల నుండి డేటాను యాక్సెస్ చేయడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_readCalendar" msgid="6716116972752441641">"క్యాలెండర్ ఈవెంట్లు మరియు వివరాలను చదవడం"</string> <string name="permdesc_readCalendar" product="tablet" msgid="4993979255403945892">"ఈ యాప్ మీ టాబ్లెట్లో నిల్వ చేసిన క్యాలెండర్ ఈవెంట్లన్నీ చదవగలదు మరియు మీ క్యాలెండర్ డేటాను షేర్ చేయగలదు లేదా సేవ్ చేయగలదు."</string> <string name="permdesc_readCalendar" product="tv" msgid="8837931557573064315">"ఈ యాప్ మీ టీవీలో నిల్వ చేసిన క్యాలెండర్ ఈవెంట్లన్నీ చదవగలదు మరియు మీ క్యాలెండర్ డేటాను షేర్ చేయగలదు లేదా సేవ్ చేయగలదు."</string> @@ -382,16 +382,16 @@ <string name="permdesc_writeCalendar" product="tablet" msgid="1675270619903625982">"ఈ యాప్ మీ టాబ్లెట్లో క్యాలెండర్ ఈవెంట్లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ యజమానుల నుండి వచ్చినట్లుగా సందేశాలను పంపగలదు లేదా ఈవెంట్లను వాటి యజమానులకు తెలియకుండానే మార్చగలదు."</string> <string name="permdesc_writeCalendar" product="tv" msgid="9017809326268135866">"ఈ యాప్ మీ టీవీలో క్యాలెండర్ ఈవెంట్లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ యజమానుల నుండి వచ్చినట్లుగా సందేశాలను పంపగలదు లేదా ఈవెంట్లను వాటి యజమానులకు తెలియకుండానే మార్చగలదు."</string> <string name="permdesc_writeCalendar" product="default" msgid="7592791790516943173">"ఈ యాప్ మీ ఫోన్లో క్యాలెండర్ ఈవెంట్లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ యజమానుల నుండి వచ్చినట్లుగా సందేశాలను పంపగలదు లేదా ఈవెంట్లను వాటి యజమానులకు తెలియకుండానే మార్చగలదు."</string> - <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"అదనపు స్థాన ప్రదాత ఆదేశాలను ప్రాప్యత చేయడం"</string> + <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"అదనపు స్థాన ప్రదాత ఆదేశాలను యాక్సెస్ చేయడం"</string> <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"అదనపు స్థాన ప్రదాత ఆదేశాలను యాక్సెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. ఇది GPS లేదా ఇతర స్థాన మూలాల నిర్వహణలో యాప్ ప్రమేయం ఉండేలా అనుమతించవచ్చు."</string> - <string name="permlab_accessFineLocation" msgid="251034415460950944">"ఖచ్చితమైన స్థానాన్ని (GPS మరియు నెట్వర్క్-ఆధారితం) ప్రాప్యత చేయడం"</string> + <string name="permlab_accessFineLocation" msgid="251034415460950944">"ఖచ్చితమైన స్థానాన్ని (GPS మరియు నెట్వర్క్-ఆధారితం) యాక్సెస్ చేయడం"</string> <string name="permdesc_accessFineLocation" msgid="5821994817969957884">"ఈ యాప్ GPS ఆధారంగా లేదా సెల్ టవర్లు, Wi-Fi నెట్వర్క్ల వంటి నెట్వర్క్ స్థాన మూలాధారాల ఆధారంగా మీ స్థానాన్ని తెలుసుకోగలదు. యాప్ ఉపయోగించడానికి మీ ఫోన్లో ఈ స్థాన సేవలను తప్పనిసరిగా ఆన్ చేయాలి మరియు అందుబాటులో ఉండాలి. ఇది బ్యాటరీ వినియోగాన్ని పెంచవచ్చు."</string> - <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"ఇంచుమించు స్థానాన్ని (నెట్వర్క్-ఆధారితం) ప్రాప్యత చేయడం"</string> + <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"ఇంచుమించు స్థానాన్ని (నెట్వర్క్-ఆధారితం) యాక్సెస్ చేయడం"</string> <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"ఈ యాప్ సెల్ టవర్లు మరియు Wi-Fi నెట్వర్క్ల వంటి నెట్వర్క్ మూలాధారాల ఆధారంగా మీ స్థానాన్ని తెలుసుకోగలదు. యాప్ ఉపయోగించడానికి మీ టాబ్లెట్లో ఈ స్థాన సేవలను తప్పనిసరిగా ఆన్ చేయాలి మరియు అందుబాటులో ఉండాలి."</string> <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"ఈ యాప్ సెల్ టవర్లు మరియు Wi-Fi నెట్వర్క్ల వంటి నెట్వర్క్ మూలాధారాల ఆధారంగా మీ స్థానాన్ని తెలుసుకోగలదు. యాప్ ఉపయోగించడానికి మీ టీవీలో ఈ స్థాన సేవలను తప్పనిసరిగా ఆన్ చేయాలి మరియు అందుబాటులో ఉండాలి."</string> <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"ఈ యాప్ సెల్ టవర్లు మరియు Wi-Fi నెట్వర్క్ల వంటి నెట్వర్క్ మూలాధారాల ఆధారంగా మీ స్థానాన్ని తెలుసుకోగలదు. యాప్ ఉపయోగించడానికి మీ ఫోన్లో ఈ స్థాన సేవలను తప్పనిసరిగా ఆన్ చేయాలి మరియు అందుబాటులో ఉండాలి."</string> <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"మీ ఆడియో సెట్టింగ్లను మార్చడం"</string> - <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"వాల్యూమ్ మరియు అవుట్పుట్ కోసం ఉపయోగించాల్సిన స్పీకర్ వంటి సార్వజనీన ఆడియో సెట్టింగ్లను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"వాల్యూమ్ మరియు అవుట్పుట్ కోసం ఉపయోగించాల్సిన స్పీకర్ వంటి సార్వజనీన ఆడియో సెట్టింగ్లను సవరించడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_recordAudio" msgid="3876049771427466323">"ఆడియోను రికార్డ్ చేయడం"</string> <string name="permdesc_recordAudio" msgid="4245930455135321433">"ఈ యాప్ మైక్రోఫోన్ని ఉపయోగించి ఎప్పుడైనా ఆడియోను రికార్డ్ చేయగలదు."</string> <string name="permlab_sim_communication" msgid="2935852302216852065">"SIMకి ఆదేశాలను పంపడం"</string> @@ -399,75 +399,75 @@ <string name="permlab_camera" msgid="3616391919559751192">"చిత్రాలు మరియు వీడియోలు తీయడం"</string> <string name="permdesc_camera" msgid="5392231870049240670">"ఈ యాప్ కెమెరాను ఉపయోగించి ఎప్పుడైనా చిత్రాలను తీయగలదు మరియు వీడియోలను రికార్డ్ చేయగలదు."</string> <string name="permlab_vibrate" msgid="7696427026057705834">"వైబ్రేషన్ను నియంత్రించడం"</string> - <string name="permdesc_vibrate" msgid="6284989245902300945">"వైబ్రేటర్ను నియంత్రించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_vibrate" msgid="6284989245902300945">"వైబ్రేటర్ను నియంత్రించడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_callPhone" msgid="3925836347681847954">"నేరుగా కాల్ చేసే ఫోన్ నంబర్లు"</string> - <string name="permdesc_callPhone" msgid="3740797576113760827">"మీ ప్రమేయం లేకుండా ఫోన్ నంబర్లకు కాల్ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది. దీని వలన అనుకోని ఛార్జీలు విధించబడవచ్చు లేదా కాల్లు రావచ్చు. ఇది అత్యవసర నంబర్లకు కాల్ చేయడానికి అనువర్తనాన్ని అనుమతించదని గుర్తుంచుకోండి. హానికరమైన అనువర్తనాలు మీ నిర్ధారణ లేకుండానే కాల్లు చేయడం ద్వారా మీకు డబ్బు ఖర్చయ్యేలా చేయవచ్చు."</string> - <string name="permlab_accessImsCallService" msgid="3574943847181793918">"IMS కాల్ సేవ ప్రాప్యత అనుమతి"</string> + <string name="permdesc_callPhone" msgid="3740797576113760827">"మీ ప్రమేయం లేకుండా ఫోన్ నంబర్లకు కాల్ చేయడానికి యాప్ను అనుమతిస్తుంది. దీని వలన అనుకోని ఛార్జీలు విధించబడవచ్చు లేదా కాల్లు రావచ్చు. ఇది అత్యవసర నంబర్లకు కాల్ చేయడానికి యాప్ను అనుమతించదని గుర్తుంచుకోండి. హానికరమైన యాప్లు మీ నిర్ధారణ లేకుండానే కాల్లు చేయడం ద్వారా మీకు డబ్బు ఖర్చయ్యేలా చేయవచ్చు."</string> + <string name="permlab_accessImsCallService" msgid="3574943847181793918">"IMS కాల్ సేవ యాక్సెస్ అనుమతి"</string> <string name="permdesc_accessImsCallService" msgid="8992884015198298775">"మీ ప్రమేయం లేకుండా కాల్లు చేయడం కోసం IMS సేవను ఉపయోగించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> <string name="permlab_readPhoneState" msgid="9178228524507610486">"ఫోన్ స్థితి మరియు గుర్తింపుని చదవడం"</string> - <string name="permdesc_readPhoneState" msgid="1639212771826125528">"పరికరం యొక్క ఫోన్ లక్షణాలను ప్రాప్యత చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఈ అనుమతి ఫోన్ నంబర్ మరియు పరికరం IDలను, కాల్ సక్రియంగా ఉందా లేదా అనే విషయాన్ని మరియు కాల్ ద్వారా కనెక్ట్ చేయబడిన రిమోట్ నంబర్ను కనుగొనడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_readPhoneState" msgid="1639212771826125528">"పరికరం యొక్క ఫోన్ ఫీచర్లను యాక్సెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. ఈ అనుమతి ఫోన్ నంబర్ మరియు పరికరం IDలను, కాల్ సక్రియంగా ఉందా లేదా అనే విషయాన్ని మరియు కాల్ ద్వారా కనెక్ట్ చేయబడిన రిమోట్ నంబర్ను కనుగొనడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_manageOwnCalls" msgid="1503034913274622244">"కాల్లను సిస్టమ్ ద్వారా వెళ్లేలా చేయి"</string> <string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"కాలింగ్ అనుభవాన్ని మెరుగుపరచడం కోసం తన కాల్లను సిస్టమ్ ద్వారా వెళ్లేలా చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"ఫోన్ నంబర్లను చదువు"</string> - <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"పరికరం యొక్క ఫోన్ నంబర్లను ప్రాప్యత చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"పరికరం యొక్క ఫోన్ నంబర్లను యాక్సెస్ చేయడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"టాబ్లెట్ను నిద్రావస్థకు వెళ్లనీయకుండా నిరోధించడం"</string> <string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"టీవీ నిద్రావస్థకు వెళ్లకుండా నిరోధించడం"</string> <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ఫోన్ను నిద్రావస్థకు వెళ్లనీయకుండా నిరోధించడం"</string> - <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"నిద్రావస్థకి వెళ్లకుండా టాబ్లెట్ను నిరోధించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"నిద్రావస్థకి వెళ్లకుండా టాబ్లెట్ను నిరోధించడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permdesc_wakeLock" product="tv" msgid="3208534859208996974">"టీవీ నిద్రావస్థకు వెళ్లకుండా నిరోధించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> - <string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"నిద్రావస్థకి వెళ్లకుండా ఫోన్ను నిరోధించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"నిద్రావస్థకి వెళ్లకుండా ఫోన్ను నిరోధించడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_transmitIr" msgid="7545858504238530105">"ఇన్ఫ్రారెడ్ ప్రసరణ"</string> <string name="permdesc_transmitIr" product="tablet" msgid="5358308854306529170">"టాబ్లెట్ యొక్క ఇన్ఫ్రారెడ్ ట్రాన్స్మిటర్ను ఉపయోగించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> <string name="permdesc_transmitIr" product="tv" msgid="3926790828514867101">"టీవీ ఇన్ఫ్రారెడ్ ట్రాన్స్మిటర్ని ఉపయోగించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> <string name="permdesc_transmitIr" product="default" msgid="7957763745020300725">"ఫోన్ యొక్క ఇన్ఫ్రారెడ్ ట్రాన్స్మిటర్ను ఉపయోగించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> <string name="permlab_setWallpaper" msgid="6627192333373465143">"వాల్పేపర్ను సెట్ చేయడం"</string> - <string name="permdesc_setWallpaper" msgid="7373447920977624745">"సిస్టమ్ వాల్పేపర్ను సెట్ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_setWallpaper" msgid="7373447920977624745">"సిస్టమ్ వాల్పేపర్ను సెట్ చేయడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_setWallpaperHints" msgid="3278608165977736538">"మీ వాల్పేపర్ పరిమాణాన్ని సర్దుబాటు చేయడం"</string> - <string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"సిస్టమ్ వాల్పేపర్ పరిమాణం సూచనలను సెట్ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"సిస్టమ్ వాల్పేపర్ పరిమాణం సూచనలను సెట్ చేయడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_setTimeZone" msgid="2945079801013077340">"సమయ మండలిని సెట్ చేయడం"</string> - <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"టాబ్లెట్ యొక్క సమయ మండలిని మార్చడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"టాబ్లెట్ యొక్క సమయ మండలిని మార్చడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permdesc_setTimeZone" product="tv" msgid="888864653946175955">"టీవీ సమయ మండలిని మార్చడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> - <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"ఫోన్ యొక్క సమయ మండలిని మార్చడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"ఫోన్ యొక్క సమయ మండలిని మార్చడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_getAccounts" msgid="1086795467760122114">"పరికరంలో ఖాతాలను కనుగొనడం"</string> - <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"టాబ్లెట్కు తెలిసిన ఖాతాల జాబితాను పొందడానికి అనువర్తనాన్ని అనుమతిస్తుంది. దీనిలో మీరు ఇన్స్టాల్ చేసిన అనువర్తనాల ద్వారా సృష్టించబడిన ఖాతాలు ఏవైనా ఉండవచ్చు."</string> + <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"టాబ్లెట్కు తెలిసిన ఖాతాల జాబితాను పొందడానికి యాప్ను అనుమతిస్తుంది. దీనిలో మీరు ఇన్స్టాల్ చేసిన యాప్ల ద్వారా సృష్టించబడిన ఖాతాలు ఏవైనా ఉండవచ్చు."</string> <string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"టీవీకి తెలిసిన ఖాతాల జాబితాను పొందడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఇందులో మీరు ఇన్స్టాల్ చేసిన అనువర్తనాల ద్వారా సృష్టించబడిన ఖాతాలు కూడా ఉండవచ్చు."</string> - <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"ఫోన్కు తెలిసిన ఖాతాల జాబితాను పొందడానికి అనువర్తనాన్ని అనుమతిస్తుంది. దీనిలో మీరు ఇన్స్టాల్ చేసిన అనువర్తనాల ద్వారా సృష్టించబడిన ఖాతాలు ఏవైనా ఉండవచ్చు."</string> + <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"ఫోన్కు తెలిసిన ఖాతాల జాబితాను పొందడానికి యాప్ను అనుమతిస్తుంది. దీనిలో మీరు ఇన్స్టాల్ చేసిన యాప్ల ద్వారా సృష్టించబడిన ఖాతాలు ఏవైనా ఉండవచ్చు."</string> <string name="permlab_accessNetworkState" msgid="4951027964348974773">"నెట్వర్క్ కనెక్షన్లను వీక్షించడం"</string> - <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"ఏ నెట్వర్క్లు ఉన్నాయి మరియు కనెక్ట్ చేయబడ్డాయి వంటి నెట్వర్క్ కనెక్షన్ల గురించి సమాచారాన్ని వీక్షించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"ఏ నెట్వర్క్లు ఉన్నాయి మరియు కనెక్ట్ చేయబడ్డాయి వంటి నెట్వర్క్ కనెక్షన్ల గురించి సమాచారాన్ని వీక్షించడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_createNetworkSockets" msgid="7934516631384168107">"పూర్తి నెట్వర్క్ ప్రాప్యతను కలిగి ఉండటం"</string> - <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"నెట్వర్క్ సాకెట్లను సృష్టించడానికి మరియు అనుకూల నెట్వర్క్ ప్రోటోకాల్లను ఉపయోగించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. బ్రౌజర్ మరియు ఇతర అనువర్తనాలు ఇంటర్నెట్కు డేటా పంపడానికి మార్గాలను అందిస్తాయి, కనుక ఇంటర్నెట్కు డేటా పంపడానికి ఈ అనుమతి అవసరం లేదు."</string> + <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"నెట్వర్క్ సాకెట్లను సృష్టించడానికి మరియు అనుకూల నెట్వర్క్ ప్రోటోకాల్లను ఉపయోగించడానికి యాప్ను అనుమతిస్తుంది. బ్రౌజర్ మరియు ఇతర యాప్లు ఇంటర్నెట్కు డేటా పంపడానికి మార్గాలను అందిస్తాయి, కనుక ఇంటర్నెట్కు డేటా పంపడానికి ఈ అనుమతి అవసరం లేదు."</string> <string name="permlab_changeNetworkState" msgid="958884291454327309">"నెట్వర్క్ కనెక్టివిటీని మార్చడం"</string> - <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"నెట్వర్క్ కనెక్టివిటీ యొక్క స్థితిని మార్చడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"నెట్వర్క్ కనెక్టివిటీ యొక్క స్థితిని మార్చడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_changeTetherState" msgid="5952584964373017960">"టీథర్ చేయబడిన కనెక్టివిటీని మార్చడం"</string> - <string name="permdesc_changeTetherState" msgid="1524441344412319780">"టీథర్ చేసిన నెట్వర్క్ కనెక్టివిటీ యొక్క స్థితిని మార్చడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_changeTetherState" msgid="1524441344412319780">"టీథర్ చేసిన నెట్వర్క్ కనెక్టివిటీ యొక్క స్థితిని మార్చడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_accessWifiState" msgid="5202012949247040011">"Wi-Fi కనెక్షన్లను వీక్షించడం"</string> <string name="permdesc_accessWifiState" msgid="5002798077387803726">"Wi-Fi ప్రారంభించబడిందా, లేదా మరియు కనెక్ట్ చేయబడిన Wi-Fi పరికరాల పేరు వంటి Wi-Fi నెట్వర్కింగ్ గురించి సమాచారాన్ని వీక్షించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> <string name="permlab_changeWifiState" msgid="6550641188749128035">"Wi-Fiకి కనెక్ట్ చేయడం మరియు దాని నుండి డిస్కనెక్ట్ చేయడం"</string> - <string name="permdesc_changeWifiState" msgid="7137950297386127533">"Wi-Fi ప్రాప్యత స్థానాలకు కనెక్ట్ చేయడానికి మరియు వాటి నుండి డిస్కనెక్ట్ చేయడానికి మరియు Wi-Fi నెట్వర్క్ల కోసం పరికర కాన్ఫిగరేషన్కు మార్పులు చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_changeWifiState" msgid="7137950297386127533">"Wi-Fi యాక్సెస్ స్థానాలకు కనెక్ట్ చేయడానికి మరియు వాటి నుండి డిస్కనెక్ట్ చేయడానికి మరియు Wi-Fi నెట్వర్క్ల కోసం పరికర కాన్ఫిగరేషన్కు మార్పులు చేయడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"Wi-Fi Multicast స్వీకరణను అనుమతించడం"</string> - <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"మల్టీక్యాస్ట్ చిరునామాలను ఉపయోగించి మీ టాబ్లెట్కు మాత్రమే కాకుండా Wi-Fi నెట్వర్క్లోని అన్ని పరికరాలకు పంపబడిన ప్యాకెట్లను స్వీకరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. మల్టీక్యాస్ట్ యేతర మోడ్ కంటే ఇది ఎక్కువ పవర్ ఉపయోగిస్తుంది."</string> + <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"మల్టీక్యాస్ట్ చిరునామాలను ఉపయోగించి మీ టాబ్లెట్కు మాత్రమే కాకుండా Wi-Fi నెట్వర్క్లోని అన్ని పరికరాలకు పంపబడిన ప్యాకెట్లను స్వీకరించడానికి యాప్ను అనుమతిస్తుంది. మల్టీక్యాస్ట్ యేతర మోడ్ కంటే ఇది ఎక్కువ పవర్ ఉపయోగిస్తుంది."</string> <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"మల్టీక్యాస్ట్ చిరునామాలను ఉపయోగించి మీ టీవీకి మాత్రమే కాకుండా Wi-Fi నెట్వర్క్లోని అన్ని పరికరాలకు పంపిన ప్యాకెట్లను స్వీకరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఇది మల్టీక్యాస్ట్ యేతర మోడ్ కంటే ఎక్కువ పవర్ను ఉపయోగిస్తుంది."</string> <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"మల్టీక్యాస్ట్ చిరునామాలను ఉపయోగించి మీ ఫోన్కు మాత్రమే కాకుండా Wi-Fi నెట్వర్క్లోని అన్ని పరికరాలకు పంపబడిన ప్యాకెట్లను స్వీకరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. మల్టీక్యాస్ట్ యేతర మోడ్ కంటే ఇది ఎక్కువ పవర్ ఉపయోగిస్తుంది."</string> - <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"బ్లూటూత్ సెట్టింగ్లను ప్రాప్యత చేయడం"</string> - <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"స్థానిక బ్లూటూత్ టాబ్లెట్ను కాన్ఫిగర్ చేయడానికి మరియు రిమోట్ పరికరాలతో దాన్ని కనుగొనడానికి మరియు జత చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"బ్లూటూత్ సెట్టింగ్లను యాక్సెస్ చేయడం"</string> + <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"స్థానిక బ్లూటూత్ టాబ్లెట్ను కాన్ఫిగర్ చేయడానికి మరియు రిమోట్ పరికరాలతో దాన్ని కనుగొనడానికి మరియు జత చేయడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"స్థానిక బ్లూటూత్ టీవీని కాన్ఫిగర్ చేయడానికి మరియు రిమోట్ పరికరాలను గుర్తించి, వాటితో జత చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> - <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"స్థానిక బ్లూటూత్ ఫోన్ను కాన్ఫిగర్ చేయడానికి మరియు రిమోట్ పరికరాలతో దాన్ని కనుగొనడానికి మరియు జత చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"స్థానిక బ్లూటూత్ ఫోన్ను కాన్ఫిగర్ చేయడానికి మరియు రిమోట్ పరికరాలతో దాన్ని కనుగొనడానికి మరియు జత చేయడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAXకు కనెక్ట్ చేయడం మరియు దాని నుండి డిస్కనెక్ట్ చేయడం"</string> - <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Wi-Fi ప్రారంభించబడిందా, లేదా మరియు కనెక్ట్ చేయబడిన WiMAX నెట్వర్క్ల గురించి సమాచారాన్ని కనుగొనడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Wi-Fi ప్రారంభించబడిందా, లేదా మరియు కనెక్ట్ చేయబడిన WiMAX నెట్వర్క్ల గురించి సమాచారాన్ని కనుగొనడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_changeWimaxState" msgid="340465839241528618">"WiMAX స్థితిని మార్చడం"</string> <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"WiMAX నెట్వర్క్లకు టాబ్లెట్ను కనెక్ట్ చేయడానికి మరియు వాటి నుండి టాబ్లెట్ను డిస్కనెక్ట్ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> <string name="permdesc_changeWimaxState" product="tv" msgid="6022307083934827718">"టీవీని WiMAX నెట్వర్క్లకు కనెక్ట్ చేయడానికి మరియు వాటి నుండి టీవీని డిస్కనెక్ట్ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> - <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"WiMAX నెట్వర్క్లకు ఫోన్ను కనెక్ట్ చేయడానికి మరియు వాటి నుండి ఫోన్ను డిస్కనెక్ట్ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"WiMAX నెట్వర్క్లకు ఫోన్ను కనెక్ట్ చేయడానికి మరియు వాటి నుండి ఫోన్ను డిస్కనెక్ట్ చేయడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_bluetooth" msgid="6127769336339276828">"బ్లూటూత్ పరికరాలతో జత చేయడం"</string> - <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"టాబ్లెట్లో బ్లూటూత్ యొక్క కాన్ఫిగరేషన్ను వీక్షించడానికి మరియు జత చేయబడిన పరికరాలతో కనెక్షన్లను ఏర్పాటు చేయడానికి మరియు ఆమోదించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"టాబ్లెట్లో బ్లూటూత్ యొక్క కాన్ఫిగరేషన్ను వీక్షించడానికి మరియు జత చేయబడిన పరికరాలతో కనెక్షన్లను ఏర్పాటు చేయడానికి మరియు ఆమోదించడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permdesc_bluetooth" product="tv" msgid="3974124940101104206">"బ్లూటూత్ కాన్ఫిగరేషన్ను టీవీలో వీక్షించడానికి మరియు జత చేసిన పరికరాలతో కనెక్షన్లను ఏర్పాటు చేయడానికి మరియు ఆమోదించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> - <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"ఫోన్లో బ్లూటూత్ యొక్క కాన్ఫిగరేషన్ను వీక్షించడానికి మరియు జత చేయబడిన పరికరాలతో కనెక్షన్లను ఏర్పాటు చేయడానికి మరియు ఆమోదించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"ఫోన్లో బ్లూటూత్ యొక్క కాన్ఫిగరేషన్ను వీక్షించడానికి మరియు జత చేయబడిన పరికరాలతో కనెక్షన్లను ఏర్పాటు చేయడానికి మరియు ఆమోదించడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_nfc" msgid="4423351274757876953">"సమీప క్షేత్ర కమ్యూనికేషన్ను నియంత్రించడం"</string> - <string name="permdesc_nfc" msgid="7120611819401789907">"సమీప ఫీల్డ్ కమ్యూనికేషన్ (NFC) ట్యాగ్లు, కార్డులు మరియు రీడర్లతో కమ్యూనికేట్ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_nfc" msgid="7120611819401789907">"సమీప ఫీల్డ్ కమ్యూనికేషన్ (NFC) ట్యాగ్లు, కార్డులు మరియు రీడర్లతో కమ్యూనికేట్ చేయడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_disableKeyguard" msgid="3598496301486439258">"మీ స్క్రీన్ లాక్ను నిలిపివేయడం"</string> - <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"కీలాక్ మరియు ఏదైనా అనుబంధించబడిన పాస్వర్డ్ భద్రతను నిలిపివేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఉదాహరణకు, ఇన్కమింగ్ ఫోన్ కాల్ వస్తున్నప్పుడు ఫోన్ కీలాక్ను నిలిపివేస్తుంది, ఆపై కాల్ ముగిసిన తర్వాత కీలాక్ను మళ్లీ ప్రారంభిస్తుంది."</string> + <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"కీలాక్ మరియు ఏదైనా అనుబంధించబడిన పాస్వర్డ్ భద్రతను నిలిపివేయడానికి యాప్ను అనుమతిస్తుంది. ఉదాహరణకు, ఇన్కమింగ్ ఫోన్ కాల్ వస్తున్నప్పుడు ఫోన్ కీలాక్ను నిలిపివేస్తుంది, ఆపై కాల్ ముగిసిన తర్వాత కీలాక్ను మళ్లీ ప్రారంభిస్తుంది."</string> <string name="permlab_manageFingerprint" msgid="5640858826254575638">"వేలిముద్ర హార్డ్వేర్ని నిర్వహించడానికి అనుమతి"</string> - <string name="permdesc_manageFingerprint" msgid="178208705828055464">"వినియోగం కోసం వేలిముద్ర టెంప్లేట్లను జోడించే మరియు తొలగించే పద్ధతులను అమలు చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_manageFingerprint" msgid="178208705828055464">"వినియోగం కోసం వేలిముద్ర టెంప్లేట్లను జోడించే మరియు తొలగించే పద్ధతులను అమలు చేయడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_useFingerprint" msgid="3150478619915124905">"వేలిముద్ర హార్డ్వేర్ని ఉపయోగించడానికి అనుమతి"</string> <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ప్రామాణీకరణ కోసం వేలిముద్ర హార్డ్వేర్ను ఉపయోగించడానికి అనువర్తనాన్ని అనుమతిస్తుంది"</string> <string name="fingerprint_acquired_partial" msgid="735082772341716043">"పాక్షిక వేలిముద్ర గుర్తించబడింది. దయచేసి మళ్లీ ప్రయత్నించండి."</string> @@ -493,15 +493,15 @@ <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"సమకాలీకరణను ఆన్ మరియు ఆఫ్కు టోగుల్ చేయడం"</string> <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"ఖాతా యొక్క సమకాలీకరణ సెట్టింగ్లను సవరించడానికి యాప్ను అనుమతిస్తుంది. ఉదాహరణకు, ఇది ఒక ఖాతాతో వ్యక్తుల యాప్ యొక్క సమకాలీకరణను ప్రారంభించడానికి ఉపయోగించబడవచ్చు."</string> <string name="permlab_readSyncStats" msgid="7396577451360202448">"సమకాలీకరణ గణాంకాలను చదవడం"</string> - <string name="permdesc_readSyncStats" msgid="1510143761757606156">"ఖాతా యొక్క సమకాలీకరణ గణాంకాలను అలాగే సమకాలీకరణ ఈవెంట్ల చరిత్రను మరియు ఎంత డేటా సమకాలీకరించబడింది అనేవాటిని చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_readSyncStats" msgid="1510143761757606156">"ఖాతా యొక్క సమకాలీకరణ గణాంకాలను అలాగే సమకాలీకరణ ఈవెంట్ల చరిత్రను మరియు ఎంత డేటా సమకాలీకరించబడింది అనేవాటిని చదవడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"మీ USB నిల్వ యొక్క కంటెంట్లను చదవడం"</string> <string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"మీ SD కార్డు యొక్క కంటెంట్లను చదవడం"</string> <string name="permdesc_sdcardRead" product="nosdcard" msgid="3446988712598386079">"మీ USB నిల్వలోని కంటెంట్లను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> <string name="permdesc_sdcardRead" product="default" msgid="2607362473654975411">"మీ SD కార్డ్లోని కంటెంట్లను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"మీ USB నిల్వ యొక్క కంటెంట్లను సవరించడం లేదా తొలగించడం"</string> <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"మీ SD కార్డు యొక్క కంటెంట్లను సవరించడం లేదా తొలగించడం"</string> - <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"USB నిల్వకు వ్రాయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> - <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"SD కార్డుకి వ్రాయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"USB నిల్వకు వ్రాయడానికి యాప్ను అనుమతిస్తుంది."</string> + <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"SD కార్డుకి వ్రాయడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_use_sip" msgid="2052499390128979920">"SIP కాల్లను చేయడానికి/స్వీకరించడానికి"</string> <string name="permdesc_use_sip" msgid="2297804849860225257">"SIP కాల్లను చేయడానికి మరియు స్వీకరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> <string name="permlab_register_sim_subscription" msgid="3166535485877549177">"కొత్త టెలికామ్ SIM కనెక్షన్లను నమోదు చేయడం"</string> @@ -517,12 +517,12 @@ <string name="permlab_control_incall_experience" msgid="9061024437607777619">"ఇన్-కాల్ వినియోగదారు అనుభవాన్ని అందించడం"</string> <string name="permdesc_control_incall_experience" msgid="915159066039828124">"ఇన్-కాల్ వినియోగదారుని అనుభవాన్ని అందించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"చారిత్రక నెట్వర్క్ వినియోగాన్ని చదవడం"</string> - <string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"నిర్దిష్ట నెట్వర్క్లు మరియు అనువర్తనాలు కోసం చారిత్రాత్మక నెట్వర్క్ వినియోగాన్ని చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"నిర్దిష్ట నెట్వర్క్లు మరియు యాప్ల కోసం చారిత్రాత్మక నెట్వర్క్ వినియోగాన్ని చదవడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"నెట్వర్క్ విధానాన్ని నిర్వహించడం"</string> - <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"నెట్వర్క్ విధానాలను నిర్వహించడానికి మరియు అనువర్తన-నిర్దిష్ట నిబంధనలను నిర్వచించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"నెట్వర్క్ విధానాలను నిర్వహించడానికి మరియు యాప్-నిర్దిష్ట నిబంధనలను నిర్వచించడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"నెట్వర్క్ వినియోగ అకౌంటింగ్ను సవరించడం"</string> - <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"అనువర్తనాల్లో నెట్వర్క్ వినియోగం ఎలా గణించాలనే దాన్ని సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. సాధారణ అనువర్తనాల ద్వారా ఉపయోగించడానికి ఉద్దేశించినది కాదు."</string> - <string name="permlab_accessNotifications" msgid="7673416487873432268">"నోటిఫికేషన్లను ప్రాప్యత చేయడం"</string> + <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"యాప్లలో నెట్వర్క్ వినియోగం ఎలా గణించాలనే దాన్ని సవరించడానికి యాప్ను అనుమతిస్తుంది. సాధారణ యాప్ల ద్వారా ఉపయోగించడానికి ఉద్దేశించినది కాదు."</string> + <string name="permlab_accessNotifications" msgid="7673416487873432268">"నోటిఫికేషన్లను యాక్సెస్ చేయడం"</string> <string name="permdesc_accessNotifications" msgid="458457742683431387">"నోటిఫికేషన్లను, ఇతర అనువర్తనాల ద్వారా పోస్ట్ చేయబడిన వాటిని తిరిగి పొందడానికి, పరిశీలించడానికి మరియు క్లియర్ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"నోటిఫికేషన్ పరిశీలన సేవకు అనుబంధించడం"</string> <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"నోటిఫికేషన్ పరిశీలన సేవ యొక్క అగ్ర-స్థాయి ఇంటర్ఫేస్కు అనుబంధించడానికి హోల్డర్ను అనుమతిస్తుంది. సాధారణ అనువర్తనాల కోసం ఎప్పటికీ అవసరం ఉండకూడదు."</string> @@ -536,7 +536,7 @@ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"నెట్వర్క్ పరిస్థితులపై పరిశీలనల గురించి తెలుసుకోవడానికి అనువర్తనాన్ని అనుమతిస్తుంది. సాధారణ అనువర్తనాలకు ఎప్పటికీ అవసరం ఉండకూడదు."</string> <string name="permlab_setInputCalibration" msgid="4902620118878467615">"ఇన్పుట్ పరికరం క్రమాంకనాన్ని మార్చండి"</string> <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"టచ్ స్క్రీన్ యొక్క క్రమాంకన పరామితులను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. సాధారణ అనువర్తనాలకు ఎప్పటికీ అవసరం ఉండదు."</string> - <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM ప్రమాణపత్రాలను ప్రాప్యత చేయడం"</string> + <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM ప్రమాణపత్రాలను యాక్సెస్ చేయడం"</string> <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"DRM ప్రమాణపత్రాలను కేటాయించడానికి మరియు ఉపయోగించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. సాధారణ అనువర్తనాలకు ఎప్పటికీ అవసరం ఉండదు."</string> <string name="permlab_handoverStatus" msgid="7820353257219300883">"Android Beam బదిలీ స్థితిని స్వీకరించడం"</string> <string name="permdesc_handoverStatus" msgid="4788144087245714948">"ప్రస్తుత Android Beam బదిలీలకు సంబంధించిన సమాచారాన్ని స్వీకరించడానికి ఈ అనువర్తనాన్ని అనుమతిస్తుంది"</string> @@ -546,7 +546,7 @@ <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"క్యారియర్ సందేశ సేవ యొక్క అగ్ర-స్థాయి ఇంటర్ఫేస్కు అనుబంధించడానికి హోల్డర్ను అనుమతిస్తుంది. సాధారణ అనువర్తనాలకు ఎప్పటికీ అవసరం ఉండదు."</string> <string name="permlab_bindCarrierServices" msgid="3233108656245526783">"క్యారియర్ సేవలకు అనుబంధించడం"</string> <string name="permdesc_bindCarrierServices" msgid="1391552602551084192">"క్యారియర్ సేవలకు అనుబంధించడానికి హోల్డర్ను అనుమతిస్తుంది. సాధారణ అనువర్తనాలకు ఎప్పటికీ అవసరం ఉండదు."</string> - <string name="permlab_access_notification_policy" msgid="4247510821662059671">"అంతరాయం కలిగించవద్దు ఎంపిక ప్రాప్యత"</string> + <string name="permlab_access_notification_policy" msgid="4247510821662059671">"అంతరాయం కలిగించవద్దును యాక్సెస్ చేయడం"</string> <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"అంతరాయం కలిగించవద్దు ఎంపిక కాన్ఫిగరేషన్ చదవడానికి మరియు వ్రాయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> <string name="policylab_limitPassword" msgid="4497420728857585791">"పాస్వర్డ్ నియమాలను సెట్ చేయండి"</string> <string name="policydesc_limitPassword" msgid="2502021457917874968">"స్క్రీన్ లాక్ పాస్వర్డ్లు మరియు PINల్లో అనుమతించబడిన పొడవు మరియు అక్షరాలను నియంత్రిస్తుంది."</string> @@ -574,7 +574,7 @@ <string name="policylab_expirePassword" msgid="5610055012328825874">"స్క్రీన్ లాక్ పాస్వర్డ్ గడువు ముగింపుని సెట్ చేయండి"</string> <string name="policydesc_expirePassword" msgid="5367525762204416046">"స్క్రీన్ లాక్ పాస్వర్డ్, పిన్ లేదా నమూనాని తప్పనిసరిగా ఎంత తరచుగా మార్చాలనే దాన్ని మారుస్తుంది."</string> <string name="policylab_encryptedStorage" msgid="8901326199909132915">"నిల్వ గుప్తీకరణను సెట్ చేయండి"</string> - <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"నిల్వ చేయబడిన అనువర్తన డేటా గుప్తీకరించబడి ఉండటం అవసరం."</string> + <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"నిల్వ చేయబడిన యాప్ డేటా గుప్తీకరించబడి ఉండటం అవసరం."</string> <string name="policylab_disableCamera" msgid="6395301023152297826">"కెమెరాలను నిలిపివేయండి"</string> <string name="policydesc_disableCamera" msgid="2306349042834754597">"అన్ని పరికర కెమెరాల వినియోగాన్ని నిరోధించండి."</string> <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"కొన్ని స్క్రీన్ లాక్ లక్షణాలు నిలిపివేయండి"</string> @@ -827,17 +827,17 @@ <string name="autofill_area" msgid="3547409050889952423">"ప్రాంతం"</string> <string name="autofill_emirate" msgid="2893880978835698818">"ఎమిరేట్"</string> <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"మీ వెబ్ బుక్మార్క్లు మరియు చరిత్రను చదవడం"</string> - <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"బ్రౌజర్ సందర్శించిన అన్ని URLల చరిత్ర గురించి మరియు అన్ని బ్రౌజర్ బుక్మార్క్ల గురించి చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది. గమనిక: ఈ అనుమతి మూడవ పక్షం బ్రౌజర్లు లేదా వెబ్ బ్రౌజింగ్ సామర్థ్యాలు గల ఇతర అనువర్తనాల ద్వారా అమలు చేయబడకపోవచ్చు."</string> + <string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"బ్రౌజర్ సందర్శించిన అన్ని URLల చరిత్ర గురించి మరియు అన్ని బ్రౌజర్ బుక్మార్క్ల గురించి చదవడానికి యాప్ను అనుమతిస్తుంది. గమనిక: ఈ అనుమతి మూడవ పక్షం బ్రౌజర్లు లేదా వెబ్ బ్రౌజింగ్ సామర్థ్యాలు గల ఇతర యాప్ల ద్వారా అమలు చేయబడకపోవచ్చు."</string> <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"వెబ్ బుక్మార్క్లు మరియు చరిత్రను వ్రాయడం"</string> - <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"మీ టాబ్లెట్లో నిల్వ చేయబడిన బ్రౌజర్ చరిత్రను లేదా బుక్మార్క్లను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఇది బ్రౌజర్ డేటాను ఎరేజ్ చేయడానికి లేదా సవరించడానికి అనువర్తనాన్ని అనుమతించవచ్చు. గమనిక: ఈ అనుమతి మూడవ పక్షం బ్రౌజర్లు లేదా వెబ్ బ్రౌజింగ్ సామర్థ్యాలు గల ఇతర అనువర్తనాల ద్వారా అమలు చేయబడకపోవచ్చు."</string> + <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"మీ టాబ్లెట్లో నిల్వ చేయబడిన బ్రౌజర్ చరిత్రను లేదా బుక్మార్క్లను సవరించడానికి యాప్ను అనుమతిస్తుంది. ఇది బ్రౌజర్ డేటాను ఎరేజ్ చేయడానికి లేదా సవరించడానికి యాప్ను అనుమతించవచ్చు. గమనిక: ఈ అనుమతి మూడవ పక్షం బ్రౌజర్లు లేదా వెబ్ బ్రౌజింగ్ సామర్థ్యాలు గల ఇతర యాప్ల ద్వారా అమలు చేయబడకపోవచ్చు."</string> <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"మీ టీవీలో నిల్వ చేసిన బ్రౌజర్ చరిత్ర లేదా బుక్మార్క్లను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఇది బ్రౌజర్ డేటాను తీసివేయడానికి లేదా సవరించడానికి అనువర్తనాన్ని అనుమతించవచ్చు. గమనిక: ఈ అనుమతి మూడవ-పక్ష బ్రౌజర్లు లేదా వెబ్ బ్రౌజింగ్ సామర్థ్యాలు గల ఇతర అనువర్తనాల ద్వారా అమలు కాకపోవచ్చు."</string> - <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"మీ ఫోన్లో నిల్వ చేయబడిన బ్రౌజర్ చరిత్రను లేదా బుక్మార్క్లను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఇది బ్రౌజర్ డేటాను ఎరేజ్ చేయడానికి లేదా సవరించడానికి అనువర్తనాన్ని అనుమతించవచ్చు. గమనిక: ఈ అనుమతి మూడవ పక్షం బ్రౌజర్లు లేదా వెబ్ బ్రౌజింగ్ సామర్థ్యాలు గల ఇతర అనువర్తనాల ద్వారా అమలు చేయబడకపోవచ్చు."</string> + <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"మీ ఫోన్లో నిల్వ చేయబడిన బ్రౌజర్ చరిత్రను లేదా బుక్మార్క్లను సవరించడానికి యాప్ను అనుమతిస్తుంది. ఇది బ్రౌజర్ డేటాను ఎరేజ్ చేయడానికి లేదా సవరించడానికి యాప్ను అనుమతించవచ్చు. గమనిక: ఈ అనుమతి మూడవ పక్షం బ్రౌజర్లు లేదా వెబ్ బ్రౌజింగ్ సామర్థ్యాలు గల ఇతర యాప్ల ద్వారా అమలు చేయబడకపోవచ్చు."</string> <string name="permlab_setAlarm" msgid="1379294556362091814">"అలారం సెట్ చేయడం"</string> - <string name="permdesc_setAlarm" msgid="316392039157473848">"ఇన్స్టాల్ చేయబడిన అలారం గడియారం అనువర్తనంలో అలారంను సెట్ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది. కొన్ని అలారం గల గడియారం అనువర్తనాలు ఈ లక్షణాన్ని అమలు చేయకపోవచ్చు."</string> + <string name="permdesc_setAlarm" msgid="316392039157473848">"ఇన్స్టాల్ చేయబడిన అలారం గడియారం యాప్లో అలారంను సెట్ చేయడానికి యాప్ను అనుమతిస్తుంది. కొన్ని అలారం గల గడియారం యాప్లు ఈ ఫీచర్ను అమలు చేయకపోవచ్చు."</string> <string name="permlab_addVoicemail" msgid="5525660026090959044">"వాయిస్ మెయిల్ను జోడించడం"</string> - <string name="permdesc_addVoicemail" msgid="6604508651428252437">"మీ వాయిస్ మెయిల్ ఇన్బాక్స్కి సందేశాలను జోడించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string> + <string name="permdesc_addVoicemail" msgid="6604508651428252437">"మీ వాయిస్ మెయిల్ ఇన్బాక్స్కి సందేశాలను జోడించడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"బ్రౌజర్ భౌగోళిక స్థానం అనుమతులను సవరించడం"</string> - <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"బ్రౌజర్ యొక్క భౌగోళిక స్థానం అనుమతులను సవరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది. హానికరమైన అనువర్తనాలు ఏకపక్ష వెబ్ సైట్లకు స్థాన సమాచారాన్ని అనుమతించడానికి దీన్ని ఉపయోగించవచ్చు."</string> + <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"బ్రౌజర్ యొక్క భౌగోళిక స్థానం అనుమతులను సవరించడానికి యాప్ను అనుమతిస్తుంది. హానికరమైన యాప్లు ఏకపక్ష వెబ్ సైట్లకు స్థాన సమాచారాన్ని అనుమతించడానికి దీన్ని ఉపయోగించవచ్చు."</string> <string name="save_password_message" msgid="767344687139195790">"మీరు బ్రౌజర్ ఈ పాస్వర్డ్ను గుర్తుపెట్టుకోవాలని కోరుకుంటున్నారా?"</string> <string name="save_password_notnow" msgid="6389675316706699758">"ఇప్పుడు కాదు"</string> <string name="save_password_remember" msgid="6491879678996749466">"గుర్తుంచుకో"</string> @@ -849,8 +849,8 @@ <string name="menu_space_shortcut_label" msgid="2410328639272162537">"space"</string> <string name="menu_enter_shortcut_label" msgid="2743362785111309668">"enter"</string> <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"delete"</string> - <string name="search_go" msgid="8298016669822141719">"శోధించు"</string> - <string name="search_hint" msgid="1733947260773056054">"శోధించు..."</string> + <string name="search_go" msgid="8298016669822141719">"వెతుకు"</string> + <string name="search_hint" msgid="1733947260773056054">"వెతుకు..."</string> <string name="searchview_description_search" msgid="6749826639098512120">"శోధించండి"</string> <string name="searchview_description_query" msgid="5911778593125355124">"ప్రశ్నను శోధించండి"</string> <string name="searchview_description_clear" msgid="1330281990951833033">"ప్రశ్నను క్లియర్ చేయి"</string> @@ -1018,7 +1018,7 @@ <string name="use_a_different_app" msgid="8134926230585710243">"వేరొక అనువర్తనాన్ని ఉపయోగించండి"</string> <string name="clearDefaultHintMsg" msgid="3252584689512077257">"సిస్టమ్ సెట్టింగ్లు > అనువర్తనాలు > డౌన్లోడ్ చేయబడినవిలో డిఫాల్ట్ను క్లియర్ చేయి."</string> <string name="chooseActivity" msgid="7486876147751803333">"చర్యను ఎంచుకోండి"</string> - <string name="chooseUsbActivity" msgid="6894748416073583509">"USB పరికరం కోసం అనువర్తనాన్ని ఎంచుకోండి"</string> + <string name="chooseUsbActivity" msgid="6894748416073583509">"USB పరికరం కోసం యాప్ను ఎంచుకోండి"</string> <string name="noApplications" msgid="2991814273936504689">"ఈ చర్యను అమలు చేయగల అనువర్తనాలు ఏవీ లేవు."</string> <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> ఆపివేయబడింది"</string> <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> ఆపివేయబడింది"</string> @@ -1055,7 +1055,7 @@ <string name="android_upgrading_notification_title" msgid="8428357096969413169">"Android నవీకరణను ముగిస్తోంది…"</string> <string name="android_upgrading_notification_body" msgid="5761201379457064286">"అప్గ్రేడ్ పూర్తయ్యే వరకు కొన్ని అనువర్తనాలు సరిగ్గా పని చేయకపోవచ్చు"</string> <string name="app_upgrading_toast" msgid="3008139776215597053">"<xliff:g id="APPLICATION">%1$s</xliff:g>ని అప్గ్రేడ్ చేస్తోంది…"</string> - <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g>లో <xliff:g id="NUMBER_0">%1$d</xliff:g> అనువర్తనాన్ని అనుకూలీకరిస్తోంది."</string> + <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g>లో <xliff:g id="NUMBER_0">%1$d</xliff:g> యాప్ను అనుకూలీకరిస్తోంది."</string> <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g>ని సిద్ధం చేస్తోంది."</string> <string name="android_upgrading_starting_apps" msgid="451464516346926713">"అనువర్తనాలను ప్రారంభిస్తోంది."</string> <string name="android_upgrading_complete" msgid="1405954754112999229">"బూట్ను ముగిస్తోంది."</string> @@ -1064,9 +1064,9 @@ <string name="heavy_weight_switcher_title" msgid="7153167085403298169">"అనువర్తనాలను మార్చాలా?"</string> <string name="heavy_weight_switcher_text" msgid="7022631924534406403">"మరో యాప్ ఇప్పటికే అమలవుతోంది, మీరు మరోదాన్ని ప్రారంభించడానికి ముందు అది తప్పనిసరిగా ఆపివేయబడాలి."</string> <string name="old_app_action" msgid="493129172238566282">"<xliff:g id="OLD_APP">%1$s</xliff:g>కు తిరిగి వెళ్లండి"</string> - <string name="old_app_description" msgid="2082094275580358049">"కొత్త అనువర్తనాన్ని ప్రారంభించవద్దు."</string> + <string name="old_app_description" msgid="2082094275580358049">"కొత్త యాప్ను ప్రారంభించవద్దు."</string> <string name="new_app_action" msgid="5472756926945440706">"<xliff:g id="OLD_APP">%1$s</xliff:g>ని ప్రారంభించండి"</string> - <string name="new_app_description" msgid="1932143598371537340">"పాత అనువర్తనాన్ని సేవ్ చేయకుండానే ఆపివేయండి."</string> + <string name="new_app_description" msgid="1932143598371537340">"పాత యాప్ను సేవ్ చేయకుండానే ఆపివేయండి."</string> <string name="dump_heap_notification" msgid="2618183274836056542">"<xliff:g id="PROC">%1$s</xliff:g> మెమరీ పరిమితిని మించిపోయింది"</string> <string name="dump_heap_notification_detail" msgid="6901391084243999274">"కుప్పలు తెప్పలుగా సేకరించబడింది; షేర్ చేయడానికి నొక్కండి"</string> <string name="dump_heap_title" msgid="5864292264307651673">"హీప్ డంప్ను భాగస్వామ్యం చేయాలా?"</string> @@ -1112,10 +1112,10 @@ <string name="network_available_sign_in" msgid="1848877297365446605">"నెట్వర్క్కి సైన్ ఇన్ చేయండి"</string> <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) --> <skip /> - <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fiకి ఇంటర్నెట్ ప్రాప్యత లేదు"</string> + <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fiకి ఇంటర్నెట్ యాక్సెస్ లేదు"</string> <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"ఎంపికల కోసం నొక్కండి"</string> <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>కి మార్చబడింది"</string> - <string name="network_switch_metered_detail" msgid="5325661434777870353">"పరికరం <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>కి ఇంటర్నెట్ ప్రాప్యత లేనప్పుడు <xliff:g id="NEW_NETWORK">%1$s</xliff:g>ని ఉపయోగిస్తుంది. ఛార్జీలు వర్తించవచ్చు."</string> + <string name="network_switch_metered_detail" msgid="5325661434777870353">"పరికరం <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>కి ఇంటర్నెట్ యాక్సెస్ లేనప్పుడు <xliff:g id="NEW_NETWORK">%1$s</xliff:g>ని ఉపయోగిస్తుంది. ఛార్జీలు వర్తించవచ్చు."</string> <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> నుండి <xliff:g id="NEW_NETWORK">%2$s</xliff:g>కి మార్చబడింది"</string> <string-array name="network_switch_type_name"> <item msgid="3979506840912951943">"మొబైల్ డేటా"</item> @@ -1148,7 +1148,7 @@ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"ఫోన్ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>కి కనెక్ట్ అయినప్పుడు అది Wi-Fi నుండి తాత్కాలికంగా డిస్కనెక్ట్ చేయబడుతుంది"</string> <string name="select_character" msgid="3365550120617701745">"అక్షరాన్ని చొప్పించండి"</string> <string name="sms_control_title" msgid="7296612781128917719">"SMS సందేశాలు పంపుతోంది"</string> - <string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> పెద్ద సంఖ్యలో SMS సందేశాలను పంపుతోంది. సందేశాలను పంపడం కొనసాగించడానికి మీరు ఈ అనువర్తనాన్ని అనుమతించాలనుకుంటున్నారా?"</string> + <string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> పెద్ద సంఖ్యలో SMS సందేశాలను పంపుతోంది. సందేశాలను పంపడం కొనసాగించడానికి మీరు ఈ యాప్ను అనుమతించాలనుకుంటున్నారా?"</string> <string name="sms_control_yes" msgid="3663725993855816807">"అనుమతిస్తున్నాను"</string> <string name="sms_control_no" msgid="625438561395534982">"తిరస్కరిస్తున్నాను"</string> <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ఒక సందేశాన్ని <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b>కి పంపాలనుకుంటోంది."</string> @@ -1164,7 +1164,7 @@ <string name="sim_removed_message" msgid="2333164559970958645">"మీరు చెల్లుబాటు అయ్యే సిమ్ కార్డును చొప్పించి పునఃప్రారంభించే వరకు మొబైల్ నెట్వర్క్ అందుబాటులో ఉండదు."</string> <string name="sim_done_button" msgid="827949989369963775">"పూర్తయింది"</string> <string name="sim_added_title" msgid="3719670512889674693">"సిమ్ కార్డు జోడించబడింది"</string> - <string name="sim_added_message" msgid="6599945301141050216">"మొబైల్ నెట్వర్క్ను ప్రాప్యత చేయడానికి మీ పరికరాన్ని పునఃప్రారంభించండి."</string> + <string name="sim_added_message" msgid="6599945301141050216">"మొబైల్ నెట్వర్క్ను యాక్సెస్ చేయడానికి మీ పరికరాన్ని పునఃప్రారంభించండి."</string> <string name="sim_restart_button" msgid="4722407842815232347">"పునఃప్రారంభించు"</string> <string name="carrier_app_dialog_message" msgid="7066156088266319533">"మీ SIM సక్రమంగా పని చేస్తుండటానికి, మీరు మీ క్యారియర్ నుండి ఒక అనువర్తనాన్ని ఇన్స్టాల్ చేసుకొని, తెరవాలి."</string> <string name="carrier_app_dialog_button" msgid="7900235513678617329">"అనువర్తనాన్ని పొందండి"</string> @@ -1262,7 +1262,7 @@ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"జూమ్ నియంత్రణ కోసం రెండుసార్లు నొక్కండి"</string> <string name="gadget_host_error_inflating" msgid="4882004314906466162">"విడ్జెట్ను జోడించడం సాధ్యపడలేదు."</string> <string name="ime_action_go" msgid="8320845651737369027">"వెళ్లు"</string> - <string name="ime_action_search" msgid="658110271822807811">"శోధించు"</string> + <string name="ime_action_search" msgid="658110271822807811">"వెతుకు"</string> <string name="ime_action_send" msgid="2316166556349314424">"పంపు"</string> <string name="ime_action_next" msgid="3138843904009813834">"తదుపరి"</string> <string name="ime_action_done" msgid="8971516117910934605">"పూర్తయింది"</string> @@ -1270,9 +1270,9 @@ <string name="ime_action_default" msgid="2840921885558045721">"అమలు చేయి"</string> <string name="dial_number_using" msgid="5789176425167573586">"<xliff:g id="NUMBER">%s</xliff:g>ని ఉపయోగించి\nనంబర్ డయల్ చేయండి"</string> <string name="create_contact_using" msgid="4947405226788104538">"<xliff:g id="NUMBER">%s</xliff:g>ని ఉపయోగించి\nపరిచయాన్ని సృష్టించండి"</string> - <string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"క్రింది ఒకటి లేదా అంతకంటే ఎక్కువ అనువర్తనాలు మీ ఖాతాను ప్రాప్యత చేయడానికి ఇప్పుడే మరియు భవిష్యత్తులో అనుమతిని అభ్యర్థించవచ్చు."</string> + <string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"క్రింది ఒకటి లేదా అంతకంటే ఎక్కువ యాప్లు మీ ఖాతాను యాక్సెస్ చేయడానికి ఇప్పుడే మరియు భవిష్యత్తులో అనుమతిని అభ్యర్థించవచ్చు."</string> <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"మీరు ఈ అభ్యర్థనను అనుమతించాలనుకుంటున్నారా?"</string> - <string name="grant_permissions_header_text" msgid="6874497408201826708">"ప్రాప్యత అభ్యర్థన"</string> + <string name="grant_permissions_header_text" msgid="6874497408201826708">"యాక్సెస్ అభ్యర్థన"</string> <string name="allow" msgid="7225948811296386551">"అనుమతించండి"</string> <string name="deny" msgid="2081879885755434506">"తిరస్కరించండి"</string> <string name="permission_request_notification_title" msgid="6486759795926237907">"అనుమతి అభ్యర్థించబడింది"</string> @@ -1281,7 +1281,7 @@ <string name="forward_intent_to_work" msgid="621480743856004612">"మీరు మీ కార్యాలయ ప్రొఫైల్లో ఈ అనువర్తనాన్ని ఉపయోగిస్తున్నారు"</string> <string name="input_method_binding_label" msgid="1283557179944992649">"ఇన్పుట్ పద్ధతి"</string> <string name="sync_binding_label" msgid="3687969138375092423">"సమకాలీకరణ"</string> - <string name="accessibility_binding_label" msgid="4148120742096474641">"ప్రాప్యత"</string> + <string name="accessibility_binding_label" msgid="4148120742096474641">"యాక్సెస్ సామర్థ్యం"</string> <string name="wallpaper_binding_label" msgid="1240087844304687662">"వాల్పేపర్"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"వాల్పేపర్ను మార్చండి"</string> <string name="notification_listener_binding_label" msgid="2014162835481906429">"నోటిఫికేషన్ పరిశీలన"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g>కు కనెక్ట్ చేయబడింది. నెట్వర్క్ను నిర్వహించడానికి నొక్కండి."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"ఎల్లప్పుడూ-ఆన్లో ఉండే VPN కనెక్ట్ చేయబడుతోంది…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"ఎల్లప్పుడూ-ఆన్లో ఉండే VPN కనెక్ట్ చేయబడింది"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"ఎల్లప్పుడూ ఆన్లో ఉండే VPN డిస్కనెక్ట్ చేయబడింది"</string> - <string name="vpn_lockdown_error" msgid="6009249814034708175">"ఎల్లప్పుడూ-ఆన్లో ఉండే VPN లోపం"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"సెటప్ చేయడానికి నొక్కండి"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"ఎల్లప్పుడూ ఆన్లో ఉండే VPN నుండి డిస్కనెక్ట్ చేయబడింది"</string> + <string name="vpn_lockdown_error" msgid="6009249814034708175">"ఎల్లప్పుడూ-ఆన్లో ఉండే VPN ఎర్రర్"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"నెట్వర్క్ లేదా VPN సెట్టింగ్లను మార్చండి"</string> <string name="upload_file" msgid="2897957172366730416">"ఫైల్ను ఎంచుకోండి"</string> <string name="no_file_chosen" msgid="6363648562170759465">"ఫైల్ ఎంచుకోబడలేదు"</string> <string name="reset" msgid="2448168080964209908">"రీసెట్ చేయి"</string> @@ -1362,7 +1362,7 @@ <string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"మోడ్ మార్పు"</string> <string name="keyboardview_keycode_shift" msgid="2270748814315147690">"Shift"</string> <string name="keyboardview_keycode_enter" msgid="2985864015076059467">"Enter"</string> - <string name="activitychooserview_choose_application" msgid="2125168057199941199">"అనువర్తనాన్ని ఎంచుకోండి"</string> + <string name="activitychooserview_choose_application" msgid="2125168057199941199">"యాప్ను ఎంచుకోండి"</string> <string name="activitychooserview_choose_application_error" msgid="8624618365481126668">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>ని ప్రారంభించడం సాధ్యపడలేదు"</string> <string name="shareactionprovider_share_with" msgid="806688056141131819">"వీటితో భాగస్వామ్యం చేయండి"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>తో భాగస్వామ్యం చేయండి"</string> @@ -1483,20 +1483,20 @@ <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string> <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"తీసివేయి"</string> <string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"వాల్యూమ్ను సిఫార్సు చేయబడిన స్థాయి కంటే ఎక్కువగా పెంచాలా?\n\nసుదీర్ఘ వ్యవధుల పాటు అధిక వాల్యూమ్లో వినడం వలన మీ వినికిడి శక్తి దెబ్బ తినవచ్చు."</string> - <string name="accessibility_shortcut_warning_dialog_title" msgid="8404780875025725199">"ప్రాప్యత సత్వరమార్గాన్ని ఉపయోగించాలా?"</string> - <string name="accessibility_shortcut_toogle_warning" msgid="7256507885737444807">"సత్వరమార్గం ఆన్లో ఉన్నప్పుడు, రెండు వాల్యూమ్ బటన్లను 3 సెకన్ల పాటు నొక్కితే ప్రాప్యత లక్షణం ప్రారంభం అవుతుంది.\n\n ప్రస్తుత ప్రాప్యత లక్షణం:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n సెట్టింగ్లు > ప్రాప్యతలో మీరు లక్షణాన్ని మార్చవచ్చు."</string> + <string name="accessibility_shortcut_warning_dialog_title" msgid="8404780875025725199">"యాక్సెస్ షార్ట్కట్ ఉపయోగించాలా?"</string> + <string name="accessibility_shortcut_toogle_warning" msgid="7256507885737444807">"షార్ట్కట్ ఆన్లో ఉన్నప్పుడు, రెండు వాల్యూమ్ బటన్లను 3 సెకన్ల పాటు నొక్కితే యాక్సెస్ ఫీచర్ ప్రారంభం అవుతుంది.\n\n ప్రస్తుత యాక్సెస్ ఫీచర్:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n సెట్టింగ్లు > యాక్సెస్లో మీరు ఫీచర్ను మార్చవచ్చు."</string> <string name="disable_accessibility_shortcut" msgid="627625354248453445">"సత్వరమార్గాన్ని ఆఫ్ చేయి"</string> <string name="leave_accessibility_shortcut_on" msgid="7653111894438512680">"సత్వరమార్గాన్ని ఉపయోగించు"</string> - <string name="accessibility_shortcut_enabling_service" msgid="7771852911861522636">"ప్రాప్యతా సత్వరమార్గం ద్వారా <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆన్ చేయబడింది"</string> - <string name="accessibility_shortcut_disabling_service" msgid="2747243438223109821">"ప్రాప్యతా సత్వరమార్గం ద్వారా <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆఫ్ చేయబడింది"</string> - <string name="accessibility_button_prompt_text" msgid="4234556536456854251">"ప్రాప్యత బటన్ను మీరు నొక్కినప్పుడు ఉపయోగించాల్సిన ఒక లక్షణాన్ని ఎంచుకోండి:"</string> - <string name="accessibility_button_instructional_text" msgid="6942300463612999993">"లక్షణాలను మార్చడానికి, ప్రాప్యత బటన్ను నొక్కి & పట్టుకోండి."</string> + <string name="accessibility_shortcut_enabling_service" msgid="7771852911861522636">"యాక్సెస్ సామర్థ్య షార్ట్కట్ ద్వారా <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆన్ చేయబడింది"</string> + <string name="accessibility_shortcut_disabling_service" msgid="2747243438223109821">"యాక్సెస్ సామర్థ్య షార్ట్కట్ ద్వారా <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆఫ్ చేయబడింది"</string> + <string name="accessibility_button_prompt_text" msgid="4234556536456854251">"యాక్సెస్ బటన్ను మీరు నొక్కినప్పుడు ఉపయోగించాల్సిన ఒక ఫీచర్ను ఎంచుకోండి:"</string> + <string name="accessibility_button_instructional_text" msgid="6942300463612999993">"ఫీచర్లను మార్చడానికి, యాక్సెస్ సామర్థ్య బటన్ను నొక్కి & పట్టుకోండి."</string> <string name="accessibility_magnification_chooser_text" msgid="1227146738764986237">"మాగ్నిఫికేషన్"</string> <string name="user_switched" msgid="3768006783166984410">"ప్రస్తుత వినియోగదారు <xliff:g id="NAME">%1$s</xliff:g>."</string> <string name="user_switching_message" msgid="2871009331809089783">"<xliff:g id="NAME">%1$s</xliff:g>కి మారుస్తోంది…"</string> <string name="user_logging_out_message" msgid="8939524935808875155">"<xliff:g id="NAME">%1$s</xliff:g>ని లాగ్ అవుట్ చేస్తోంది…"</string> <string name="owner_name" msgid="2716755460376028154">"యజమాని"</string> - <string name="error_message_title" msgid="4510373083082500195">"లోపం"</string> + <string name="error_message_title" msgid="4510373083082500195">"ఎర్రర్"</string> <string name="error_message_change_not_allowed" msgid="1238035947357923497">"ఈ మార్పును మీ నిర్వాహకులు అనుమతించలేదు"</string> <string name="app_not_found" msgid="3429141853498927379">"ఈ చర్యను నిర్వహించడానికి యాప్ ఏదీ కనుగొనబడలేదు"</string> <string name="revoke" msgid="5404479185228271586">"ఉపసంహరించండి"</string> @@ -1584,7 +1584,7 @@ <string name="mediasize_unknown_portrait" msgid="3088043641616409762">"తెలియని పొర్ట్రెయిట్"</string> <string name="mediasize_unknown_landscape" msgid="4876995327029361552">"తెలియని ల్యాండ్స్కేప్"</string> <string name="write_fail_reason_cancelled" msgid="7091258378121627624">"రద్దు చేయబడింది"</string> - <string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"కంటెంట్ను వ్రాయడంలో లోపం"</string> + <string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"కంటెంట్ను వ్రాయడంలో ఎర్రర్"</string> <string name="reason_unknown" msgid="6048913880184628119">"తెలియదు"</string> <string name="reason_service_unavailable" msgid="7824008732243903268">"ముద్రణ సేవ ప్రారంభించబడలేదు"</string> <string name="print_service_installed_title" msgid="2246317169444081628">"<xliff:g id="NAME">%s</xliff:g> సేవ ఇన్స్టాల్ చేయబడింది"</string> @@ -1627,7 +1627,7 @@ <string name="package_installed_device_owner" msgid="6875717669960212648">"మీ నిర్వాహకులు ఇన్స్టాల్ చేసారు"</string> <string name="package_updated_device_owner" msgid="1847154566357862089">"మీ నిర్వాహకులు నవీకరించారు"</string> <string name="package_deleted_device_owner" msgid="2307122077550236438">"మీ నిర్వాహకులు తొలగించారు"</string> - <string name="battery_saver_description" msgid="1960431123816253034">"బ్యాటరీ జీవితకాలాన్ని మెరుగుపరచడంలో సహాయపడటానికి, బ్యాటరీ సేవర్ మీ పరికరం పనితీరును తగ్గిస్తుంది మరియు వైబ్రేషన్ను, స్థాన సేవలను మరియు అత్యధిక నేపథ్య డేటాను పరిమితం చేస్తుంది. ఇమెయిల్, మెసేజింగ్ మరియు సమకాలీకరణపై ఆధారపడే ఇతర అనువర్తనాలు మీరు వాటిని తెరిస్తే మినహా నవీకరించబడవు.\n\nమీ పరికరం ఛార్జ్ అవుతున్నప్పుడు బ్యాటరీ సేవర్ స్వయంచాలకంగా ఆఫ్ అవుతుంది."</string> + <string name="battery_saver_description" msgid="1960431123816253034">"బ్యాటరీ జీవితకాలాన్ని మెరుగుపరచడంలో సహాయపడటానికి, బ్యాటరీ సేవర్ మీ పరికరం పనితీరును తగ్గిస్తుంది మరియు వైబ్రేషన్ను, స్థాన సేవలను మరియు అత్యధిక నేపథ్య డేటాను పరిమితం చేస్తుంది. ఇమెయిల్, మెసేజింగ్ మరియు సమకాలీకరణపై ఆధారపడే ఇతర యాప్లు మీరు వాటిని తెరిస్తే మినహా అప్డేట్ చేయబడవు.\n\nమీ పరికరం ఛార్జ్ అవుతున్నప్పుడు బ్యాటరీ సేవర్ స్వయంచాలకంగా ఆఫ్ అవుతుంది."</string> <string name="data_saver_description" msgid="6015391409098303235">"డేటా వినియోగాన్ని తగ్గించడంలో సహాయకరంగా ఉండటానికి, డేటా సేవర్ కొన్ని యాప్లను నేపథ్యంలో డేటాను పంపకుండా లేదా స్వీకరించకుండా నిరోధిస్తుంది. మీరు ప్రస్తుతం ఉపయోగిస్తున్న యాప్ డేటాను యాక్సెస్ చేయగలదు కానీ అలా అరుదుగా చేయవచ్చు. అంటే, ఉదాహరణకు, మీరు ఆ చిత్రాలను నొక్కే వరకు అవి ప్రదర్శించబడవు."</string> <string name="data_saver_enable_title" msgid="4674073932722787417">"డేటా సేవర్ను ఆన్ చేయాలా?"</string> <string name="data_saver_enable_button" msgid="7147735965247211818">"ఆన్ చేయి"</string> @@ -1710,7 +1710,7 @@ <string name="language_picker_section_suggested" msgid="8414489646861640885">"సూచించినవి"</string> <string name="language_picker_section_all" msgid="3097279199511617537">"అన్ని భాషలు"</string> <string name="region_picker_section_all" msgid="8966316787153001779">"అన్ని ప్రాంతాలు"</string> - <string name="locale_search_menu" msgid="2560710726687249178">"శోధించు"</string> + <string name="locale_search_menu" msgid="2560710726687249178">"వెతుకు"</string> <string name="work_mode_off_title" msgid="2615362773958585967">"కార్యాలయ మోడ్ని ఆన్ చేయాలా?"</string> <string name="work_mode_off_message" msgid="2961559609199223594">"ఇది అనువర్తనాలు, నేపథ్య సమకాలీకరణ మరియు సంబంధిత లక్షణాలతో సహా మీ కార్యాలయ ప్రొఫైల్ను ఆన్ చేస్తుంది"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"ఆన్ చేయి"</string> @@ -1725,7 +1725,7 @@ <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"ఫైల్లను వీక్షించడానికి నొక్కండి"</string> <string name="pin_target" msgid="3052256031352291362">"పిన్ చేయి"</string> <string name="unpin_target" msgid="3556545602439143442">"అన్పిన్ చేయి"</string> - <string name="app_info" msgid="6856026610594615344">"అనువర్తన సమాచారం"</string> + <string name="app_info" msgid="6856026610594615344">"యాప్ సమాచారం"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="demo_starting_message" msgid="5268556852031489931">"డెమోను ప్రారంభిస్తోంది..."</string> <string name="demo_restarting_message" msgid="952118052531642451">"పరికరాన్ని రీసెట్ చేస్తోంది..."</string> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index 497c73311273..802d0ee6d523 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"การแจ้งเตือน"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"การสาธิตสำหรับผู้ค้าปลีก"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"การเชื่อมต่อ USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"แอปที่กำลังทำงานในเบื้องหลัง"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังทำงานในเบื้องหลัง"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"แอป <xliff:g id="NUMBER">%1$d</xliff:g> กำลังทำงานในเบื้องหลัง"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"แอปหลายแอปกำลังใช้แบตเตอรี่"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังใช้แบตเตอรี่"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"แอป <xliff:g id="NUMBER">%1$d</xliff:g> แอปกำลังใช้แบตเตอรี่"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"แตะเพื่อดูรายละเอียดเกี่ยวกับแบตเตอรี่และปริมาณการใช้อินเทอร์เน็ต"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"โหมดปลอดภัย"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"เชื่อมต่อกับ <xliff:g id="SESSION">%s</xliff:g> แตะเพื่อจัดการเครือข่าย"</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"กำลังเชื่อมต่อ VPN แบบเปิดตลอดเวลา…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"เชื่อมต่อ VPN แบบเปิดตลอดเวลาแล้ว"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"ยกเลิกการเชื่อมต่อ VPN แบบเปิดตลอดเวลาแล้ว"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"ยกเลิกการเชื่อมต่อกับ VPN แบบเปิดตลอดเวลาแล้ว"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"ข้อผิดพลาดของ VPN แบบเปิดตลอดเวลา"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"แตะเพื่อตั้งค่า"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"เปลี่ยนเครือข่ายหรือการตั้งค่า VPN"</string> <string name="upload_file" msgid="2897957172366730416">"เลือกไฟล์"</string> <string name="no_file_chosen" msgid="6363648562170759465">"ไม่ได้เลือกไฟล์ไว้"</string> <string name="reset" msgid="2448168080964209908">"รีเซ็ต"</string> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index 7e74b1e9cadf..36f94d4bfa54 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Mga Alerto"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Retail demo"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Koneksyon ng USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Tumatakbo ang mga app sa background"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"Tumatakbo ang <xliff:g id="APP_NAME">%1$s</xliff:g> sa background"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> (na) app ang tumatakbo sa background"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Mga app na kumokonsumo ng baterya"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"Gumagamit ng baterya ang <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"Gumagamit ng baterya ang <xliff:g id="NUMBER">%1$d</xliff:g> (na) app"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"I-tap para sa mga detalye tungkol sa paggamit ng baterya at data"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Nakakonekta sa <xliff:g id="SESSION">%s</xliff:g>. Tapikin upang pamahalaan ang network."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Kumukonekta ang Always-on VPN…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Nakakonekta ang Always-on VPN"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Hindi nakakonekta ang palaging naka-on na VPN"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Nadiskonekta sa VPN na palaging naka-on"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Error sa Always-on VPN"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"I-tap upang i-set up"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Baguhin ang mga setting ng network o VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Pumili ng file"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Walang napiling file"</string> <string name="reset" msgid="2448168080964209908">"I-reset"</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 762f2908242d..99b88a0430d5 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Uyarılar"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Mağaza demo"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB bağlantısı"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Arka planda çalışan uygulamalar"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> arka planda çalışıyor"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> uygulama arka planda çalışıyor"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Pil kullanan uygulamalar"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> pil kullanıyor"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> uygulama pil kullanıyor"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Pil ve veri kullanımı ile ilgili ayrıntılar için dokunun"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Güvenli mod"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> oturumuna bağlı. Ağı yönetmek için dokunun."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Her zaman açık VPN\'ye bağlanılıyor…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Her zaman açık VPN\'ye bağlanıldı"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Her zaman açık VPN bağlantısı kesildi"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Her zaman açık VPN bağlantı kesildi"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Her zaman açık VPN hatası"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Ayarlamak için dokunun"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Ağ veya VPN ayarlarını değiştirin"</string> <string name="upload_file" msgid="2897957172366730416">"Dosya seç"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Seçili dosya yok"</string> <string name="reset" msgid="2448168080964209908">"Sıfırla"</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index df1d8ce96139..98663b5f5fde 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -254,9 +254,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Сповіщення"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Демо-режим для роздрібної торгівлі"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"З’єднання USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Додатки, які працюють у фоновому режимі"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> працює у фоновому режимі"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"Додатки, які працюють у фоновому режимі: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Додатки, що використовують заряд акумулятора"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> використовує заряд акумулятора"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"Додатків, що використовують заряд акумулятора: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Торкніться, щоб перевірити використання акумулятора й трафік"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Безп. режим"</string> @@ -1338,9 +1338,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Під’єднано до <xliff:g id="SESSION">%s</xliff:g>. Торкніться, щоб керувати мережею."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Під’єднання до постійної мережі VPN…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Під’єднано до постійної мережі VPN"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Постійну мережу VPN від’єднано"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Від’єднано від постійної мережі VPN"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Помилка постійної мережі VPN"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Торкніться, щоб налаштувати"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Змінити налаштування мережі або VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Виберіть файл"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Не вибрано файл"</string> <string name="reset" msgid="2448168080964209908">"Скинути"</string> diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml index f06f775c33b7..0cef2228733c 100644 --- a/core/res/res/values-ur/strings.xml +++ b/core/res/res/values-ur/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"الرٹس"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"ریٹیل ڈیمو"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB کنکشن"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"ایپس پس منظر میں چل رہی ہیں"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> پس منظر میں چل رہی ہے"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> ایپس پس منظر میں چل رہی ہیں"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"ایپس بیٹری خرچ کر رہی ہیں"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> بیٹری کا استعمال کر رہی ہے"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> ایپس بیٹری کا استعمال کر رہی ہیں"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"بیٹری اور ڈیٹا استعمال کے بارے میں تفصیلات کے لیے تھپتھپائیں"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>، <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"حفاظتی وضع"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> سے منسلک ہے۔ نیٹ ورک کا نظم کرنے کیلئے تھپتھپائیں۔"</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"ہمیشہ آن VPN مربوط ہو رہا ہے…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"ہمیشہ آن VPN مربوط ہوگیا"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"ہمیشہ آن VPN غیر منسلک ہو گیا"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"ہمیشہ آن VPN سے غیر منسلک ہو گيا"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"ہمیشہ آن VPN کی خرابی"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"سیٹ اپ کرنے کیلئے تھپتھپائیں"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"نیٹ ورک یا VPN کی ترتیبات تبدیل کریں"</string> <string name="upload_file" msgid="2897957172366730416">"فائل منتخب کریں"</string> <string name="no_file_chosen" msgid="6363648562170759465">"کوئی فائل منتخب نہیں کی گئی"</string> <string name="reset" msgid="2448168080964209908">"دوبارہ ترتیب دیں"</string> diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index 931cbe922d7b..ea8609f5455a 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Ogohlantirishlar"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Demo rejim"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB orqali ulanish"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Fonda ishlayotgan ilovalar"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> orqa fonda ishlayapti"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> ta ilova fonda ishlamoqda"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Batareya quvvatini sarflayotgan ilovalar"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi batareya quvvatini sarflamoqda"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> ta ilova batareya quvvatini sarflamoqda"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Batareya va trafik sarfi tafsilotlari uchun ustiga bosing"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Xavfsiz usul"</string> @@ -1205,7 +1205,7 @@ <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Til va sxemani belgilash uchun bosing"</string> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> - <string name="alert_windows_notification_channel_group_name" msgid="1463953341148606396">"Boshqa oynalar ustidan ochish"</string> + <string name="alert_windows_notification_channel_group_name" msgid="1463953341148606396">"Boshqa ilovalar ustidan ochilish"</string> <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> boshqa ilovalar ustidan ochilgan"</string> <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> boshqa ilovalar ustidan ochilgan"</string> <string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> ilovasi uchun bu funksiyani sozlamalar orqali o‘chirib qo‘yish mumkin."</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> ulandi. Tarmoq sozlamalarini o‘zgartirish uchun bu yerni bosing."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Ulanmoqda…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Ulandi"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Doimiy VPN o‘chirildi"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Doimiy VPN tarmoqdan uzildi"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Xato"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Sozlash uchun bosing"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Tarmoq yoki VPN sozlamalarini o‘zgartiring"</string> <string name="upload_file" msgid="2897957172366730416">"Faylni tanlash"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Hech qanday fayl tanlanmadi"</string> <string name="reset" msgid="2448168080964209908">"Asliga qaytarish"</string> @@ -1603,7 +1603,7 @@ <item quantity="one">1 soniyadan so‘ng qayta urinib ko‘ring</item> </plurals> <string name="restr_pin_try_later" msgid="973144472490532377">"Keyinroq urinib ko‘ring"</string> - <string name="immersive_cling_title" msgid="8394201622932303336">"To‘liq ekran ko‘rsatilmoqda"</string> + <string name="immersive_cling_title" msgid="8394201622932303336">"To‘liq ekranli rejim"</string> <string name="immersive_cling_description" msgid="3482371193207536040">"Chiqish uchun tepadan pastga torting."</string> <string name="immersive_cling_positive" msgid="5016839404568297683">"OK"</string> <string name="done_label" msgid="2093726099505892398">"Tayyor"</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 9ef8670c599a..89ee92f31393 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Cảnh báo"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Giới thiệu bán lẻ"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Kết nối USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Ứng dụng đang chạy trong nền"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang chạy ẩn"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> ứng dụng đang chạy trong nền"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Các ứng dụng tiêu thụ pin"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang sử dụng pin"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> ứng dụng đang sử dụng pin"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Nhấn để biết chi tiết về mức sử dụng dữ liệu và pin"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Chế độ an toàn"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Đã kết nối với <xliff:g id="SESSION">%s</xliff:g>. Chạm để quản lý mạng."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Đang kết nối VPN luôn bật…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Đã kết nối VPN luôn bật"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Đã ngắt kết nối VPN luôn bật"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Đã ngắt kết nối khỏi VPN luôn bật"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Lỗi VPN luôn bật"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Nhấn để thiết lập"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Thay đổi cài đặt mạng hoặc VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Chọn tệp"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Không có tệp nào được chọn"</string> <string name="reset" msgid="2448168080964209908">"Đặt lại"</string> @@ -1604,7 +1604,7 @@ </plurals> <string name="restr_pin_try_later" msgid="973144472490532377">"Hãy thử lại sau"</string> <string name="immersive_cling_title" msgid="8394201622932303336">"Xem toàn màn hình"</string> - <string name="immersive_cling_description" msgid="3482371193207536040">"Để thoát, hãy vuốt xuống từ trên cùng."</string> + <string name="immersive_cling_description" msgid="3482371193207536040">"Để thoát, hãy vuốt từ trên cùng xuống dưới."</string> <string name="immersive_cling_positive" msgid="5016839404568297683">"OK"</string> <string name="done_label" msgid="2093726099505892398">"Xong"</string> <string name="hour_picker_description" msgid="6698199186859736512">"Thanh trượt giờ hình tròn"</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 98e7e7615190..7f4885fdb0a2 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"提醒"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"零售演示模式"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB 连接"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"在后台运行的应用"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g>正在后台运行"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> 个应用正在后台运行"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"消耗电量的应用"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g>正在消耗电量"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> 个应用正在消耗电量"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"点按即可详细了解电量和流量消耗情况"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>、<xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"安全模式"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"已连接到<xliff:g id="SESSION">%s</xliff:g>。点按即可管理网络。"</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"正在连接到始终开启的 VPN…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"已连接到始终开启的 VPN"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"始终开启的 VPN 已断开连接"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"始终开启的 VPN 已断开连接"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"始终开启的 VPN 出现错误"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"点按即可进行设置"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"更改网络或 VPN 设置"</string> <string name="upload_file" msgid="2897957172366730416">"选择文件"</string> <string name="no_file_chosen" msgid="6363648562170759465">"未选定任何文件"</string> <string name="reset" msgid="2448168080964209908">"重置"</string> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index 87c78aa69850..180d31ee8de0 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"通知"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"零售示範"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB 連線"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"正在背景中執行的應用程式"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在背景執行"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> 個應用程式正在背景中執行"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"耗用電量的應用程式"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在使用電量"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> 個應用程式正在使用電量"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"輕按即可查看電池和數據用量詳情"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>、<xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"安全模式"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"已連線至 <xliff:g id="SESSION">%s</xliff:g>,輕按一下即可管理網絡。"</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"正在連線至永久連線的 VPN…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"已連線至永久連線的 VPN"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"永久連線的 VPN 已中斷"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"永遠開啟的 VPN 已中斷連線"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"永久連線的 VPN 發生錯誤"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"輕按即可設定"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"變更網絡或 VPN 設定"</string> <string name="upload_file" msgid="2897957172366730416">"選擇檔案"</string> <string name="no_file_chosen" msgid="6363648562170759465">"未選擇檔案"</string> <string name="reset" msgid="2448168080964209908">"重設"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 4fabbe2c3728..046c8bdb8f3a 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"快訊"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"零售商示範模式"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"USB 連線"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"在背景執行的應用程式"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在背景執行"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> 個應用程式正在背景執行"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"正在耗用電量的應用程式"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在耗用電量"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> 個應用程式正在耗用電量"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"輕觸即可查看電池和數據用量詳情"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>、<xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"安全模式"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"已連線至 <xliff:g id="SESSION">%s</xliff:g>,輕觸一下即可管理網路。"</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"正在連線至永久連線的 VPN…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"已連線至永久連線的 VPN"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"永久連線的 VPN 已中斷連線"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"已中斷連線至永久連線的 VPN"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"永久連線的 VPN 發生錯誤"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"輕觸即可進行設定"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"變更網路或 VPN 設定"</string> <string name="upload_file" msgid="2897957172366730416">"選擇檔案"</string> <string name="no_file_chosen" msgid="6363648562170759465">"未選擇任何檔案"</string> <string name="reset" msgid="2448168080964209908">"重設"</string> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index ffe751db064d..f74ab76fc71e 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -248,9 +248,9 @@ <string name="notification_channel_alerts" msgid="4496839309318519037">"Izexwayiso"</string> <string name="notification_channel_retail_mode" msgid="6088920674914038779">"Idemo yokuthenga"</string> <string name="notification_channel_usb" msgid="9006850475328924681">"Ukuxhumeka kwe-USB"</string> - <string name="notification_channel_foreground_service" msgid="6665375982962336520">"Izinhlelo zokusebenza zisebenza ngasemuva"</string> - <string name="foreground_service_app_in_background" msgid="6826789589341671842">"<xliff:g id="APP_NAME">%1$s</xliff:g> iyasebenza ngemuva"</string> - <string name="foreground_service_apps_in_background" msgid="7150914856893450380">"<xliff:g id="NUMBER">%1$d</xliff:g> izinhlelo zokusebenza ziyasebenza ngemuva"</string> + <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Izinhlelo zokusebenza ezidla ibhethri"</string> + <string name="foreground_service_app_in_background" msgid="1060198778219731292">"<xliff:g id="APP_NAME">%1$s</xliff:g> isebenzisa ibhethri"</string> + <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> izinhlelo zokusebenza zisebenzisa ibhethri"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Thepha ngemininingwane ekusetshenzisweni kwebhethri nedatha"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Imodi ephephile"</string> @@ -1294,9 +1294,9 @@ <string name="vpn_text_long" msgid="4907843483284977618">"Ixhume ku-<xliff:g id="SESSION">%s</xliff:g>. Thepha ukuphatha inethiwekhi."</string> <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"I-VPN ehlala ikhanya iyaxhuma…"</string> <string name="vpn_lockdown_connected" msgid="8202679674819213931">"I-VPN ehlala ikhanya ixhunyiwe"</string> - <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Njalo kuvuliwe i-VPN kunqamukile"</string> + <string name="vpn_lockdown_disconnected" msgid="735805531187559719">"Inqamukile kusuka ku-VPN njalo"</string> <string name="vpn_lockdown_error" msgid="6009249814034708175">"Iphutha le-VPN ehlala ikhanya"</string> - <string name="vpn_lockdown_config" msgid="5099330695245008680">"Thepha ukuze usethe"</string> + <string name="vpn_lockdown_config" msgid="8151951501116759194">"Shintsha inethiwekhi noma izilungiselelo ze-VPN"</string> <string name="upload_file" msgid="2897957172366730416">"Khetha ifayela"</string> <string name="no_file_chosen" msgid="6363648562170759465">"Ayikho ifayela ekhethiwe"</string> <string name="reset" msgid="2448168080964209908">"Setha kabusha"</string> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 4cf5e8bdcb95..598b5861af15 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2087,6 +2087,16 @@ {@link android.R.attr#windowBackground}. --> <attr name="windowSplashscreenContent" format="reference" /> + + <!-- If set, the navigation bar will be drawn such that it is compatible with a light + navigation bar background. + <p>For this to take effect, the window must be drawing the system bar backgrounds with + {@link android.R.attr#windowDrawsSystemBarBackgrounds} and the navigation bar must not + have been requested to be translucent with + {@link android.R.attr#windowTranslucentNavigation}. + Corresponds to setting {@link android.view.View#SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR} on + the decor view. --> + <attr name="windowLightNavigationBar" format="boolean" /> </declare-styleable> <!-- The set of attributes that describe a AlertDialog's theme. --> @@ -4401,7 +4411,7 @@ <attr name="textStyle" /> <!-- Typeface (normal, sans, serif, monospace) for the text. --> <attr name="typeface" /> - <!-- Font family (named by string) for the text. --> + <!-- Font family (named by string or as a font resource reference) for the text. --> <attr name="fontFamily" /> <!-- Color of the text selection highlight. --> <attr name="textColorHighlight" /> @@ -4484,7 +4494,7 @@ <attr name="typeface" /> <!-- Style (bold, italic, bolditalic) for the text. --> <attr name="textStyle" /> - <!-- Font family (named by string) for the text. --> + <!-- Font family (named by string or as a font resource reference) for the text. --> <attr name="fontFamily" /> <!-- Text color for links. --> <attr name="textColorLink" /> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 07a9a33897a3..793b5b2ae253 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -242,9 +242,9 @@ <!-- Additional flag from base permission type: this permission can be automatically granted to the setup wizard app --> <flag name="setup" value="0x800" /> - <!-- Additional flag from base permission type: this permission can be granted to ephemeral + <!-- Additional flag from base permission type: this permission can be granted to instant apps --> - <flag name="ephemeral" value="0x1000" /> + <flag name="instant" value="0x1000" /> <!-- Additional flag from base permission type: this permission can only be granted to apps that target runtime permissions ({@link android.os.Build.VERSION_CODES#M} and above) --> @@ -1781,6 +1781,11 @@ the library at build time while it offers apps to share code defined in such libraries. Hence, static libraries are strictly required. + <p>On devices running O MR1 or higher, if the library is singed with multiple + signing certificates you must to specify the SHA-256 hashes of the additional + certificates via adding + {@link #AndroidManifestAdditionalCertificate additional-certificate} tags. + <p>This appears as a child tag of the {@link #AndroidManifestApplication application} tag. --> <declare-styleable name="AndroidManifestUsesStaticLibrary" parent="AndroidManifestApplication"> @@ -1792,6 +1797,17 @@ <attr name="certDigest" format="string" /> </declare-styleable> + <!-- The <code>additional-certificate</code> specifies the SHA-256 digest of a static + shared library's additional signing certificate. You need to use this tag if the + library is singed with more than one certificate. + + <p>This appears as a child tag of the + {@link #AndroidManifestUsesStaticLibrary uses-static-library} tag. --> + <declare-styleable name="AndroidManifestAdditionalCertificate" parent="AndroidManifestUsesStaticLibrary"> + <!-- The SHA-256 digest of the library signing certificate. --> + <attr name="certDigest" /> + </declare-styleable> + <!-- The <code>supports-screens</code> specifies the screen dimensions an application supports. By default a modern application supports all screen sizes and must explicitly disable certain screen sizes here; diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 95aa264639ac..05f3ff1279dd 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -301,6 +301,17 @@ less than 0x600 --> <bool translatable="false" name="config_apfDrop802_3Frames">true</bool> + <!-- An array of Black listed EtherType, packets with EtherTypes within this array + will be dropped + TODO: need to put proper values, these are for testing purposes only --> + <integer-array translatable="false" name="config_apfEthTypeBlackList"> + <item>0x88A2</item> + <item>0x88A4</item> + <item>0x88B8</item> + <item>0x88CD</item> + <item>0x88E3</item> + </integer-array> + <!-- Default value for ConnectivityManager.getMultipathPreference() on metered networks. Actual device behaviour is controlled by Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE. This is the default value of that setting. --> @@ -531,15 +542,18 @@ <!-- Integer parameters of the wifi to cellular handover feature wifi should not stick to bad networks --> <integer translatable="false" name="config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz">-82</integer> + <integer translatable="false" name="config_wifi_framework_wifi_score_entry_rssi_threshold_5GHz">-82</integer> <integer translatable="false" name="config_wifi_framework_wifi_score_low_rssi_threshold_5GHz">-70</integer> <integer translatable="false" name="config_wifi_framework_wifi_score_good_rssi_threshold_5GHz">-57</integer> <integer translatable="false" name="config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz">-85</integer> + <integer translatable="false" name="config_wifi_framework_wifi_score_entry_rssi_threshold_24GHz">-85</integer> <integer translatable="false" name="config_wifi_framework_wifi_score_low_rssi_threshold_24GHz">-73</integer> <integer translatable="false" name="config_wifi_framework_wifi_score_good_rssi_threshold_24GHz">-60</integer> <integer translatable="false" name="config_wifi_framework_wifi_score_bad_link_speed_24">6</integer> <integer translatable="false" name="config_wifi_framework_wifi_score_bad_link_speed_5">12</integer> <integer translatable="false" name="config_wifi_framework_wifi_score_good_link_speed_24">24</integer> <integer translatable="false" name="config_wifi_framework_wifi_score_good_link_speed_5">36</integer> + <string translatable="false" name="config_wifi_random_mac_oui">DA-A1-19</string> <string translatable="false" name="config_wifi_framework_sap_2G_channel_list">1,6,11</string> @@ -626,10 +640,10 @@ <bool name="config_automatic_brightness_available">false</bool> <!-- Fast brightness animation ramp rate in brightness units per second--> - <integer translatable="false" name="config_brightness_ramp_rate_fast">200</integer> + <integer translatable="false" name="config_brightness_ramp_rate_fast">180</integer> <!-- Slow brightness animation ramp rate in brightness units per second--> - <integer translatable="false" name="config_brightness_ramp_rate_slow">40</integer> + <integer translatable="false" name="config_brightness_ramp_rate_slow">60</integer> <!-- Don't name config resources like this. It should look like config_annoyDianne --> <bool name="config_annoy_dianne">true</bool> @@ -879,6 +893,18 @@ <!-- Maximum color temperature, in Kelvin, supported by Night display. --> <integer name="config_nightDisplayColorTemperatureMax">4082</integer> + <string-array name="config_nightDisplayColorTemperatureCoefficients"> + <!-- R a-coefficient --> <item>0.0</item> + <!-- R b-coefficient --> <item>0.0</item> + <!-- R y-intercept --> <item>1.0</item> + <!-- G a-coefficient --> <item>-0.00000000962353339</item> + <!-- G b-coefficient --> <item>0.000153045476</item> + <!-- G y-intercept --> <item>0.390782778</item> + <!-- B a-coefficient --> <item>-0.0000000189359041</item> + <!-- B b-coefficient --> <item>0.000302412211</item> + <!-- B y-intercept --> <item>-0.198650895</item> + </string-array> + <!-- Indicate whether to allow the device to suspend when the screen is off due to the proximity sensor. This resource should only be set to true if the sensor HAL correctly handles the proximity sensor as a wake-up source. @@ -2197,10 +2223,14 @@ <string name="config_customAdbPublicKeyConfirmationSecondaryUserComponent" >com.android.systemui/com.android.systemui.usb.UsbDebuggingSecondaryUserActivity</string> - <!-- Name of the CustomDialog that is used for VPN --> - <string name="config_customVpnConfirmDialogComponent" + <!-- Name of the dialog that is used to request the user's consent to VPN connection --> + <string name="config_customVpnConfirmDialogComponent" translatable="false" >com.android.vpndialogs/com.android.vpndialogs.ConfirmDialog</string> + <!-- Name of the dialog that is used to inform the user that always-on VPN is disconnected --> + <string name="config_customVpnAlwaysOnDisconnectedDialogComponent" translatable="false" + >com.android.vpndialogs/com.android.vpndialogs.AlwaysOnDisconnectedDialog</string> + <!-- Apps that are authorized to access shared accounts, overridden by product overlays --> <string name="config_appsAuthorizedForSharedAccounts" translatable="false">;com.android.settings;</string> @@ -3041,4 +3071,10 @@ <!-- Allow SystemUI to show the shutdown dialog --> <bool name="config_showSysuiShutdown">true</bool> + + <!-- The stable device width and height in pixels. If these aren't set to a positive number + then the device will use the width and height of the default display the first time it's + booted. --> + <integer name="config_stableDeviceDisplayWidth">-1</integer> + <integer name="config_stableDeviceDisplayHeight">-1</integer> </resources> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 12feba941103..9b1ebc877384 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -438,15 +438,6 @@ <!-- Width of the outline stroke used by the accessibility screen magnification indicator --> <dimen name="accessibility_magnification_indicator_width">4dip</dimen> - <!-- Width of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) --> - <dimen name="keyguard_security_width">320dp</dimen> - - <!-- Height of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) --> - <dimen name="keyguard_security_height">400dp</dimen> - - <!-- Margin around the various security views --> - <dimen name="keyguard_security_view_margin">8dp</dimen> - <!-- Margin around the various security views --> <dimen name="keyguard_muliuser_selector_margin">8dp</dimen> @@ -592,6 +583,21 @@ <!-- The size of the right icon --> <dimen name="notification_right_icon_size">40dp</dimen> + <!-- The maximum height of any image in a remote view. This is applied to all images in custom remoteviews. --> + <dimen name="notification_custom_view_max_image_height_low_ram">208dp</dimen> + <!-- The maximum height of any image in a remote view. This is applied to all images in custom remoteviews. --> + <dimen name="notification_custom_view_max_image_width_low_ram">294dp</dimen> + <!-- The maximum height of a big picture in a notification. The images will be reduced to that height in case they are bigger. --> + <dimen name="notification_big_picture_max_height_low_ram">208dp</dimen> + <!-- The maximum width of a big picture in a notification. The images will be reduced to that width in case they are bigger. --> + <dimen name="notification_big_picture_max_width_low_ram">294dp</dimen> + <!-- The maximum height of a image in a media notification. The images will be reduced to that height in case they are bigger. --> + <dimen name="notification_media_image_max_height_low_ram">100dp</dimen> + <!-- The maximum width of a image in a media notification. The images will be reduced to that width in case they are bigger.--> + <dimen name="notification_media_image_max_width_low_ram">100dp</dimen> + <!-- The size of the right icon image when on low ram --> + <dimen name="notification_right_icon_size_low_ram">40dp</dimen> + <!-- Max width/height of the autofill data set picker as a fraction of the screen width/height --> <dimen name="autofill_dataset_picker_max_size">90%</dimen> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 634d79a92a4b..9b2f18511e83 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2858,6 +2858,27 @@ <public name="autofill"/> </public-group> + <!-- =============================================================== + Resources added in version P of the platform + + NOTE: add <public> elements within a <public-group> like so: + + <public-group type="attr" first-id="0x01010531"> + <public name="exampleAttr1" /> + <public name="exampleAttr2" /> + </public-group> + + To add a new public-group block, choose an id value that is 1 greater + than the last of that item above. For example, the last "attr" id + value above is 0x01010530, so the public-group of attrs below has + the id value of 0x01010531. + =============================================================== --> + <eat-comment /> + + <public-group type="attr" first-id="0x0101056c"> + <public name="windowLightNavigationBar" /> + </public-group> + <!-- =============================================================== DO NOT ADD UN-GROUPED ITEMS HERE diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 0ff24b76160e..9bd779e8cfb2 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -593,17 +593,18 @@ <!-- This is the label for the notification channel settings that controls the behavior of the notification about applications that are running in the background (that is, perhaps confusingly, running foreground services but not the foreground UI on the screen). - [CHAR LIMIT=NONE] --> - <string name="notification_channel_foreground_service">Apps running in background</string> + [CHAR LIMIT=NONE BACKUP_MESSAGE_ID=6665375982962336520] --> + <string name="notification_channel_foreground_service">Apps consuming battery</string> - <!-- Label for foreground service notification when one app is running. [CHAR LIMIT=NONE] --> + <!-- Label for foreground service notification when one app is running. + [CHAR LIMIT=NONE BACKUP_MESSAGE_ID=6826789589341671842] --> <string name="foreground_service_app_in_background"><xliff:g id="app_name">%1$s</xliff:g> is - running in the background</string> + using battery</string> <!-- Label for foreground service notification when multiple apps are running. - [CHAR LIMIT=NONE] --> + [CHAR LIMIT=NONE BACKUP_MESSAGE_ID=7150914856893450380] --> <string name="foreground_service_apps_in_background"><xliff:g id="number">%1$d</xliff:g> apps - are running in the background</string> + are using battery</string> <!-- Content for foreground service notification when one app is running. [CHAR LIMIT=NONE] --> @@ -3444,16 +3445,21 @@ <!-- The text of the notification when VPN is active with a session name. --> <string name="vpn_text_long">Connected to <xliff:g id="session" example="office">%s</xliff:g>. Tap to manage the network.</string> - <!-- Notification title when connecting to lockdown VPN. --> + <!-- Notification title when connecting to always-on VPN, a VPN that's set to always stay + connected. --> <string name="vpn_lockdown_connecting">Always-on VPN connecting\u2026</string> - <!-- Notification title when connected to lockdown VPN. --> + <!-- Notification title when connected to always-on VPN, a VPN that's set to always stay + connected. --> <string name="vpn_lockdown_connected">Always-on VPN connected</string> - <!-- Notification title when not connected to lockdown VPN. --> - <string name="vpn_lockdown_disconnected">Always-on VPN disconnected</string> - <!-- Notification title when error connecting to lockdown VPN. --> + <!-- Notification title when not connected to always-on VPN, a VPN that's set to always stay + connected. --> + <string name="vpn_lockdown_disconnected">Disconnected from always-on VPN</string> + <!-- Notification title when error connecting to always-on VPN, a VPN that's set to always stay + connected. --> <string name="vpn_lockdown_error">Always-on VPN error</string> - <!-- Notification body that indicates user can touch to configure lockdown VPN connection. --> - <string name="vpn_lockdown_config">Tap to set up</string> + <!-- Notification body that indicates user can touch to configure always-on VPN, a VPN that's + set to always stay connected. --> + <string name="vpn_lockdown_config">Change network or VPN settings</string> <!-- Localized strings for WebView --> <!-- Label for button in a WebView that will open a chooser to choose a file to upload --> @@ -3859,7 +3865,10 @@ <!-- Message shown when user enters wrong PIN --> <string name="kg_wrong_pin">Wrong PIN</string> <!-- Countdown message shown after too many failed unlock attempts --> - <string name="kg_too_many_failed_attempts_countdown">Try again in <xliff:g id="number">%1$d</xliff:g> seconds.</string> + <plurals name="kg_too_many_failed_attempts_countdown"> + <item quantity="one">Try again in 1 second.</item> + <item quantity="other">Try again in <xliff:g id="number">%d</xliff:g> seconds.</item> + </plurals> <!-- Instructions for using the pattern unlock screen --> <string name="kg_pattern_instructions">Draw your pattern</string> <!-- Instructions for using the SIM PIN unlock screen --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 326d31aa99d7..927d9dcec002 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -74,6 +74,7 @@ <java-symbol type="id" name="fillInIntent" /> <java-symbol type="id" name="find" /> <java-symbol type="id" name="fullscreenArea" /> + <java-symbol type="id" name="group_divider" /> <java-symbol type="id" name="hard_keyboard_section" /> <java-symbol type="id" name="hard_keyboard_switch" /> <java-symbol type="id" name="headers" /> @@ -357,9 +358,11 @@ <java-symbol type="integer" name="config_wifi_framework_associated_full_scan_max_total_dwell_time" /> <java-symbol type="integer" name="config_wifi_framework_associated_partial_scan_max_num_active_channels" /> <java-symbol type="integer" name="config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz" /> + <java-symbol type="integer" name="config_wifi_framework_wifi_score_entry_rssi_threshold_24GHz" /> <java-symbol type="integer" name="config_wifi_framework_wifi_score_low_rssi_threshold_24GHz" /> <java-symbol type="integer" name="config_wifi_framework_wifi_score_good_rssi_threshold_24GHz" /> <java-symbol type="integer" name="config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz" /> + <java-symbol type="integer" name="config_wifi_framework_wifi_score_entry_rssi_threshold_5GHz" /> <java-symbol type="integer" name="config_wifi_framework_wifi_score_low_rssi_threshold_5GHz" /> <java-symbol type="integer" name="config_wifi_framework_wifi_score_good_rssi_threshold_5GHz" /> <java-symbol type="integer" name="config_wifi_framework_wifi_score_bad_link_speed_24" /> @@ -1828,6 +1831,7 @@ <java-symbol type="integer" name="config_networkWakeupPacketMark" /> <java-symbol type="integer" name="config_networkWakeupPacketMask" /> <java-symbol type="bool" name="config_apfDrop802_3Frames" /> + <java-symbol type="array" name="config_apfEthTypeBlackList" /> <java-symbol type="integer" name="config_networkMeteredMultipathPreference" /> <java-symbol type="integer" name="config_notificationsBatteryFullARGB" /> <java-symbol type="integer" name="config_notificationsBatteryLedOff" /> @@ -2002,6 +2006,7 @@ <java-symbol type="string" name="config_customAdbPublicKeyConfirmationComponent" /> <java-symbol type="string" name="config_customAdbPublicKeyConfirmationSecondaryUserComponent" /> <java-symbol type="string" name="config_customVpnConfirmDialogComponent" /> + <java-symbol type="string" name="config_customVpnAlwaysOnDisconnectedDialogComponent" /> <java-symbol type="string" name="config_defaultNetworkScorerPackageName" /> <java-symbol type="string" name="config_persistentDataPackageName" /> @@ -2815,6 +2820,7 @@ <java-symbol type="integer" name="config_nightDisplayColorTemperatureDefault" /> <java-symbol type="integer" name="config_nightDisplayColorTemperatureMin" /> <java-symbol type="integer" name="config_nightDisplayColorTemperatureMax" /> + <java-symbol type="array" name="config_nightDisplayColorTemperatureCoefficients" /> <!-- Default first user restrictions --> <java-symbol type="array" name="config_defaultFirstUserRestrictions" /> @@ -2904,7 +2910,6 @@ <java-symbol type="id" name="autofill_save_title" /> <java-symbol type="id" name="autofill_save_no" /> <java-symbol type="id" name="autofill_save_yes" /> - <java-symbol type="id" name="autofill_save_close" /> <java-symbol type="string" name="autofill_error_cannot_autofill" /> <java-symbol type="string" name="autofill_picker_no_suggestions" /> <java-symbol type="plurals" name="autofill_picker_some_suggestions" /> @@ -2936,6 +2941,14 @@ <java-symbol type="dimen" name="notification_custom_view_max_image_height"/> <java-symbol type="dimen" name="notification_custom_view_max_image_width"/> + <java-symbol type="dimen" name="notification_big_picture_max_height_low_ram"/> + <java-symbol type="dimen" name="notification_big_picture_max_width_low_ram"/> + <java-symbol type="dimen" name="notification_media_image_max_width_low_ram"/> + <java-symbol type="dimen" name="notification_media_image_max_height_low_ram"/> + <java-symbol type="dimen" name="notification_right_icon_size_low_ram"/> + <java-symbol type="dimen" name="notification_custom_view_max_image_height_low_ram"/> + <java-symbol type="dimen" name="notification_custom_view_max_image_width_low_ram"/> + <!-- Accessibility fingerprint gestures --> <java-symbol type="string" name="capability_title_canCaptureFingerprintGestures" /> <java-symbol type="string" name="capability_desc_canCaptureFingerprintGestures" /> @@ -3064,4 +3077,7 @@ <java-symbol type="layout" name="shutdown_dialog" /> <java-symbol type="dimen" name="chooser_service_spacing" /> <java-symbol type="bool" name="config_showSysuiShutdown" /> + + <java-symbol type="integer" name="config_stableDeviceDisplayWidth" /> + <java-symbol type="integer" name="config_stableDeviceDisplayHeight" /> </resources> diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml index 7e9f561e68d5..f5b350b053d4 100644 --- a/core/res/res/xml/sms_short_codes.xml +++ b/core/res/res/xml/sms_short_codes.xml @@ -181,7 +181,7 @@ <shortcode country="mk" pattern="\\d{1,6}" free="129005|122" /> <!-- Mexico: 4-5 digits (not confirmed), known premium codes listed --> - <shortcode country="mx" pattern="\\d{4,5}" premium="53035|7766" free="46645|5050|26259|50025|50052|9963" /> + <shortcode country="mx" pattern="\\d{4,5}" premium="53035|7766" free="46645|5050|26259|50025|50052|9963|76551" /> <!-- Malaysia: 5 digits: http://www.skmm.gov.my/attachment/Consumer_Regulation/Mobile_Content_Services_FAQs.pdf --> <shortcode country="my" pattern="\\d{5}" premium="32298|33776" free="22099|28288" /> diff --git a/core/tests/coretests/assets/fonts/ascent1em-descent2em.ttf b/core/tests/coretests/assets/fonts/ascent1em-descent2em.ttf Binary files differnew file mode 100644 index 000000000000..f34698f3ebce --- /dev/null +++ b/core/tests/coretests/assets/fonts/ascent1em-descent2em.ttf diff --git a/core/tests/coretests/assets/fonts/ascent1em-descent2em.ttx b/core/tests/coretests/assets/fonts/ascent1em-descent2em.ttx new file mode 100644 index 000000000000..68d43239575f --- /dev/null +++ b/core/tests/coretests/assets/fonts/ascent1em-descent2em.ttx @@ -0,0 +1,181 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0"> + + <GlyphOrder> + <GlyphID id="0" name=".notdef"/> + <GlyphID id="1" name="1em"/> + </GlyphOrder> + + <head> + <tableVersion value="1.0"/> + <fontRevision value="1.0"/> + <checkSumAdjustment value="0x640cdb2f"/> + <magicNumber value="0x5f0f3cf5"/> + <flags value="00000000 00000011"/> + <unitsPerEm value="1000"/> + <created value="Fri Mar 17 07:26:00 2017"/> + <macStyle value="00000000 00000000"/> + <lowestRecPPEM value="7"/> + <fontDirectionHint value="2"/> + <glyphDataFormat value="0"/> + </head> + + <hhea> + <tableVersion value="0x10000"/> + <ascent value="1000"/> + <descent value="-2000"/> + <lineGap value="0"/> + <caretSlopeRise value="1"/> + <caretSlopeRun value="0"/> + <caretOffset value="0"/> + <reserved0 value="0"/> + <reserved1 value="0"/> + <reserved2 value="0"/> + <reserved3 value="0"/> + <metricDataFormat value="0"/> + </hhea> + + <maxp> + <tableVersion value="0x10000"/> + <maxZones value="0"/> + <maxTwilightPoints value="0"/> + <maxStorage value="0"/> + <maxFunctionDefs value="0"/> + <maxInstructionDefs value="0"/> + <maxStackElements value="0"/> + <maxSizeOfInstructions value="0"/> + <maxComponentElements value="0"/> + </maxp> + + <OS_2> + <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex' + will be recalculated by the compiler --> + <version value="3"/> + <xAvgCharWidth value="594"/> + <usWeightClass value="400"/> + <usWidthClass value="5"/> + <fsType value="00000000 00001000"/> + <ySubscriptXSize value="650"/> + <ySubscriptYSize value="600"/> + <ySubscriptXOffset value="0"/> + <ySubscriptYOffset value="75"/> + <ySuperscriptXSize value="650"/> + <ySuperscriptYSize value="600"/> + <ySuperscriptXOffset value="0"/> + <ySuperscriptYOffset value="350"/> + <yStrikeoutSize value="50"/> + <yStrikeoutPosition value="300"/> + <sFamilyClass value="0"/> + <panose> + <bFamilyType value="0"/> + <bSerifStyle value="0"/> + <bWeight value="5"/> + <bProportion value="0"/> + <bContrast value="0"/> + <bStrokeVariation value="0"/> + <bArmStyle value="0"/> + <bLetterForm value="0"/> + <bMidline value="0"/> + <bXHeight value="0"/> + </panose> + <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/> + <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/> + <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/> + <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/> + <achVendID value="UKWN"/> + <fsSelection value="00000000 01000000"/> + <usFirstCharIndex value="32"/> + <usLastCharIndex value="122"/> + <sTypoAscender value="800"/> + <sTypoDescender value="-200"/> + <sTypoLineGap value="200"/> + <usWinAscent value="1000"/> + <usWinDescent value="200"/> + <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/> + <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/> + <sxHeight value="500"/> + <sCapHeight value="700"/> + <usDefaultChar value="0"/> + <usBreakChar value="32"/> + <usMaxContext value="0"/> + </OS_2> + + <hmtx> + <mtx name=".notdef" width="1000" lsb="0"/> + <mtx name="1em" width="1000" lsb="0"/> + </hmtx> + + <cmap> + <tableVersion version="0"/> + <cmap_format_4 platformID="3" platEncID="10" language="0"> + <map code="0x0020" name="1em" /> <!-- SPACE --> + <map code="0x0061" name="1em" /> <!-- LATIN SMALL LETTER A --> + </cmap_format_4> + </cmap> + + <loca> + <!-- The 'loca' table will be calculated by the compiler --> + </loca> + + <glyf> + <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" /> + <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" /> + </glyf> + + <name> + <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409"> + Copyright (C) 2017 The Android Open Source Project + </namerecord> + <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409"> + Sample Font + </namerecord> + <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409"> + Regular + </namerecord> + <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409"> + Sample Font + </namerecord> + <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409"> + SampleFont-Regular + </namerecord> + <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409"> + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + 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. + </namerecord> + <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409"> + http://www.apache.org/licenses/LICENSE-2.0 + </namerecord> + </name> + + <post> + <formatType value="3.0"/> + <italicAngle value="0.0"/> + <underlinePosition value="-75"/> + <underlineThickness value="50"/> + <isFixedPitch value="0"/> + <minMemType42 value="0"/> + <maxMemType42 value="0"/> + <minMemType1 value="0"/> + <maxMemType1 value="0"/> + </post> + +</ttFont> diff --git a/core/tests/coretests/assets/fonts/ascent3em-descent4em.ttf b/core/tests/coretests/assets/fonts/ascent3em-descent4em.ttf Binary files differnew file mode 100644 index 000000000000..085d13377231 --- /dev/null +++ b/core/tests/coretests/assets/fonts/ascent3em-descent4em.ttf diff --git a/core/tests/coretests/assets/fonts/ascent3em-descent4em.ttx b/core/tests/coretests/assets/fonts/ascent3em-descent4em.ttx new file mode 100644 index 000000000000..432331b2bc46 --- /dev/null +++ b/core/tests/coretests/assets/fonts/ascent3em-descent4em.ttx @@ -0,0 +1,180 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0"> + + <GlyphOrder> + <GlyphID id="0" name=".notdef"/> + <GlyphID id="1" name="1em"/> + </GlyphOrder> + + <head> + <tableVersion value="1.0"/> + <fontRevision value="1.0"/> + <checkSumAdjustment value="0x640cdb2f"/> + <magicNumber value="0x5f0f3cf5"/> + <flags value="00000000 00000011"/> + <unitsPerEm value="1000"/> + <created value="Fri Mar 17 07:26:00 2017"/> + <macStyle value="00000000 00000000"/> + <lowestRecPPEM value="7"/> + <fontDirectionHint value="2"/> + <glyphDataFormat value="0"/> + </head> + + <hhea> + <tableVersion value="0x10000"/> + <ascent value="3000"/> + <descent value="-4000"/> + <lineGap value="0"/> + <caretSlopeRise value="1"/> + <caretSlopeRun value="0"/> + <caretOffset value="0"/> + <reserved0 value="0"/> + <reserved1 value="0"/> + <reserved2 value="0"/> + <reserved3 value="0"/> + <metricDataFormat value="0"/> + </hhea> + + <maxp> + <tableVersion value="0x10000"/> + <maxZones value="0"/> + <maxTwilightPoints value="0"/> + <maxStorage value="0"/> + <maxFunctionDefs value="0"/> + <maxInstructionDefs value="0"/> + <maxStackElements value="0"/> + <maxSizeOfInstructions value="0"/> + <maxComponentElements value="0"/> + </maxp> + + <OS_2> + <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex' + will be recalculated by the compiler --> + <version value="3"/> + <xAvgCharWidth value="594"/> + <usWeightClass value="400"/> + <usWidthClass value="5"/> + <fsType value="00000000 00001000"/> + <ySubscriptXSize value="650"/> + <ySubscriptYSize value="600"/> + <ySubscriptXOffset value="0"/> + <ySubscriptYOffset value="75"/> + <ySuperscriptXSize value="650"/> + <ySuperscriptYSize value="600"/> + <ySuperscriptXOffset value="0"/> + <ySuperscriptYOffset value="350"/> + <yStrikeoutSize value="50"/> + <yStrikeoutPosition value="300"/> + <sFamilyClass value="0"/> + <panose> + <bFamilyType value="0"/> + <bSerifStyle value="0"/> + <bWeight value="5"/> + <bProportion value="0"/> + <bContrast value="0"/> + <bStrokeVariation value="0"/> + <bArmStyle value="0"/> + <bLetterForm value="0"/> + <bMidline value="0"/> + <bXHeight value="0"/> + </panose> + <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/> + <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/> + <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/> + <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/> + <achVendID value="UKWN"/> + <fsSelection value="00000000 01000000"/> + <usFirstCharIndex value="32"/> + <usLastCharIndex value="122"/> + <sTypoAscender value="800"/> + <sTypoDescender value="-200"/> + <sTypoLineGap value="200"/> + <usWinAscent value="1000"/> + <usWinDescent value="200"/> + <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/> + <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/> + <sxHeight value="500"/> + <sCapHeight value="700"/> + <usDefaultChar value="0"/> + <usBreakChar value="32"/> + <usMaxContext value="0"/> + </OS_2> + + <hmtx> + <mtx name=".notdef" width="1000" lsb="0"/> + <mtx name="1em" width="1000" lsb="0"/> + </hmtx> + + <cmap> + <tableVersion version="0"/> + <cmap_format_4 platformID="3" platEncID="10" language="0"> + <map code="0x0062" name="1em" /> <!-- LATIN SMALL LETTER B --> + </cmap_format_4> + </cmap> + + <loca> + <!-- The 'loca' table will be calculated by the compiler --> + </loca> + + <glyf> + <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" /> + <TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" /> + </glyf> + + <name> + <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409"> + Copyright (C) 2017 The Android Open Source Project + </namerecord> + <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409"> + Sample Font + </namerecord> + <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409"> + Regular + </namerecord> + <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409"> + Sample Font + </namerecord> + <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409"> + SampleFont-Regular + </namerecord> + <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409"> + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + 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. + </namerecord> + <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409"> + http://www.apache.org/licenses/LICENSE-2.0 + </namerecord> + </name> + + <post> + <formatType value="3.0"/> + <italicAngle value="0.0"/> + <underlinePosition value="-75"/> + <underlineThickness value="50"/> + <isFixedPitch value="0"/> + <minMemType42 value="0"/> + <maxMemType42 value="0"/> + <minMemType1 value="0"/> + <maxMemType1 value="0"/> + </post> + +</ttFont> diff --git a/core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java b/core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java index 5dd3c2ce6b5d..a9d19b4b295c 100644 --- a/core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java +++ b/core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java @@ -2,9 +2,11 @@ package android.content.pm; import android.os.Parcel; import android.os.Parcelable; + import junit.framework.TestCase; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class ParceledListSliceTest extends TestCase { @@ -91,15 +93,10 @@ public class ParceledListSliceTest extends TestCase { } } - public void testStringList() throws Exception { - final int objectCount = 400; - List<String> list = new ArrayList<String>(); - for (long i = 0; i < objectCount; i++) { - list.add(Long.toString(i * (6 - i))); - } - + private void sendParcelStringList(List<String> list) { StringParceledListSlice slice; Parcel parcel = Parcel.obtain(); + try { parcel.writeParcelable(new StringParceledListSlice(list), 0); parcel.setDataPosition(0); @@ -113,6 +110,26 @@ public class ParceledListSliceTest extends TestCase { assertEquals(list, slice.getList()); } + public void testStringList() throws Exception { + final int objectCount = 400; + List<String> list = new ArrayList<String>(); + for (long i = 0; i < objectCount; i++) { + list.add(Long.toString(i * (6 - i))); + } + + sendParcelStringList(list); + } + + public void testLargeStringList() throws Exception { + final int thresholdBytes = 256 * 1024; + final String value = Long.toString(Long.MAX_VALUE); + final int objectCount = 2 * thresholdBytes / value.length(); + final List<String> list = Collections.nCopies(objectCount, value); + + sendParcelStringList(list); + } + + /** * Test that only homogeneous elements may be unparceled. */ diff --git a/core/tests/coretests/src/android/database/DatabaseGeneralTest.java b/core/tests/coretests/src/android/database/DatabaseGeneralTest.java index 335cea772a74..50e29c2863c2 100644 --- a/core/tests/coretests/src/android/database/DatabaseGeneralTest.java +++ b/core/tests/coretests/src/android/database/DatabaseGeneralTest.java @@ -1221,4 +1221,19 @@ public class DatabaseGeneralTest extends AndroidTestCase implements PerformanceT InstrumentationRegistry.getInstrumentation()).executeShellCommand(cmd); } + @SmallTest + public void testSavepointRollbacks() { + try (SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(":memory:", null)) { + db.execSQL("drop table if exists data"); + db.execSQL("create table if not exists data (id INTEGER PRIMARY KEY, val TEXT)"); + db.execSQL("begin deferred transaction"); + db.execSQL("insert into data (val) values('row 1')"); + db.execSQL("savepoint foo"); + db.execSQL("insert into data (val) values('row 2')"); + db.execSQL("rollback to foo"); + db.execSQL("commit transaction"); + long rowCount = DatabaseUtils.longForQuery(db, "select count(*) from data", null); + assertEquals(1, rowCount); + } + } } diff --git a/core/tests/coretests/src/android/graphics/TypefaceTest.java b/core/tests/coretests/src/android/graphics/TypefaceTest.java index c8ce884cf826..b0c7976f8014 100644 --- a/core/tests/coretests/src/android/graphics/TypefaceTest.java +++ b/core/tests/coretests/src/android/graphics/TypefaceTest.java @@ -16,15 +16,29 @@ package android.graphics; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import android.content.Context; +import android.content.res.AssetManager; +import android.content.res.Resources; import android.graphics.Paint; import android.graphics.Typeface; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; +import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.SmallTest; -import junit.framework.TestCase; +import com.android.frameworks.coretests.R; + +import org.junit.Test; +import org.junit.runner.RunWith; +import java.util.Random; -public class TypefaceTest extends TestCase { +@RunWith(AndroidJUnit4.class) +public class TypefaceTest { // create array of all std faces private final Typeface[] mFaces = new Typeface[] { @@ -36,8 +50,9 @@ public class TypefaceTest extends TestCase { Typeface.create(Typeface.SERIF, 3), Typeface.create(Typeface.MONOSPACE, 0) }; - + @SmallTest + @Test public void testBasic() throws Exception { assertTrue("basic", Typeface.DEFAULT != null); assertTrue("basic", Typeface.DEFAULT_BOLD != null); @@ -45,8 +60,9 @@ public class TypefaceTest extends TestCase { assertTrue("basic", Typeface.SERIF != null); assertTrue("basic", Typeface.MONOSPACE != null); } - + @SmallTest + @Test public void testUnique() throws Exception { final int n = mFaces.length; for (int i = 0; i < n; i++) { @@ -57,6 +73,7 @@ public class TypefaceTest extends TestCase { } @SmallTest + @Test public void testStyles() throws Exception { assertTrue("style", mFaces[0].getStyle() == Typeface.NORMAL); assertTrue("style", mFaces[1].getStyle() == Typeface.BOLD); @@ -68,6 +85,7 @@ public class TypefaceTest extends TestCase { } @MediumTest + @Test public void testUniformY() throws Exception { Paint p = new Paint(); final int n = mFaces.length; @@ -89,4 +107,69 @@ public class TypefaceTest extends TestCase { } } + @LargeTest + @Test + public void testMultithreadCacheStressTest() { + final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + final Resources res = context.getResources(); + final AssetManager assets = res.getAssets(); + final Typeface[] baseTypefaces = { + null, + Typeface.SANS_SERIF, + Typeface.SERIF, + Typeface.MONOSPACE, + res.getFont(R.font.samplefont), + res.getFont(R.font.samplefont2), + res.getFont(R.font.samplefont3), + res.getFont(R.font.samplefont4), + res.getFont(R.font.samplexmlfont), + Typeface.createFromAsset(assets, "fonts/a3em.ttf"), + Typeface.createFromAsset(assets, "fonts/b3em.ttf"), + Typeface.createFromAsset(assets, "fonts/c3em.ttf"), + Typeface.createFromAsset(assets, "fonts/all2em.ttf"), + Typeface.createFromAsset(assets, "fonts/hasGlyphTestFont.ttf"), + Typeface.createFromAsset(assets, "fonts/samplefont1.ttf"), + Typeface.createFromAsset(assets, "fonts/no_coverage.ttf"), + }; + + final int loopCount = 10000; + + final Runnable threadedCreater = () -> { + final Random random = new Random(); + for (int i = 0; i < loopCount; ++i) { + final Typeface base = baseTypefaces[random.nextInt(baseTypefaces.length)]; + if (random.nextBoolean()) { + final int style = random.nextInt(3); + final Typeface result = Typeface.create(base, style); + assertEquals(style, result.getStyle()); + } else { + final int weight = 100 * (random.nextInt(10) + 1); // [100, 1000] + final boolean italic = random.nextBoolean(); + final Typeface result = Typeface.create(base, weight, italic); + assertEquals(italic, result.isItalic()); + assertEquals(weight, result.getWeight()); + } + } + }; + + final int threadCount = 4; + final Thread[] threads = new Thread[threadCount]; + for (int i = 0; i < threadCount; ++i) { + threads[i] = new Thread(threadedCreater); + } + + for (int i = 0; i < threadCount; ++i) { + threads[i].start(); + } + + for (int i = 0; i < threadCount; ++i) { + try { + threads[i].join(); + } catch (InterruptedException e) { + // ignore + } + } + + } + } diff --git a/core/tests/coretests/src/android/net/ScoredNetworkTest.java b/core/tests/coretests/src/android/net/ScoredNetworkTest.java index dc17da25df54..109f32e1a48e 100644 --- a/core/tests/coretests/src/android/net/ScoredNetworkTest.java +++ b/core/tests/coretests/src/android/net/ScoredNetworkTest.java @@ -49,6 +49,55 @@ public class ScoredNetworkTest { = new NetworkKey(new WifiKey("\"ssid\"", "00:00:00:00:00:00")); @Test + public void scoredNetworksWithBothNullAttributeBundle_equal() { + ScoredNetwork scoredNetwork1 = + new ScoredNetwork(KEY, CURVE, false /* meteredHint */, null /* attributes */); + ScoredNetwork scoredNetwork2 = + new ScoredNetwork(KEY, CURVE, false /* meteredHint */, null /* attributes */); + assertTrue(scoredNetwork1.equals(scoredNetwork2)); + } + + @Test + public void scoredNetworksWithOneNullAttributeBundle_notEqual() { + ScoredNetwork scoredNetwork1 = + new ScoredNetwork(KEY, CURVE, false /* meteredHint */, ATTRIBUTES); + ScoredNetwork scoredNetwork2 = + new ScoredNetwork(KEY, CURVE, false /* meteredHint */, null /* attributes */); + assertFalse(scoredNetwork1.equals(scoredNetwork2)); + } + + @Test + public void scoredNetworksWithDifferentSizedAttributeBundle_notEqual() { + ScoredNetwork scoredNetwork1 = + new ScoredNetwork(KEY, CURVE, false /* meteredHint */, ATTRIBUTES); + Bundle attr = new Bundle(ATTRIBUTES); + attr.putBoolean(ScoredNetwork.ATTRIBUTES_KEY_HAS_CAPTIVE_PORTAL, true); + ScoredNetwork scoredNetwork2 = + new ScoredNetwork(KEY, CURVE, false /* meteredHint */, attr); + assertFalse(scoredNetwork1.equals(scoredNetwork2)); + } + + @Test + public void scoredNetworksWithDifferentAttributeValues_notEqual() { + ScoredNetwork scoredNetwork1 = + new ScoredNetwork(KEY, CURVE, false /* meteredHint */, ATTRIBUTES); + Bundle attr = new Bundle(); + attr.putInt(ScoredNetwork.ATTRIBUTES_KEY_RANKING_SCORE_OFFSET, Integer.MIN_VALUE); + ScoredNetwork scoredNetwork2 = + new ScoredNetwork(KEY, CURVE, false /* meteredHint */, attr); + assertFalse(scoredNetwork1.equals(scoredNetwork2)); + } + + @Test + public void scoredNetworksWithSameAttributeValuesAndSize_equal() { + ScoredNetwork scoredNetwork1 = + new ScoredNetwork(KEY, CURVE, false /* meteredHint */, ATTRIBUTES); + ScoredNetwork scoredNetwork2 = + new ScoredNetwork(KEY, CURVE, false /* meteredHint */, ATTRIBUTES); + assertTrue(scoredNetwork1.equals(scoredNetwork2)); + } + + @Test public void calculateRankingOffsetShouldThrowUnsupportedOperationException() { // No curve or ranking score offset set in curve ScoredNetwork scoredNetwork = new ScoredNetwork(KEY, null); diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 6848fce764bc..8a57ea9a9c13 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -99,6 +99,7 @@ public class SettingsBackupTest { Settings.Global.ALARM_MANAGER_CONSTANTS, Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED, Settings.Global.ALWAYS_FINISH_ACTIVITIES, + Settings.Global.ALWAYS_ON_DISPLAY_CONSTANTS, Settings.Global.ANIMATOR_DURATION_SCALE, Settings.Global.ANOMALY_DETECTION_CONSTANTS, Settings.Global.APN_DB_UPDATE_CONTENT_URL, @@ -253,6 +254,7 @@ public class SettingsBackupTest { Settings.Global.NETSTATS_GLOBAL_ALERT_BYTES, Settings.Global.NETSTATS_POLL_INTERVAL, Settings.Global.NETSTATS_SAMPLE_ENABLED, + Settings.Global.NETSTATS_AUGMENT_ENABLED, Settings.Global.NETSTATS_TIME_CACHE_MAX_AGE, Settings.Global.NETSTATS_UID_BUCKET_DURATION, Settings.Global.NETSTATS_UID_DELETE_AGE, diff --git a/core/tests/coretests/src/android/text/DynamicLayoutTest.java b/core/tests/coretests/src/android/text/DynamicLayoutTest.java index 5ef08e02029e..ed6bfbfa3491 100644 --- a/core/tests/coretests/src/android/text/DynamicLayoutTest.java +++ b/core/tests/coretests/src/android/text/DynamicLayoutTest.java @@ -186,4 +186,77 @@ public class DynamicLayoutTest { ALIGN_NORMAL, 1.0f /*spacingMultiplier*/, 0f /*spacingAdd*/, false /*includepad*/); layout.getLineExtra(100); } + + @Test + public void testFallbackLineSpacing() { + // All glyphs in the fonts are 1em wide. + final String[] testFontFiles = { + // ascent == 1em, descent == 2em, only supports 'a' and space + "ascent1em-descent2em.ttf", + // ascent == 3em, descent == 4em, only supports 'b' + "ascent3em-descent4em.ttf" + }; + final String xml = "<?xml version='1.0' encoding='UTF-8'?>" + + "<familyset>" + + " <family name='sans-serif'>" + + " <font weight='400' style='normal'>ascent1em-descent2em.ttf</font>" + + " </family>" + + " <family>" + + " <font weight='400' style='normal'>ascent3em-descent4em.ttf</font>" + + " </family>" + + "</familyset>"; + + try (FontFallbackSetup setup = + new FontFallbackSetup("DynamicLayout", testFontFiles, xml)) { + final TextPaint paint = setup.getPaintFor("sans-serif"); + final int textSize = 100; + paint.setTextSize(textSize); + assertEquals(-textSize, paint.ascent(), 0.0f); + assertEquals(2 * textSize, paint.descent(), 0.0f); + + final int paraWidth = 5 * textSize; + final String text = "aaaaa aabaa aaaaa"; // This should result in three lines. + + // Old line spacing. All lines should get their ascent and descents from the first font. + DynamicLayout layout = DynamicLayout.Builder + .obtain(text, paint, paraWidth) + .setIncludePad(false) + .setUseLineSpacingFromFallbacks(false) + .build(); + assertEquals(3, layout.getLineCount()); + assertEquals(-textSize, layout.getLineAscent(0)); + assertEquals(2 * textSize, layout.getLineDescent(0)); + assertEquals(-textSize, layout.getLineAscent(1)); + assertEquals(2 * textSize, layout.getLineDescent(1)); + assertEquals(-textSize, layout.getLineAscent(2)); + assertEquals(2 * textSize, layout.getLineDescent(2)); + + // New line spacing. The second line has a 'b', so it needs more ascent and descent. + layout = DynamicLayout.Builder + .obtain(text, paint, paraWidth) + .setIncludePad(false) + .setUseLineSpacingFromFallbacks(true) + .build(); + assertEquals(3, layout.getLineCount()); + assertEquals(-textSize, layout.getLineAscent(0)); + assertEquals(2 * textSize, layout.getLineDescent(0)); + assertEquals(-3 * textSize, layout.getLineAscent(1)); + assertEquals(4 * textSize, layout.getLineDescent(1)); + assertEquals(-textSize, layout.getLineAscent(2)); + assertEquals(2 * textSize, layout.getLineDescent(2)); + + // The default is the old line spacing, for backward compatibility. + layout = DynamicLayout.Builder + .obtain(text, paint, paraWidth) + .setIncludePad(false) + .build(); + assertEquals(3, layout.getLineCount()); + assertEquals(-textSize, layout.getLineAscent(0)); + assertEquals(2 * textSize, layout.getLineDescent(0)); + assertEquals(-textSize, layout.getLineAscent(1)); + assertEquals(2 * textSize, layout.getLineDescent(1)); + assertEquals(-textSize, layout.getLineAscent(2)); + assertEquals(2 * textSize, layout.getLineDescent(2)); + } + } } diff --git a/core/tests/coretests/src/android/text/FontFallbackSetup.java b/core/tests/coretests/src/android/text/FontFallbackSetup.java new file mode 100644 index 000000000000..ced74eebe47b --- /dev/null +++ b/core/tests/coretests/src/android/text/FontFallbackSetup.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.text; + +import android.annotation.NonNull; +import android.content.Context; +import android.content.res.AssetManager; +import android.graphics.FontFamily; +import android.graphics.Typeface; +import android.support.test.InstrumentationRegistry; +import android.util.ArrayMap; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; + +public class FontFallbackSetup implements AutoCloseable { + private final String[] mTestFontFiles; + private final String mXml; + private final String mTestFontsDir; + final ArrayMap<String, Typeface> mFontMap = new ArrayMap<>(); + + public FontFallbackSetup(@NonNull String testSubDir, @NonNull String[] testFontFiles, + @NonNull String xml) { + mTestFontFiles = testFontFiles; + mXml = xml; + + final Context targetCtx = InstrumentationRegistry.getInstrumentation().getTargetContext(); + final File cacheDir = new File(targetCtx.getCacheDir(), testSubDir); + if (!cacheDir.isDirectory()) { + final boolean dirsCreated = cacheDir.mkdirs(); + if (!dirsCreated) { + throw new RuntimeException("Creating test directories for fonts failed."); + } + } + mTestFontsDir = cacheDir.getAbsolutePath() + "/"; + + final String testFontsXml = new File(mTestFontsDir, "fonts.xml").getAbsolutePath(); + final AssetManager am = + InstrumentationRegistry.getInstrumentation().getContext().getAssets(); + for (String fontFile : mTestFontFiles) { + final String sourceInAsset = "fonts/" + fontFile; + final File outInCache = new File(mTestFontsDir, fontFile); + try (InputStream is = am.open(sourceInAsset)) { + Files.copy(is, outInCache.toPath(), StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + try (FileOutputStream fos = new FileOutputStream(testFontsXml)) { + fos.write(mXml.getBytes(Charset.forName("UTF-8"))); + } catch (IOException e) { + throw new RuntimeException(e); + } + + final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>(); + Typeface.buildSystemFallback(testFontsXml, mTestFontsDir, mFontMap, fallbackMap); + } + + @NonNull + public Typeface getTypefaceFor(@NonNull String fontName) { + return mFontMap.get(fontName); + } + + @NonNull + public TextPaint getPaintFor(@NonNull String fontName) { + final TextPaint paint = new TextPaint(); + paint.setTypeface(getTypefaceFor(fontName)); + return paint; + } + + @Override + public void close() { + for (String fontFile : mTestFontFiles) { + final File outInCache = new File(mTestFontsDir, fontFile); + outInCache.delete(); + } + } +} diff --git a/core/tests/coretests/src/android/text/LayoutTest.java b/core/tests/coretests/src/android/text/LayoutTest.java index 6b262ebf2c41..0cc41ba0a36b 100644 --- a/core/tests/coretests/src/android/text/LayoutTest.java +++ b/core/tests/coretests/src/android/text/LayoutTest.java @@ -40,6 +40,7 @@ import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.List; +import java.util.Locale; @SmallTest @RunWith(AndroidJUnit4.class) @@ -288,6 +289,172 @@ public class LayoutTest { } @Test + public void testGetSelectionWithEmptySelection() { + final Layout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth, + mAlign, mSpacingMult, mSpacingAdd); + + /* + * When the selection is empty (i.e. the start and the end index are the same), we do not + * expect any rectangles to be generated. + */ + + layout.getSelection(5 /* startIndex */, 5 /* endIndex */, + (left, top, right, bottom) -> fail(String.format(Locale.getDefault(), + "Did not expect any rectangles, got a rectangle with (left: %f," + + " top: %f), (right: %f, bottom: %f)", + left, top, right, bottom))); + } + + @Test + public void testGetSelectionWithASingleLineSelection() { + final Layout layout = new StaticLayout("abc", mTextPaint, Integer.MAX_VALUE, + Alignment.ALIGN_LEFT, mSpacingMult, mSpacingAdd, false); + + final List<RectF> rectangles = new ArrayList<>(); + + layout.getSelection(0 /* startIndex */, 1 /* endIndex */, + (left, top, right, bottom) -> rectangles.add(new RectF(left, top, right, bottom))); + + /* + * The selection we expect will only cover the letter "a". Hence, we expect one rectangle + * to be generated and this rectangle should start at the top left of the canvas and should + * end somewhere to the right and down. + * + * | a | b c + * + */ + + assertEquals(1, rectangles.size()); + + final RectF rectangle = rectangles.get(0); + + assertEquals(0, rectangle.left, 0.0f); + assertEquals(0, rectangle.top, 0.0f); + assertTrue(rectangle.right > 0); + assertTrue(rectangle.bottom > 0); + } + + @Test + public void + testGetSelectionWithMultilineSelection_secondLineSelectionEndsBeforeFirstCharacter() { + final Layout layout = new StaticLayout("a\nb\nc", mTextPaint, Integer.MAX_VALUE, + Alignment.ALIGN_LEFT, mSpacingMult, mSpacingAdd, false); + + final List<RectF> rectangles = new ArrayList<>(); + + layout.getSelection(0 /* startIndex */, 2 /* endIndex */, + (left, top, right, bottom) -> rectangles.add(new RectF(left, top, right, bottom))); + + /* + * The selection that will be selected is "a\n" - the selection starts at the beginning + * of the first line and ends at the start of the second line. This means the selection + * highlight will span from the beginning of the first line to the end of the first line + * and will appear as a zero width line at the beginning of the second line. + * + * Hence, we expect three rectangles - one that will select the "a" on the first line, + * one that will extend the selection from the "a" to the end of the first line and one + * that will prepare the selection for the second line. + * + * | a | *topToEndOfLineRectangle* | + * | b + * c + */ + + assertEquals(3, rectangles.size()); + + final RectF topRectangle = rectangles.get(0); + final RectF topToEndOfLineRectangle = rectangles.get(1); + final RectF bottomLineStartRectangle = rectangles.get(2); + + assertFalse(topRectangle.intersect(bottomLineStartRectangle)); + assertTrue(topRectangle.top < bottomLineStartRectangle.top); + assertTrue(topRectangle.left == bottomLineStartRectangle.left); + + assertFalse(topRectangle.intersect(topToEndOfLineRectangle)); + assertEquals(Integer.MAX_VALUE, topToEndOfLineRectangle.right, 1); + assertTrue(topRectangle.top == topToEndOfLineRectangle.top); + assertTrue(topRectangle.right == topToEndOfLineRectangle.left); + assertTrue(topRectangle.bottom == topToEndOfLineRectangle.bottom); + + assertEquals(0, bottomLineStartRectangle.left, 0.0f); + assertEquals(0, bottomLineStartRectangle.right, 0.0f); + } + + @Test + public void testGetSelectionWithMultilineSelection_secondLineSelectionEndsAfterACharacter() { + final Layout layout = new StaticLayout("a\nb\nc", mTextPaint, Integer.MAX_VALUE, + Alignment.ALIGN_LEFT, mSpacingMult, mSpacingAdd, false); + + final List<RectF> rectangles = new ArrayList<>(); + + layout.getSelection(0 /* startIndex */, 3 /* endIndex */, + (left, top, right, bottom) -> rectangles.add(new RectF(left, top, right, bottom))); + + /* + * The selection that will be selected is "a\nb" - the selection starts at the beginning + * of the first line and ends at the end of the letter "b". This means the selection + * highlight will span from the beginning of the first line to the end of the first line + * and will also cover the letter "b" on the second line. + * + * We expect four rectangles - one that will select the "a" on the first line, + * one that will extend the selection from the "a" to the end of the first line the one + * from the previous case that will prepare the selection for the second line and finally + * one that will select the letter b. + * + * | a | *topToEndOfLineRectangle* | + * || b | + * c + */ + + assertEquals(4, rectangles.size()); + + final RectF topRectangle = rectangles.get(0); + final RectF topToEndOfLineRectangle = rectangles.get(1); + final RectF bottomRectangle = rectangles.get(2); + final RectF bottomLineStartRectangle = rectangles.get(3); + + assertTrue(topRectangle.top == topToEndOfLineRectangle.top); + assertTrue(bottomLineStartRectangle.top == bottomRectangle.top); + assertTrue(bottomLineStartRectangle.bottom == bottomRectangle.bottom); + assertEquals(0, bottomLineStartRectangle.left, 0.0f); + assertEquals(0, bottomLineStartRectangle.right, 0.0f); + assertEquals(0, bottomRectangle.left, 0.0f); + assertTrue(bottomRectangle.right > 0); + } + + @Test + public void testGetSelectionPathWithASingleLineSelection() { + final Layout layout = new StaticLayout("abc", mTextPaint, Integer.MAX_VALUE, + Alignment.ALIGN_LEFT, mSpacingMult, mSpacingAdd, false); + + final List<RectF> rectangles = new ArrayList<>(); + + layout.getSelection(0 /* startIndex */, 1 /* endIndex */, + (left, top, right, bottom) -> rectangles.add(new RectF(left, top, right, bottom))); + + /* + * In the single line selection case, we expect that only one rectangle covering the letter + * "a" will be generated. Hence, we expect that the generated path will only consist of + * that rectangle as well. + * + * | a | b c + * + */ + + assertEquals(1, rectangles.size()); + + final RectF rectangle = rectangles.get(0); + + final Path generatedPath = new Path(); + layout.getSelectionPath(0 /* startIndex */, 1 /* endIndex */, generatedPath); + + final RectF pathRectangle = new RectF(); + + assertTrue(generatedPath.isRect(pathRectangle)); + assertEquals(rectangle, pathRectangle); + } + + @Test public void testIsSpanned() { MockLayout layout = new MockLayout(LAYOUT_TEXT, mTextPaint, mWidth, mAlign, mSpacingMult, mSpacingAdd); diff --git a/core/tests/coretests/src/android/text/StaticLayoutTest.java b/core/tests/coretests/src/android/text/StaticLayoutTest.java index 2dfab87906c1..defb44ad64d0 100644 --- a/core/tests/coretests/src/android/text/StaticLayoutTest.java +++ b/core/tests/coretests/src/android/text/StaticLayoutTest.java @@ -799,4 +799,88 @@ public class StaticLayoutTest { layout.drawText(canvas, 0, 0); assertEquals(31, paint.getHyphenEdit()); } + + @Test + public void testFallbackLineSpacing() { + // All glyphs in the fonts are 1em wide. + final String[] testFontFiles = { + // ascent == 1em, descent == 2em, only supports 'a' and space + "ascent1em-descent2em.ttf", + // ascent == 3em, descent == 4em, only supports 'b' + "ascent3em-descent4em.ttf" + }; + final String xml = "<?xml version='1.0' encoding='UTF-8'?>" + + "<familyset>" + + " <family name='sans-serif'>" + + " <font weight='400' style='normal'>ascent1em-descent2em.ttf</font>" + + " </family>" + + " <family>" + + " <font weight='400' style='normal'>ascent3em-descent4em.ttf</font>" + + " </family>" + + "</familyset>"; + + try (FontFallbackSetup setup = + new FontFallbackSetup("StaticLayout", testFontFiles, xml)) { + final TextPaint paint = setup.getPaintFor("sans-serif"); + final int textSize = 100; + paint.setTextSize(textSize); + assertEquals(-textSize, paint.ascent(), 0.0f); + assertEquals(2 * textSize, paint.descent(), 0.0f); + + final int paraWidth = 5 * textSize; + final String text = "aaaaa aabaa aaaaa"; // This should result in three lines. + + // Old line spacing. All lines should get their ascent and descents from the first font. + StaticLayout layout = StaticLayout.Builder + .obtain(text, 0, text.length(), paint, paraWidth) + .setIncludePad(false) + .setUseLineSpacingFromFallbacks(false) + .build(); + assertEquals(3, layout.getLineCount()); + assertEquals(-textSize, layout.getLineAscent(0)); + assertEquals(2 * textSize, layout.getLineDescent(0)); + assertEquals(-textSize, layout.getLineAscent(1)); + assertEquals(2 * textSize, layout.getLineDescent(1)); + assertEquals(-textSize, layout.getLineAscent(2)); + assertEquals(2 * textSize, layout.getLineDescent(2)); + + // New line spacing. The second line has a 'b', so it needs more ascent and descent. + layout = StaticLayout.Builder + .obtain(text, 0, text.length(), paint, paraWidth) + .setIncludePad(false) + .setUseLineSpacingFromFallbacks(true) + .build(); + assertEquals(3, layout.getLineCount()); + assertEquals(-textSize, layout.getLineAscent(0)); + assertEquals(2 * textSize, layout.getLineDescent(0)); + assertEquals(-3 * textSize, layout.getLineAscent(1)); + assertEquals(4 * textSize, layout.getLineDescent(1)); + assertEquals(-textSize, layout.getLineAscent(2)); + assertEquals(2 * textSize, layout.getLineDescent(2)); + + // The default is the old line spacing, for backward compatibility. + layout = StaticLayout.Builder + .obtain(text, 0, text.length(), paint, paraWidth) + .setIncludePad(false) + .build(); + assertEquals(3, layout.getLineCount()); + assertEquals(-textSize, layout.getLineAscent(0)); + assertEquals(2 * textSize, layout.getLineDescent(0)); + assertEquals(-textSize, layout.getLineAscent(1)); + assertEquals(2 * textSize, layout.getLineDescent(1)); + assertEquals(-textSize, layout.getLineAscent(2)); + assertEquals(2 * textSize, layout.getLineDescent(2)); + } + } + + @Test + public void testGetHeight_zeroMaxLines() { + final String text = "a\nb"; + final TextPaint paint = new TextPaint(); + final StaticLayout layout = StaticLayout.Builder.obtain(text, 0, text.length(), paint, + Integer.MAX_VALUE).setMaxLines(0).build(); + + assertEquals(0, layout.getHeight(true)); + assertEquals(2, layout.getLineCount()); + } } diff --git a/core/tests/coretests/src/android/text/format/DateUtilsTest.java b/core/tests/coretests/src/android/text/format/DateUtilsTest.java index 0920d1e7c710..f21c9297dde9 100644 --- a/core/tests/coretests/src/android/text/format/DateUtilsTest.java +++ b/core/tests/coretests/src/android/text/format/DateUtilsTest.java @@ -136,11 +136,12 @@ public class DateUtilsTest { fixedTime, java.text.DateFormat.SHORT, java.text.DateFormat.FULL)); final long hourDuration = 2 * 60 * 60 * 1000; - assertEquals("5:30:15 AM GMT+00:00", DateUtils.formatSameDayTime(fixedTime + hourDuration, - fixedTime, java.text.DateFormat.FULL, java.text.DateFormat.FULL)); + assertEquals("5:30:15 AM Greenwich Mean Time", DateUtils.formatSameDayTime( + fixedTime + hourDuration, fixedTime, java.text.DateFormat.FULL, + java.text.DateFormat.FULL)); assertEquals("5:30:15 AM", DateUtils.formatSameDayTime(fixedTime + hourDuration, fixedTime, java.text.DateFormat.FULL, java.text.DateFormat.DEFAULT)); - assertEquals("5:30:15 AM GMT+00:00", DateUtils.formatSameDayTime(fixedTime + hourDuration, + assertEquals("5:30:15 AM GMT", DateUtils.formatSameDayTime(fixedTime + hourDuration, fixedTime, java.text.DateFormat.FULL, java.text.DateFormat.LONG)); assertEquals("5:30:15 AM", DateUtils.formatSameDayTime(fixedTime + hourDuration, fixedTime, java.text.DateFormat.FULL, java.text.DateFormat.MEDIUM)); diff --git a/core/tests/coretests/src/android/transition/FadeTransitionTest.java b/core/tests/coretests/src/android/transition/FadeTransitionTest.java index 674b36355ab0..22365bac64a2 100644 --- a/core/tests/coretests/src/android/transition/FadeTransitionTest.java +++ b/core/tests/coretests/src/android/transition/FadeTransitionTest.java @@ -16,22 +16,24 @@ package android.transition; +import android.animation.Animator; import android.animation.AnimatorSetActivity; import android.app.Activity; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; import android.test.ActivityInstrumentationTestCase2; import android.test.suitebuilder.annotation.SmallTest; import android.transition.Transition.TransitionListener; -import android.transition.TransitionListenerAdapter; import android.view.View; import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.ImageView; import com.android.frameworks.coretests.R; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import static android.support.test.espresso.Espresso.onView; - public class FadeTransitionTest extends ActivityInstrumentationTestCase2<AnimatorSetActivity> { Activity mActivity; public FadeTransitionTest() { @@ -129,6 +131,43 @@ public class FadeTransitionTest extends ActivityInstrumentationTestCase2<Animato assertEquals(View.INVISIBLE, square1.getVisibility()); } + @SmallTest + public void testSnapshotView() throws Throwable { + final View square1 = mActivity.findViewById(R.id.square1); + + final CountDownLatch disappearCalled = new CountDownLatch(1); + final Fade fadeOut = new Fade(Fade.MODE_OUT) { + @Override + public Animator onDisappear(ViewGroup sceneRoot, View view, + TransitionValues startValues, + TransitionValues endValues) { + assertNotSame(square1, view); + assertTrue(view instanceof ImageView); + ImageView imageView = (ImageView) view; + BitmapDrawable background = (BitmapDrawable) imageView.getDrawable(); + Bitmap bitmap = background.getBitmap(); + assertEquals(Bitmap.Config.HARDWARE, bitmap.getConfig()); + Bitmap copy = bitmap.copy(Bitmap.Config.ARGB_8888, false); + assertEquals(0xFFFF0000, copy.getPixel(1, 1)); + disappearCalled.countDown(); + return super.onDisappear(sceneRoot, view, startValues, endValues); + } + }; + + runTestOnUiThread(new Runnable() { + @Override + public void run() { + ViewGroup container = mActivity.findViewById(R.id.container); + TransitionManager.beginDelayedTransition(container, fadeOut); + container.removeView(square1); + FrameLayout parent = new FrameLayout(mActivity); + parent.addView(square1); + } + }); + + assertTrue(disappearCalled.await(1, TimeUnit.SECONDS)); + } + public TransitionLatch setVisibilityInTransition(final Transition transition, int viewId, final int visibility) throws Throwable { final ViewGroup sceneRoot = (ViewGroup) mActivity.findViewById(R.id.container); diff --git a/core/tests/coretests/src/android/transition/TransitionTest.java b/core/tests/coretests/src/android/transition/TransitionTest.java index 7e72e25b6f45..ab4320c65eb2 100644 --- a/core/tests/coretests/src/android/transition/TransitionTest.java +++ b/core/tests/coretests/src/android/transition/TransitionTest.java @@ -28,6 +28,8 @@ import android.widget.TextView; import com.android.frameworks.coretests.R; +import java.lang.reflect.Field; + public class TransitionTest extends ActivityInstrumentationTestCase2<AnimatorSetActivity> { Activity mActivity; public TransitionTest() { @@ -77,27 +79,47 @@ public class TransitionTest extends ActivityInstrumentationTestCase2<AnimatorSet fade.setEpicenterCallback(epicenterCallback); Fade clone = (Fade) fade.clone(); - assertEquals(fade.mStartDelay, clone.mStartDelay); - assertEquals(fade.mDuration, clone.mDuration); - assertEquals(fade.mInterpolator, clone.mInterpolator); - assertEquals(fade.mPropagation, clone.mPropagation); + assertFieldEquals(fade, clone, "mStartDelay"); + assertFieldEquals(fade, clone, "mDuration"); + assertFieldEquals(fade, clone, "mInterpolator"); + assertFieldEquals(fade, clone, "mPropagation"); assertEquals(fade.getPathMotion(), clone.getPathMotion()); assertEquals(fade.getEpicenterCallback(), clone.getEpicenterCallback()); - assertEquals(fade.mNameOverrides, clone.mNameOverrides); - assertEquals(fade.mMatchOrder, clone.mMatchOrder); + assertFieldEquals(fade, clone, "mNameOverrides"); + assertFieldEquals(fade, clone, "mMatchOrder"); + + assertFieldEquals(fade, clone, "mTargets"); + assertFieldEquals(fade, clone, "mTargetExcludes"); + assertFieldEquals(fade, clone, "mTargetChildExcludes"); + + assertFieldEquals(fade, clone, "mTargetIds"); + assertFieldEquals(fade, clone, "mTargetIdExcludes"); + assertFieldEquals(fade, clone, "mTargetIdChildExcludes"); - assertEquals(fade.mTargets, clone.mTargets); - assertEquals(fade.mTargetExcludes, clone.mTargetExcludes); - assertEquals(fade.mTargetChildExcludes, clone.mTargetChildExcludes); + assertFieldEquals(fade, clone, "mTargetNames"); + assertFieldEquals(fade, clone, "mTargetNameExcludes"); - assertEquals(fade.mTargetIds, clone.mTargetIds); - assertEquals(fade.mTargetIdExcludes, clone.mTargetIdExcludes); - assertEquals(fade.mTargetIdChildExcludes, clone.mTargetIdChildExcludes); + assertFieldEquals(fade, clone, "mTargetTypes"); + assertFieldEquals(fade, clone, "mTargetTypeExcludes"); + } - assertEquals(fade.mTargetNames, clone.mTargetNames); - assertEquals(fade.mTargetNameExcludes, clone.mTargetNameExcludes); + private static void assertFieldEquals(Fade fade1, Fade fade2, String fieldName) + throws NoSuchFieldException, IllegalAccessException { + Field field = findField(Fade.class, fieldName); + field.setAccessible(true); + assertEquals("Field '" + fieldName + "' value mismatch", field.get(fade1), + field.get(fade2)); + } - assertEquals(fade.mTargetTypes, clone.mTargetTypes); - assertEquals(fade.mTargetTypeExcludes, clone.mTargetTypeExcludes); + private static Field findField(Class<?> type, String fieldName) throws NoSuchFieldException { + while (type != null) { + try { + return type.getDeclaredField(fieldName); + } catch (NoSuchFieldException e) { + // try the parent + type = type.getSuperclass(); + } + } + throw new NoSuchFieldException(fieldName); } } diff --git a/core/tests/coretests/src/android/view/DisabledTest.java b/core/tests/coretests/src/android/view/DisabledTest.java index d78e5e9bcbbd..291a11c289b7 100644 --- a/core/tests/coretests/src/android/view/DisabledTest.java +++ b/core/tests/coretests/src/android/view/DisabledTest.java @@ -78,7 +78,7 @@ public class DisabledTest extends ActivityInstrumentationTestCase<Disabled> { assertNotNull(mDisabledParent); assertFalse(mDisabled.isEnabled()); assertTrue(mDisabledParent.isEnabled()); - assertTrue(mDisabled.hasFocus()); + assertFalse(mDisabled.hasFocus()); } @MediumTest diff --git a/core/tests/coretests/src/android/widget/SelectionActionModeHelperTest.java b/core/tests/coretests/src/android/widget/SelectionActionModeHelperTest.java new file mode 100644 index 000000000000..d94a017c27fd --- /dev/null +++ b/core/tests/coretests/src/android/widget/SelectionActionModeHelperTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.widget; + +import static org.junit.Assert.assertEquals; + +import android.graphics.PointF; +import android.graphics.RectF; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.util.Arrays; +import java.util.List; + +@RunWith(JUnit4.class) +public final class SelectionActionModeHelperTest { + + /* + * The test rectangle set is composed of three 1x1 rectangles as illustrated below. + * + * (0, 0) ____________ (100001, 0) + * |█ █| + * |_█________| + * (0, 2) (100001, 2) + */ + private final List<RectF> mRectFList = Arrays.asList( + new RectF(0, 0, 1, 1), + new RectF(100000, 0, 100001, 1), + new RectF(1, 1, 2, 2)); + + @Test + public void testMovePointInsideNearestRectangle_pointIsInsideRectangle() { + testMovePointInsideNearestRectangle( + 0.1f /* pointX */, + 0.1f /* pointY */, + 0.1f /* expectedPointX */, + 0.5f /* expectedPointY */); + } + + @Test + public void testMovePointInsideNearestRectangle_pointIsAboveRectangle() { + testMovePointInsideNearestRectangle( + 0.1f /* pointX */, + -1.0f /* pointY */, + 0.1f /* expectedPointX */, + 0.5f /* expectedPointY */); + } + + @Test + public void testMovePointInsideNearestRectangle_pointIsLeftOfRectangle() { + testMovePointInsideNearestRectangle( + -1.0f /* pointX */, + 0.4f /* pointY */, + 0.0f /* expectedPointX */, + 0.5f /* expectedPointY */); + } + + @Test + public void testMovePointInsideNearestRectangle_pointIsRightOfRectangle() { + testMovePointInsideNearestRectangle( + 1.1f /* pointX */, + 0.0f /* pointY */, + 1.0f /* expectedPointX */, + 0.5f /* expectedPointY */); + } + + @Test + public void testMovePointInsideNearestRectangle_pointIsBelowRectangle() { + testMovePointInsideNearestRectangle( + 0.1f /* pointX */, + 1.1f /* pointY */, + 0.1f /* expectedPointX */, + 0.5f /* expectedPointY */); + } + + @Test + public void testMovePointInsideNearestRectangle_pointIsToRightOfTheRightmostRectangle() { + testMovePointInsideNearestRectangle( + 200000.0f /* pointX */, + 0.1f /* pointY */, + 100001.0f /* expectedPointX */, + 0.5f /* expectedPointY */); + } + + private void testMovePointInsideNearestRectangle(final float pointX, final float pointY, + final float expectedPointX, + final float expectedPointY) { + final PointF point = new PointF(pointX, pointY); + final PointF adjustedPoint = + SelectionActionModeHelper.movePointInsideNearestRectangle(point, + mRectFList); + + assertEquals(expectedPointX, adjustedPoint.x, 0.0f); + assertEquals(expectedPointY, adjustedPoint.y, 0.0f); + } + +} diff --git a/core/tests/coretests/src/android/widget/TextViewTest.java b/core/tests/coretests/src/android/widget/TextViewTest.java index 5806bf102beb..d31da71581ef 100644 --- a/core/tests/coretests/src/android/widget/TextViewTest.java +++ b/core/tests/coretests/src/android/widget/TextViewTest.java @@ -30,6 +30,7 @@ import android.support.test.annotation.UiThreadTest; import android.support.test.filters.MediumTest; import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; +import android.text.FontFallbackSetup; import android.text.GetChars; import android.text.Layout; import android.text.Selection; @@ -249,4 +250,56 @@ public class TextViewTest { } return builder.toString(); } + + @Test + public void testFallbackLineSpacing() { + // All glyphs in the fonts are 1em wide. + final String[] testFontFiles = { + // ascent == 1em, descent == 2em, only supports 'a' and space + "ascent1em-descent2em.ttf", + // ascent == 3em, descent == 4em, only supports 'b' + "ascent3em-descent4em.ttf" + }; + final String xml = "<?xml version='1.0' encoding='UTF-8'?>" + + "<familyset>" + + " <family name='sans-serif'>" + + " <font weight='400' style='normal'>ascent1em-descent2em.ttf</font>" + + " </family>" + + " <family>" + + " <font weight='400' style='normal'>ascent3em-descent4em.ttf</font>" + + " </family>" + + "</familyset>"; + + try (FontFallbackSetup setup = + new FontFallbackSetup("DynamicLayout", testFontFiles, xml)) { + mTextView = new TextView(mActivity); + mTextView.setTypeface(setup.getTypefaceFor("sans-serif")); + mTextView.setTextSize(100); + mTextView.setText("aaaaa aabaa aaaaa"); // This should result in three lines. + mTextView.setPadding(0, 0, 0, 0); + mTextView.setIncludeFontPadding(false); + + final int em = (int) Math.ceil(mTextView.getPaint().measureText("a")); + final int width = 5 * em; + final int height = 30 * em; // tall enough to not affect our other measurements + mTextView.measure( + View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)); + mTextView.layout(0, 0, width, height); + + final Layout layout = mTextView.getLayout(); + assertNotNull(layout); + assertEquals(3, layout.getLineCount()); + + assertEquals(-em, layout.getLineAscent(0)); + assertEquals(2 * em, layout.getLineDescent(0)); + + // The second line has a 'b', so it needs more ascent and descent. + assertEquals(-3 * em, layout.getLineAscent(1)); + assertEquals(4 * em, layout.getLineDescent(1)); + + assertEquals(-em, layout.getLineAscent(2)); + assertEquals(2 * em, layout.getLineDescent(2)); + } + } } diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsDurationTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsDurationTimerTest.java index a1b05cdbd9d8..19dab7961401 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsDurationTimerTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsDurationTimerTest.java @@ -134,7 +134,8 @@ public class BatteryStatsDurationTimerTest extends TestCase { null, BatteryStats.WAKE_TYPE_PARTIAL, null, timeBase); summary.startRunningLocked(3100); summary.readSummaryFromParcelLocked(summaryParcel); - // The new one shouldn't be running, and therefore 0 for current time + // The new one shouldn't be running, and therefore 0 for current time if using + // summary parcel assertFalse(summary.isRunningLocked()); assertEquals(0, summary.getCurrentDurationMsLocked(6300)); // The new one should have the max and total durations that we had when we wrote it @@ -149,10 +150,10 @@ public class BatteryStatsDurationTimerTest extends TestCase { // Read full - Should be the same as the summary as far as DurationTimer is concerned. final BatteryStatsImpl.DurationTimer full = new BatteryStatsImpl.DurationTimer(clocks, null, BatteryStats.WAKE_TYPE_PARTIAL, null, timeBase, fullParcel); - // The new one shouldn't be running, and therefore 0 for current time + // The new one shouldn't be running assertFalse(full.isRunningLocked()); - assertEquals(0, full.getCurrentDurationMsLocked(6300)); - // The new one should have the max and total durations that we had when we wrote it + // The new one should have the current, max and total durations that we had when we wrote it + assertEquals(1200, full.getCurrentDurationMsLocked(6300)); assertEquals(1200, full.getMaxDurationMsLocked(6301)); assertEquals(1200, full.getTotalDurationMsLocked(6302)); diff --git a/core/tests/featureflagtests/Android.mk b/core/tests/featureflagtests/Android.mk new file mode 100644 index 000000000000..f2d205885c20 --- /dev/null +++ b/core/tests/featureflagtests/Android.mk @@ -0,0 +1,19 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +# We only want this apk build for tests. +LOCAL_MODULE_TAGS := tests + +# Include all test java files. +LOCAL_SRC_FILES := \ + $(call all-java-files-under, src) + +LOCAL_DX_FLAGS := --core-library +LOCAL_STATIC_JAVA_LIBRARIES := android-common frameworks-core-util-lib android-support-test +LOCAL_JAVA_LIBRARIES := android.test.runner +LOCAL_PACKAGE_NAME := FrameworksCoreFeatureFlagTests + +LOCAL_CERTIFICATE := platform +LOCAL_COMPATIBILITY_SUITE := device-tests + +include $(BUILD_PACKAGE) diff --git a/core/tests/featureflagtests/AndroidManifest.xml b/core/tests/featureflagtests/AndroidManifest.xml new file mode 100644 index 000000000000..b8ffacbe5aa8 --- /dev/null +++ b/core/tests/featureflagtests/AndroidManifest.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + android:installLocation="internalOnly" + package="com.android.frameworks.coretests.featureflagtests" + android:sharedUserId="android.uid.system"> + + <application> + <uses-library android:name="android.test.runner" /> + </application> + + <instrumentation + android:name="android.support.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.frameworks.coretests.featureflagtests" + android:label="Frameworks FeatureFlagUtils Tests" /> + +</manifest> diff --git a/core/tests/featureflagtests/AndroidTest.xml b/core/tests/featureflagtests/AndroidTest.xml new file mode 100644 index 000000000000..44f9c3e37853 --- /dev/null +++ b/core/tests/featureflagtests/AndroidTest.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> +<configuration description="Runs Frameworks Utility Tests."> + <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> + <option name="test-file-name" value="FrameworksCoreFeatureFlagTests.apk" /> + </target_preparer> + + <option name="test-suite-tag" value="apct" /> + <option name="test-tag" value="FrameworksCoreFeatureFlagTests" /> + <test class="com.android.tradefed.testtype.AndroidJUnitTest" > + <option name="package" value="com.android.frameworks.coretests.featureflagtests" /> + <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" /> + </test> +</configuration> diff --git a/core/tests/featureflagtests/src/android/util/FeatureFlagUtilsTest.java b/core/tests/featureflagtests/src/android/util/FeatureFlagUtilsTest.java new file mode 100644 index 000000000000..8fee1d11a954 --- /dev/null +++ b/core/tests/featureflagtests/src/android/util/FeatureFlagUtilsTest.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.util; + +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + +import android.os.SystemProperties; +import android.support.test.runner.AndroidJUnit4; +import android.test.suitebuilder.annotation.SmallTest; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class FeatureFlagUtilsTest { + + private static final String TEST_FEATURE_NAME = "feature_foobar"; + + @Before + public void setUp() { + cleanup(); + } + + @After + public void tearDown() { + cleanup(); + } + + private void cleanup() { + SystemProperties.set(FeatureFlagUtils.FFLAG_PREFIX + TEST_FEATURE_NAME, ""); + SystemProperties.set(FeatureFlagUtils.FFLAG_OVERRIDE_PREFIX + TEST_FEATURE_NAME, ""); + } + + @Test + public void testGetFlag_enabled_shouldReturnTrue() { + SystemProperties.set(FeatureFlagUtils.FFLAG_PREFIX + TEST_FEATURE_NAME, "true"); + + assertTrue(FeatureFlagUtils.isEnabled(TEST_FEATURE_NAME)); + } + + @Test + public void testGetFlag_override_shouldReturnTrue() { + SystemProperties.set(FeatureFlagUtils.FFLAG_PREFIX + TEST_FEATURE_NAME, "false"); + SystemProperties.set(FeatureFlagUtils.FFLAG_OVERRIDE_PREFIX + TEST_FEATURE_NAME, "true"); + + assertTrue(FeatureFlagUtils.isEnabled(TEST_FEATURE_NAME)); + } + + @Test + public void testGetFlag_notSet_shouldReturnFalse() { + assertFalse(FeatureFlagUtils.isEnabled(TEST_FEATURE_NAME)); + } + +} diff --git a/core/tests/systemproperties/run_core_systemproperties_test.sh b/core/tests/systemproperties/run_core_systemproperties_test.sh index d39adbbfa390..9b1fe4be666b 100755 --- a/core/tests/systemproperties/run_core_systemproperties_test.sh +++ b/core/tests/systemproperties/run_core_systemproperties_test.sh @@ -15,7 +15,7 @@ fi if [[ $rebuild == true ]]; then make -j4 FrameworksCoreSystemPropertiesTests - TESTAPP=${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreSystemPropertiesTests.apk + TESTAPP=${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreSystemPropertiesTests/FrameworksCoreSystemPropertiesTests.apk COMMAND="adb install -r $TESTAPP" echo $COMMAND $COMMAND diff --git a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java index 544a96727217..282b0011eede 100644 --- a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java +++ b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java @@ -51,6 +51,11 @@ public class SystemPropertiesTest extends TestCase { value = SystemProperties.get(KEY, "default"); assertEquals("default", value); + // null default value is the same as "". + SystemProperties.set(KEY, null); + value = SystemProperties.get(KEY, "default"); + assertEquals("default", value); + SystemProperties.set(KEY, "SA"); value = SystemProperties.get(KEY, "default"); assertEquals("SA", value); @@ -62,7 +67,78 @@ public class SystemPropertiesTest extends TestCase { value = SystemProperties.get(KEY, "default"); assertEquals("default", value); + // null value is the same as "". + SystemProperties.set(KEY, "SA"); + SystemProperties.set(KEY, null); + value = SystemProperties.get(KEY, "default"); + assertEquals("default", value); + value = SystemProperties.get(KEY); assertEquals("", value); } + + private static void testInt(String setVal, int defValue, int expected) { + SystemProperties.set(KEY, setVal); + int value = SystemProperties.getInt(KEY, defValue); + assertEquals(expected, value); + } + + private static void testLong(String setVal, long defValue, long expected) { + SystemProperties.set(KEY, setVal); + long value = SystemProperties.getLong(KEY, defValue); + assertEquals(expected, value); + } + + @SmallTest + public void testIntegralProperties() throws Exception { + testInt("", 123, 123); + testInt("", 0, 0); + testInt("", -123, -123); + + testInt("123", 124, 123); + testInt("0", 124, 0); + testInt("-123", 124, -123); + + testLong("", 3147483647L, 3147483647L); + testLong("", 0, 0); + testLong("", -3147483647L, -3147483647L); + + testLong("3147483647", 124, 3147483647L); + testLong("0", 124, 0); + testLong("-3147483647", 124, -3147483647L); + } + + @SmallTest + @SuppressWarnings("null") + public void testNullKey() throws Exception { + try { + SystemProperties.get(null); + fail("Expected NullPointerException"); + } catch (NullPointerException npe) { + } + + try { + SystemProperties.get(null, "default"); + fail("Expected NullPointerException"); + } catch (NullPointerException npe) { + } + + try { + SystemProperties.set(null, "value"); + fail("Expected NullPointerException"); + } catch (NullPointerException npe) { + } + + try { + SystemProperties.getInt(null, 0); + fail("Expected NullPointerException"); + } catch (NullPointerException npe) { + } + + try { + SystemProperties.getLong(null, 0); + fail("Expected NullPointerException"); + } catch (NullPointerException npe) { + } + } } diff --git a/data/etc/framework-sysconfig.xml b/data/etc/framework-sysconfig.xml index 3a81c1309a8b..ae6a7f6d6808 100644 --- a/data/etc/framework-sysconfig.xml +++ b/data/etc/framework-sysconfig.xml @@ -22,6 +22,8 @@ <allow-implicit-broadcast action="android.intent.action.SIM_STATE_CHANGED" /> <allow-implicit-broadcast action="android.intent.action.PACKAGE_CHANGED" /> <allow-implicit-broadcast action="android.intent.action.MEDIA_SCANNER_SCAN_FILE" /> + <allow-implicit-broadcast action="android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION" /> + <allow-implicit-broadcast action="android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION" /> <!-- Whitelist of what components are permitted as backup data transports. The 'service' attribute here is a flattened ComponentName string. --> diff --git a/data/sounds/AudioPackageGo.mk b/data/sounds/AudioPackageGo.mk new file mode 100644 index 000000000000..3756d3056da9 --- /dev/null +++ b/data/sounds/AudioPackageGo.mk @@ -0,0 +1,42 @@ +# Copyright 2013 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. + +LOCAL_PATH := frameworks/base/data/sounds + +# Ring_Classic_02 : Bell Phone +# Ring_Synth_02 : Chimey Phone +# Ring_Digital_02 : Digital Phone +# Ring_Synth_04 : Flutey Phone +# Alarm_Beep_03 : Beep Beep Beep +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/notifications/ogg/Alya.ogg:system/media/audio/notifications/Alya.ogg \ + $(LOCAL_PATH)/notifications/ogg/Argon.ogg:system/media/audio/notifications/Argon.ogg \ + $(LOCAL_PATH)/notifications/Canopus.ogg:system/media/audio/notifications/Canopus.ogg \ + $(LOCAL_PATH)/notifications/Deneb.ogg:system/media/audio/notifications/Deneb.ogg \ + $(LOCAL_PATH)/newwavelabs/Highwire.ogg:system/media/audio/notifications/Highwire.ogg \ + $(LOCAL_PATH)/notifications/ogg/Iridium.ogg:system/media/audio/notifications/Iridium.ogg \ + $(LOCAL_PATH)/notifications/pixiedust.ogg:system/media/audio/notifications/pixiedust.ogg \ + $(LOCAL_PATH)/notifications/ogg/Talitha.ogg:system/media/audio/notifications/Talitha.ogg \ + $(LOCAL_PATH)/Ring_Classic_02.ogg:system/media/audio/ringtones/Ring_Classic_02.ogg \ + $(LOCAL_PATH)/Ring_Synth_02.ogg:system/media/audio/ringtones/Ring_Synth_02.ogg \ + $(LOCAL_PATH)/ringtones/ogg/Cygnus.ogg:system/media/audio/ringtones/Cygnus.ogg \ + $(LOCAL_PATH)/Ring_Digital_02.ogg:system/media/audio/ringtones/Ring_Digital_02.ogg \ + $(LOCAL_PATH)/Ring_Synth_04.ogg:system/media/audio/ringtones/Ring_Synth_04.ogg \ + $(LOCAL_PATH)/ringtones/ogg/Kuma.ogg:system/media/audio/ringtones/Kuma.ogg \ + $(LOCAL_PATH)/ringtones/ogg/Themos.ogg:system/media/audio/ringtones/Themos.ogg \ + $(LOCAL_PATH)/alarms/ogg/Argon.ogg:system/media/audio/alarms/Argon.ogg \ + $(LOCAL_PATH)/alarms/ogg/Platinum.ogg:system/media/audio/alarms/Platinum.ogg \ + $(LOCAL_PATH)/Alarm_Beep_03.ogg:system/media/audio/alarms/Alarm_Beep_03.ogg \ + $(LOCAL_PATH)/alarms/ogg/Helium.ogg:system/media/audio/alarms/Helium.ogg \ + $(LOCAL_PATH)/alarms/ogg/Oxygen.ogg:system/media/audio/alarms/Oxygen.ogg \ diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index 0301f2e6b555..f5e863305766 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -200,11 +200,6 @@ public class Canvas extends BaseCanvas { } /** @hide */ - public void setHighContrastText(boolean highContrastText) { - nSetHighContrastText(mNativeCanvasWrapper, highContrastText); - } - - /** @hide */ public void insertReorderBarrier() {} /** @hide */ @@ -1242,8 +1237,6 @@ public class Canvas extends BaseCanvas { @CriticalNative private static native boolean nIsOpaque(long canvasHandle); @CriticalNative - private static native void nSetHighContrastText(long renderer, boolean highContrastText); - @CriticalNative private static native int nGetWidth(long canvasHandle); @CriticalNative private static native int nGetHeight(long canvasHandle); diff --git a/graphics/java/android/graphics/Color.java b/graphics/java/android/graphics/Color.java index bdd828fd5127..c4bf9d3123bf 100644 --- a/graphics/java/android/graphics/Color.java +++ b/graphics/java/android/graphics/Color.java @@ -73,7 +73,7 @@ import java.util.function.DoubleUnaryOperator; * <h4>Encoding</h4> * <p>The four components of a color int are encoded in the following way:</p> * <pre class="prettyprint"> - * int color = (A & 0xff) << 24 | (R & 0xff) << 16 | (G & 0xff) << 16 | (B & 0xff); + * int color = (A & 0xff) << 24 | (R & 0xff) << 16 | (G & 0xff) << 8 | (B & 0xff); * </pre> * * <p>Because of this encoding, color ints can easily be described as an integer diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index 46ada23c632f..1a06a5683cd3 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -1729,6 +1729,9 @@ public class Paint { * Return the distance above (negative) the baseline (ascent) based on the * current typeface and text size. * + * <p>Note that this is the ascent of the main typeface, and actual text rendered may need a + * larger ascent because fallback fonts may get used in rendering the text. + * * @return the distance above (negative) the baseline (ascent) based on the * current typeface and text size. */ @@ -1740,6 +1743,9 @@ public class Paint { * Return the distance below (positive) the baseline (descent) based on the * current typeface and text size. * + * <p>Note that this is the descent of the main typeface, and actual text rendered may need a + * larger descent because fallback fonts may get used in rendering the text. + * * @return the distance below (positive) the baseline (descent) based on * the current typeface and text size. */ @@ -1783,6 +1789,9 @@ public class Paint { * settings for typeface, textSize, etc. If metrics is not null, return the * fontmetric values in it. * + * <p>Note that these are the values for the main typeface, and actual text rendered may need a + * larger set of values because fallback fonts may get used in rendering the text. + * * @param metrics If this object is not null, its fields are filled with * the appropriate values given the paint's text attributes. * @return the font's recommended interline spacing. @@ -1844,6 +1853,9 @@ public class Paint { * and clipping. If you want more control over the rounding, call * getFontMetrics(). * + * <p>Note that these are the values for the main typeface, and actual text rendered may need a + * larger set of values because fallback fonts may get used in rendering the text. + * * @return the font's interline spacing. */ public int getFontMetricsInt(FontMetricsInt fmi) { @@ -1860,6 +1872,9 @@ public class Paint { * Return the recommend line spacing based on the current typeface and * text size. * + * <p>Note that this is the value for the main typeface, and actual text rendered may need a + * larger value because fallback fonts may get used in rendering the text. + * * @return recommend line spacing based on the current typeface and * text size. */ diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java index deafb6638ece..3dc928de60df 100644 --- a/graphics/java/android/graphics/Rect.java +++ b/graphics/java/android/graphics/Rect.java @@ -21,6 +21,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; +import android.util.proto.ProtoOutputStream; import java.io.PrintWriter; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -194,7 +195,24 @@ public final class Rect implements Parcelable { pw.print(top); pw.print("]["); pw.print(right); pw.print(','); pw.print(bottom); pw.print(']'); } - + + /** + * Write to a protocol buffer output stream. + * Protocol buffer message definition at {@link android.graphics.RectProto} + * + * @param protoOutputStream Stream to write the Rect object to. + * @param fieldId Field Id of the Rect as defined in the parent message + * @hide + */ + public void writeToProto(ProtoOutputStream protoOutputStream, long fieldId) { + final long token = protoOutputStream.start(fieldId); + protoOutputStream.write(RectProto.LEFT, left); + protoOutputStream.write(RectProto.TOP, top); + protoOutputStream.write(RectProto.RIGHT, right); + protoOutputStream.write(RectProto.BOTTOM, bottom); + protoOutputStream.end(token); + } + /** * Returns true if the rectangle is empty (left >= right or top >= bottom) */ diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index 7496fa6abf47..cfc389f00436 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -97,19 +97,33 @@ public class Typeface { public static final Typeface MONOSPACE; static Typeface[] sDefaults; - private static final LongSparseArray<SparseArray<Typeface>> sTypefaceCache = + + /** + * Cache for Typeface objects for style variant. Currently max size is 3. + */ + @GuardedBy("sStyledCacheLock") + private static final LongSparseArray<SparseArray<Typeface>> sStyledTypefaceCache = new LongSparseArray<>(3); + private static final Object sStyledCacheLock = new Object(); + + /** + * Cache for Typeface objects for weight variant. Currently max size is 3. + */ + @GuardedBy("sWeightCacheLock") + private static final LongSparseArray<SparseArray<Typeface>> sWeightTypefaceCache = + new LongSparseArray<>(3); + private static final Object sWeightCacheLock = new Object(); /** * Cache for Typeface objects dynamically loaded from assets. Currently max size is 16. */ - @GuardedBy("sLock") + @GuardedBy("sDynamicCacheLock") private static final LruCache<String, Typeface> sDynamicTypefaceCache = new LruCache<>(16); + private static final Object sDynamicCacheLock = new Object(); static Typeface sDefaultTypeface; static final Map<String, Typeface> sSystemFontMap; static final Map<String, FontFamily[]> sSystemFallbackMap; - private static final Object sLock = new Object(); /** * @hide @@ -121,6 +135,7 @@ public class Typeface { public static final int BOLD = 1; public static final int ITALIC = 2; public static final int BOLD_ITALIC = 3; + /** @hide */ public static final int STYLE_MASK = 0x03; private int mStyle = 0; private int mWeight = 0; @@ -143,6 +158,13 @@ public class Typeface { nativeSetDefault(t.native_instance); } + // TODO: Make this public API. (b/64852739) + /** @hide */ + @VisibleForTesting + public int getWeight() { + return mWeight; + } + /** Returns the typeface's intrinsic style attributes */ public int getStyle() { return mStyle; @@ -164,7 +186,7 @@ public class Typeface { */ @Nullable public static Typeface createFromResources(AssetManager mgr, String path, int cookie) { - synchronized (sDynamicTypefaceCache) { + synchronized (sDynamicCacheLock) { final String key = Builder.createAssetUid( mgr, path, 0 /* ttcIndex */, null /* axes */, RESOLVE_BY_FONT_TABLE /* weight */, RESOLVE_BY_FONT_TABLE /* italic */, @@ -241,7 +263,7 @@ public class Typeface { FontFamily[] familyChain = { fontFamily }; typeface = createFromFamiliesWithDefault(familyChain, DEFAULT_FAMILY, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE); - synchronized (sDynamicTypefaceCache) { + synchronized (sDynamicCacheLock) { final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */, null /* axes */, RESOLVE_BY_FONT_TABLE /* weight */, RESOLVE_BY_FONT_TABLE /* italic */, DEFAULT_FAMILY); @@ -255,7 +277,7 @@ public class Typeface { * @hide */ public static Typeface findFromCache(AssetManager mgr, String path) { - synchronized (sDynamicTypefaceCache) { + synchronized (sDynamicCacheLock) { final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */, null /* axes */, RESOLVE_BY_FONT_TABLE /* weight */, RESOLVE_BY_FONT_TABLE /* italic */, DEFAULT_FAMILY); @@ -525,12 +547,6 @@ public class Typeface { return builder.toString(); } - private static final Object sLock = new Object(); - // TODO: Unify with Typeface.sTypefaceCache. - @GuardedBy("sLock") - private static final LongSparseArray<SparseArray<Typeface>> sTypefaceCache = - new LongSparseArray<>(3); - private Typeface resolveFallbackTypeface() { if (mFallbackFamilyName == null) { return null; @@ -581,7 +597,7 @@ public class Typeface { final String key = createAssetUid( mAssetManager, mPath, mTtcIndex, mAxes, mWeight, mItalic, mFallbackFamilyName); - synchronized (sLock) { + synchronized (sDynamicCacheLock) { Typeface typeface = sDynamicTypefaceCache.get(key); if (typeface != null) return typeface; final FontFamily fontFamily = new FontFamily(); @@ -666,6 +682,11 @@ public class Typeface { * style from the same family of an existing typeface object. If family is * null, this selects from the default font's family. * + * <p> + * This method is not thread safe on API 27 or before. + * This method is thread safe on API 28 or after. + * </p> + * * @param family An existing {@link Typeface} object. In case of {@code null}, the default * typeface is used instead. * @param style The style (normal, bold, italic) of the typeface. @@ -673,36 +694,37 @@ public class Typeface { * @return The best matching typeface. */ public static Typeface create(Typeface family, int style) { - if (style < 0 || style > 3) { - style = 0; + if ((style & ~STYLE_MASK) != 0) { + style = NORMAL; + } + if (family == null) { + family = sDefaultTypeface; } - long ni = 0; - if (family != null) { - // Return early if we're asked for the same face/style - if (family.mStyle == style) { - return family; - } - ni = family.native_instance; + // Return early if we're asked for the same face/style + if (family.mStyle == style) { + return family; } + final long ni = family.native_instance; + Typeface typeface; - SparseArray<Typeface> styles = sTypefaceCache.get(ni); + synchronized (sStyledCacheLock) { + SparseArray<Typeface> styles = sStyledTypefaceCache.get(ni); - if (styles != null) { - typeface = styles.get(style); - if (typeface != null) { - return typeface; + if (styles == null) { + styles = new SparseArray<Typeface>(4); + sStyledTypefaceCache.put(ni, styles); + } else { + typeface = styles.get(style); + if (typeface != null) { + return typeface; + } } - } - typeface = new Typeface(nativeCreateFromTypeface(ni, style)); - if (styles == null) { - styles = new SparseArray<Typeface>(4); - sTypefaceCache.put(ni, styles); + typeface = new Typeface(nativeCreateFromTypeface(ni, style)); + styles.put(style, typeface); } - styles.put(style, typeface); - return typeface; } @@ -710,6 +732,10 @@ public class Typeface { * Creates a typeface object that best matches the specified existing typeface and the specified * weight and italic style * + * <p> + * This method is thread safe. + * </p> + * * @param family An existing {@link Typeface} object. In case of {@code null}, the default * typeface is used instead. * @param weight The desired weight to be drawn. @@ -728,12 +754,15 @@ public class Typeface { private static @NonNull Typeface createWeightStyle(@NonNull Typeface base, @IntRange(from = 1, to = 1000) int weight, boolean italic) { - final int key = weight << 1 | (italic ? 1 : 0); + final int key = (weight << 1) | (italic ? 1 : 0); Typeface typeface; - synchronized(sLock) { - SparseArray<Typeface> innerCache = sTypefaceCache.get(base.native_instance); - if (innerCache != null) { + synchronized(sWeightCacheLock) { + SparseArray<Typeface> innerCache = sWeightTypefaceCache.get(base.native_instance); + if (innerCache == null) { + innerCache = new SparseArray<>(4); + sWeightTypefaceCache.put(base.native_instance, innerCache); + } else { typeface = innerCache.get(key); if (typeface != null) { return typeface; @@ -743,11 +772,6 @@ public class Typeface { typeface = new Typeface( nativeCreateFromTypefaceWithExactStyle( base.native_instance, weight, italic)); - - if (innerCache == null) { - innerCache = new SparseArray<>(4); // [regular, bold] x [upright, italic] - sTypefaceCache.put(base.native_instance, innerCache); - } innerCache.put(key, typeface); } return typeface; @@ -780,7 +804,7 @@ public class Typeface { if (path == null) { throw new NullPointerException(); // for backward compatibility } - synchronized (sLock) { + synchronized (sDynamicCacheLock) { Typeface typeface = new Builder(mgr, path).build(); if (typeface != null) return typeface; diff --git a/graphics/java/android/graphics/pdf/PdfEditor.java b/graphics/java/android/graphics/pdf/PdfEditor.java index 245d76917453..0c509b77bad8 100644 --- a/graphics/java/android/graphics/pdf/PdfEditor.java +++ b/graphics/java/android/graphics/pdf/PdfEditor.java @@ -39,7 +39,7 @@ public final class PdfEditor { private final CloseGuard mCloseGuard = CloseGuard.get(); - private final long mNativeDocument; + private long mNativeDocument; private int mPageCount; @@ -77,12 +77,17 @@ public final class PdfEditor { } catch (ErrnoException ee) { throw new IllegalArgumentException("file descriptor not seekable"); } - mInput = input; synchronized (PdfRenderer.sPdfiumLock) { mNativeDocument = nativeOpen(mInput.getFd(), size); - mPageCount = nativeGetPageCount(mNativeDocument); + try { + mPageCount = nativeGetPageCount(mNativeDocument); + } catch (Throwable t) { + nativeClose(mNativeDocument); + mNativeDocument = 0; + throw t; + } } mCloseGuard.open("close"); @@ -274,20 +279,24 @@ public final class PdfEditor { mCloseGuard.warnIfOpen(); } - if (mInput != null) { - doClose(); - } + doClose(); } finally { super.finalize(); } } private void doClose() { - synchronized (PdfRenderer.sPdfiumLock) { - nativeClose(mNativeDocument); + if (mNativeDocument != 0) { + synchronized (PdfRenderer.sPdfiumLock) { + nativeClose(mNativeDocument); + } + mNativeDocument = 0; + } + + if (mInput != null) { + IoUtils.closeQuietly(mInput); + mInput = null; } - IoUtils.closeQuietly(mInput); - mInput = null; mCloseGuard.close(); } diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java index b7b81aef36fd..c82ab0dd5cc7 100644 --- a/graphics/java/android/graphics/pdf/PdfRenderer.java +++ b/graphics/java/android/graphics/pdf/PdfRenderer.java @@ -29,6 +29,8 @@ import android.system.ErrnoException; import android.system.OsConstants; import com.android.internal.util.Preconditions; import dalvik.system.CloseGuard; + +import libcore.io.IoUtils; import libcore.io.Libcore; import java.io.IOException; @@ -110,7 +112,7 @@ public final class PdfRenderer implements AutoCloseable { private final Point mTempPoint = new Point(); - private final long mNativeDocument; + private long mNativeDocument; private final int mPageCount; @@ -159,7 +161,6 @@ public final class PdfRenderer implements AutoCloseable { } catch (ErrnoException ee) { throw new IllegalArgumentException("file descriptor not seekable"); } - mInput = input; synchronized (sPdfiumLock) { @@ -168,6 +169,7 @@ public final class PdfRenderer implements AutoCloseable { mPageCount = nativeGetPageCount(mNativeDocument); } catch (Throwable t) { nativeClose(mNativeDocument); + mNativeDocument = 0; throw t; } } @@ -234,9 +236,7 @@ public final class PdfRenderer implements AutoCloseable { mCloseGuard.warnIfOpen(); } - if (mInput != null) { - doClose(); - } + doClose(); } finally { super.finalize(); } @@ -245,16 +245,20 @@ public final class PdfRenderer implements AutoCloseable { private void doClose() { if (mCurrentPage != null) { mCurrentPage.close(); + mCurrentPage = null; } - synchronized (sPdfiumLock) { - nativeClose(mNativeDocument); + + if (mNativeDocument != 0) { + synchronized (sPdfiumLock) { + nativeClose(mNativeDocument); + } + mNativeDocument = 0; } - try { - mInput.close(); - } catch (IOException ioe) { - /* ignore - best effort */ + + if (mInput != null) { + IoUtils.closeQuietly(mInput); + mInput = null; } - mInput = null; mCloseGuard.close(); } @@ -451,19 +455,20 @@ public final class PdfRenderer implements AutoCloseable { mCloseGuard.warnIfOpen(); } - if (mNativePage != 0) { - doClose(); - } + doClose(); } finally { super.finalize(); } } private void doClose() { - synchronized (sPdfiumLock) { - nativeClosePage(mNativePage); + if (mNativePage != 0) { + synchronized (sPdfiumLock) { + nativeClosePage(mNativePage); + } + mNativePage = 0; } - mNativePage = 0; + mCloseGuard.close(); mCurrentPage = null; } diff --git a/keystore/java/android/security/KeyPairGeneratorSpec.java b/keystore/java/android/security/KeyPairGeneratorSpec.java index d023866ca702..d5b34c432e79 100644 --- a/keystore/java/android/security/KeyPairGeneratorSpec.java +++ b/keystore/java/android/security/KeyPairGeneratorSpec.java @@ -260,13 +260,13 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * Example: * * <pre class="prettyprint"> - * Calendar start = new Calendar(); - * Calendar end = new Calendar(); - * end.add(1, Calendar.YEAR); + * Calendar start = Calendar.getInstance(); + * Calendar end = Calendar.getInstance(); + * end.add(Calendar.YEAR, 1); * * KeyPairGeneratorSpec spec = * new KeyPairGeneratorSpec.Builder(mContext).setAlias("myKey") - * .setSubject(new X500Principal("CN=myKey")).setSerial(BigInteger.valueOf(1337)) + * .setSubject(new X500Principal("CN=myKey")).setSerialNumber(BigInteger.valueOf(1337)) * .setStartDate(start.getTime()).setEndDate(end.getTime()).build(); * </pre> * diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp index df2b35b39aa8..3c3b3177159b 100644 --- a/libs/hwui/BakedOpRenderer.cpp +++ b/libs/hwui/BakedOpRenderer.cpp @@ -208,7 +208,6 @@ void BakedOpRenderer::drawRects(const float* rects, int count, const SkPaint* pa // TODO: Currently assume full FBO damage, due to FrameInfoVisualizer::unionDirty. // Should should scissor/set mHasDrawn safely. mRenderState.scissor().setEnabled(false); - mHasDrawn = true; Glop glop; GlopBuilder(mRenderState, mCaches, &glop) .setRoundRectClipState(nullptr) @@ -217,7 +216,8 @@ void BakedOpRenderer::drawRects(const float* rects, int count, const SkPaint* pa .setTransform(Matrix4::identity(), TransformFlags::None) .setModelViewIdentityEmptyBounds() .build(); - mRenderState.render(glop, mRenderTarget.orthoMatrix); + mRenderState.render(glop, mRenderTarget.orthoMatrix, false); + mHasDrawn = true; } // clears and re-fills stencil with provided rendertarget space quads, @@ -234,7 +234,7 @@ void BakedOpRenderer::setupStencilQuads(std::vector<Vertex>& quadVertices, .setTransform(Matrix4::identity(), TransformFlags::None) .setModelViewIdentityEmptyBounds() .build(); - mRenderState.render(glop, mRenderTarget.orthoMatrix); + mRenderState.render(glop, mRenderTarget.orthoMatrix, false); mRenderState.stencil().enableTest(incrementThreshold); } @@ -346,7 +346,16 @@ void BakedOpRenderer::prepareRender(const Rect* dirtyBounds, const ClipBase* cli void BakedOpRenderer::renderGlopImpl(const Rect* dirtyBounds, const ClipBase* clip, const Glop& glop) { prepareRender(dirtyBounds, clip); - mRenderState.render(glop, mRenderTarget.orthoMatrix); + // Disable blending if this is the first draw to the main framebuffer, in case app has defined + // transparency where it doesn't make sense - as first draw in opaque window. Note that we only + // apply this improvement when the blend mode is SRC_OVER - other modes (e.g. CLEAR) can be + // valid draws that affect other content (e.g. draw CLEAR, then draw DST_OVER) + bool overrideDisableBlending = !mHasDrawn + && mOpaque + && !mRenderTarget.frameBufferId + && glop.blend.src == GL_ONE + && glop.blend.dst == GL_ONE_MINUS_SRC_ALPHA; + mRenderState.render(glop, mRenderTarget.orthoMatrix, overrideDisableBlending); if (!mRenderTarget.frameBufferId) mHasDrawn = true; } diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp index bc4181075319..8b0346867cbc 100644 --- a/libs/hwui/FontRenderer.cpp +++ b/libs/hwui/FontRenderer.cpp @@ -99,13 +99,22 @@ FontRenderer::FontRenderer(const uint8_t* gammaTable) } auto deviceInfo = DeviceInfo::get(); + auto displayInfo = deviceInfo->displayInfo(); int maxTextureSize = deviceInfo->maxTextureSize(); + // Adjust cache size based on Pixel's desnsity. + constexpr float PIXEL_DENSITY = 2.6; + const float densityRatio = displayInfo.density / PIXEL_DENSITY; + // TODO: Most devices are hardcoded with this configuration, does it need to be dynamic? - mSmallCacheWidth = std::min(1024, maxTextureSize); - mSmallCacheHeight = std::min(1024, maxTextureSize); - mLargeCacheWidth = std::min(2048, maxTextureSize); - mLargeCacheHeight = std::min(1024, maxTextureSize); + mSmallCacheWidth = + OffscreenBuffer::computeIdealDimension(std::min(1024, maxTextureSize) * densityRatio); + mSmallCacheHeight = + OffscreenBuffer::computeIdealDimension(std::min(1024, maxTextureSize) * densityRatio); + mLargeCacheWidth = + OffscreenBuffer::computeIdealDimension(std::min(2048, maxTextureSize) * densityRatio); + mLargeCacheHeight = + OffscreenBuffer::computeIdealDimension(std::min(1024, maxTextureSize) * densityRatio); if (sLogFontRendererCreate) { INIT_LOGD(" Text cache sizes, in pixels: %i x %i, %i x %i, %i x %i, %i x %i", diff --git a/libs/hwui/OpenGLReadback.cpp b/libs/hwui/OpenGLReadback.cpp index 025503b15975..f9a1cc5296d5 100644 --- a/libs/hwui/OpenGLReadback.cpp +++ b/libs/hwui/OpenGLReadback.cpp @@ -228,7 +228,7 @@ inline CopyResult copyTextureInto(Caches& caches, RenderState& renderState, .build(); Matrix4 ortho; ortho.loadOrtho(destWidth, destHeight); - renderState.render(glop, ortho); + renderState.render(glop, ortho, false); // TODO: We should convert to linear space when the target is RGBA16F glReadPixels(0, 0, bitmap->width(), bitmap->height(), format, diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index 4c84ad2b80a8..fe291d2a4bfe 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -51,6 +51,7 @@ int Properties::overrideSpotShadowStrength = -1; ProfileType Properties::sProfileType = ProfileType::None; bool Properties::sDisableProfileBars = false; RenderPipelineType Properties::sRenderPipelineType = RenderPipelineType::NotInitialized; +bool Properties::enableHighContrastText = false; bool Properties::waitForGpuCompletion = false; bool Properties::forceDrawFrame = false; @@ -176,7 +177,7 @@ RenderPipelineType Properties::getRenderPipelineType() { return sRenderPipelineType; } char prop[PROPERTY_VALUE_MAX]; - property_get(PROPERTY_RENDERER, prop, "skiagl"); + property_get(PROPERTY_RENDERER, prop, "opengl"); if (!strcmp(prop, "skiagl") ) { ALOGD("Skia GL Pipeline"); sRenderPipelineType = RenderPipelineType::SkiaGL; diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 47ae9e912127..0fe4c7714761 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -17,6 +17,7 @@ #ifndef ANDROID_HWUI_PROPERTIES_H #define ANDROID_HWUI_PROPERTIES_H +#include <cutils/compiler.h> #include <cutils/properties.h> /** @@ -237,6 +238,8 @@ public: static RenderPipelineType getRenderPipelineType(); static bool isSkiaEnabled(); + ANDROID_API static bool enableHighContrastText; + // Should be used only by test apps static bool waitForGpuCompletion; static bool forceDrawFrame; diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h index ccdb4b0c1d8e..79db496f2acd 100644 --- a/libs/hwui/RecordingCanvas.h +++ b/libs/hwui/RecordingCanvas.h @@ -93,11 +93,6 @@ public: virtual int width() override { return mState.getWidth(); } virtual int height() override { return mState.getHeight(); } - virtual void setHighContrastText(bool highContrastText) override { - mHighContrastText = highContrastText; - } - virtual bool isHighContrastText() override { return mHighContrastText; } - // ---------------------------------------------------------------------------- // android/graphics/Canvas state operations // ---------------------------------------------------------------------------- @@ -311,7 +306,6 @@ private: DeferredBarrierType mDeferredBarrierType = DeferredBarrierType::None; const ClipBase* mDeferredBarrierClip = nullptr; DisplayList* mDisplayList = nullptr; - bool mHighContrastText = false; sk_sp<SkDrawFilter> mDrawFilter; }; // class RecordingCanvas diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 61b3876cd095..36a747519c37 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -32,6 +32,7 @@ #include "protos/hwui.pb.h" #include "protos/ProtoHelpers.h" +#include <SkPathOps.h> #include <algorithm> #include <sstream> #include <string> @@ -555,5 +556,23 @@ void RenderNode::computeOrderingImpl( } } +const SkPath* RenderNode::getClippedOutline(const SkRect& clipRect) const { + const SkPath* outlinePath = properties().getOutline().getPath(); + const uint32_t outlineID = outlinePath->getGenerationID(); + + if (outlineID != mClippedOutlineCache.outlineID || clipRect != mClippedOutlineCache.clipRect) { + // update the cache keys + mClippedOutlineCache.outlineID = outlineID; + mClippedOutlineCache.clipRect = clipRect; + + // update the cache value by recomputing a new path + SkPath clipPath; + clipPath.addRect(clipRect); + Op(*outlinePath, clipPath, kIntersect_SkPathOp, &mClippedOutlineCache.clippedOutline); + + } + return &mClippedOutlineCache.clippedOutline; +} + } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h index c4ae82af430c..89e022f5e68d 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -365,6 +365,17 @@ public: return mSkiaLayer.get(); } + /** + * Returns the path that represents the outline of RenderNode intersected with + * the provided rect. This call will internally cache the resulting path in + * order to potentially return that path for subsequent calls to this method. + * By reusing the same path we get better performance on the GPU backends since + * those resources are cached in the hardware based on the path's genID. + * + * The returned path is only guaranteed to be valid until this function is called + * again or the RenderNode's outline is mutated. + */ + const SkPath* getClippedOutline(const SkRect& clipRect) const; private: /** * If this RenderNode has been used in a previous frame then the SkiaDisplayList @@ -380,6 +391,16 @@ private: * when it has been set to draw as a LayerType::RenderLayer. */ std::unique_ptr<skiapipeline::SkiaLayer> mSkiaLayer; + + struct ClippedOutlineCache { + // keys + uint32_t outlineID = 0; + SkRect clipRect; + + // value + SkPath clippedOutline; + }; + mutable ClippedOutlineCache mClippedOutlineCache; }; // class RenderNode class MarkAndSweepRemoved : public TreeObserver { diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index d191b56768e8..1f5f733188de 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -85,7 +85,6 @@ void SkiaCanvas::reset(SkCanvas* skiaCanvas) { mCanvasWrapper.reset(); } mSaveStack.reset(nullptr); - mHighContrastText = false; } // ---------------------------------------------------------------------------- @@ -533,6 +532,9 @@ void SkiaCanvas::drawArc(float left, float top, float right, float bottom, void SkiaCanvas::drawPath(const SkPath& path, const SkPaint& paint) { if (CC_UNLIKELY(paint.nothingToDraw())) return; + if (CC_UNLIKELY(path.isEmpty() && (!path.isInverseFillType()))) { + return; + } mCanvas->drawPath(path, paint); } @@ -597,7 +599,8 @@ void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, SkPaint tmpPaint; sk_sp<SkColorFilter> colorFilter; sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); - mCanvas->drawImageRect(image, srcRect, dstRect, addFilter(paint, &tmpPaint, colorFilter)); + mCanvas->drawImageRect(image, srcRect, dstRect, addFilter(paint, &tmpPaint, colorFilter), + SkCanvas::kFast_SrcRectConstraint); } void SkiaCanvas::drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight, diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h index 6a01f964873b..e17f835031bb 100644 --- a/libs/hwui/SkiaCanvas.h +++ b/libs/hwui/SkiaCanvas.h @@ -65,11 +65,6 @@ public: virtual int width() override; virtual int height() override; - virtual void setHighContrastText(bool highContrastText) override { - mHighContrastText = highContrastText; - } - virtual bool isHighContrastText() override { return mHighContrastText; } - virtual int getSaveCount() const override; virtual int save(SaveFlags::Flags flags) override; virtual void restore() override; @@ -166,8 +161,6 @@ private: size_t clipIndex; }; - bool mHighContrastText = false; - const SaveRec* currentSaveRec() const; void recordPartialSave(SaveFlags::Flags flags); diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp index 16a19ca4d36a..ddddefac74b9 100644 --- a/libs/hwui/SkiaCanvasProxy.cpp +++ b/libs/hwui/SkiaCanvasProxy.cpp @@ -179,7 +179,7 @@ void SkiaCanvasProxy::onDrawImageLattice(const SkImage* image, const Lattice& la SkLatticeIter iter(lattice, dst); SkRect srcR, dstR; while (iter.next(&srcR, &dstR)) { - onDrawImageRect(image, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint); + onDrawImageRect(image, &srcR, dstR, paint, SkCanvas::kFast_SrcRectConstraint); } } @@ -452,7 +452,7 @@ void SkiaCanvasProxy::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScala break; } default: - SkFAIL("unhandled positioning mode"); + SK_ABORT("unhandled positioning mode"); } } } diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp index 8a1de02e6a0c..e0373cae9923 100644 --- a/libs/hwui/VectorDrawable.cpp +++ b/libs/hwui/VectorDrawable.cpp @@ -511,25 +511,19 @@ void Tree::updateCache(sp<skiapipeline::VectorDrawableAtlas>& atlas, GrContext* } } if (!canReuseSurface || mCache.dirty) { - draw(surface.get(), dst); + if (surface) { + Bitmap& bitmap = getBitmapUpdateIfDirty(); + SkBitmap skiaBitmap; + bitmap.getSkBitmap(&skiaBitmap); + if (!surface->getCanvas()->writePixels(skiaBitmap, dst.fLeft, dst.fTop)) { + ALOGD("VectorDrawable caching failed to efficiently upload"); + surface->getCanvas()->drawBitmap(skiaBitmap, dst.fLeft, dst.fTop); + } + } mCache.dirty = false; } } -void Tree::draw(SkSurface* surface, const SkRect& dst) { - if (surface) { - SkCanvas* canvas = surface->getCanvas(); - float scaleX = dst.width() / mProperties.getViewportWidth(); - float scaleY = dst.height() / mProperties.getViewportHeight(); - SkAutoCanvasRestore acr(canvas, true); - canvas->translate(dst.fLeft, dst.fTop); - canvas->clipRect(SkRect::MakeWH(dst.width(), dst.height())); - canvas->clear(SK_ColorTRANSPARENT); - canvas->scale(scaleX, scaleY); - mRootNode->draw(canvas, false); - } -} - void Tree::Cache::setAtlas(sp<skiapipeline::VectorDrawableAtlas> newAtlas, skiapipeline::AtlasKey newAtlasKey) { LOG_ALWAYS_FATAL_IF(newAtlasKey == INVALID_ATLAS_KEY); @@ -565,27 +559,20 @@ void Tree::draw(SkCanvas* canvas) { sk_sp<SkSurface> vdSurface = mCache.getSurface(&src); if (vdSurface) { canvas->drawImageRect(vdSurface->makeImageSnapshot().get(), src, - mutateProperties()->getBounds(), getPaint()); + mutateProperties()->getBounds(), getPaint(), SkCanvas::kFast_SrcRectConstraint); } else { // Handle the case when VectorDrawableAtlas has been destroyed, because of memory pressure. // We render the VD into a temporary standalone buffer and mark the frame as dirty. Next // frame will be cached into the atlas. + Bitmap& bitmap = getBitmapUpdateIfDirty(); + SkBitmap skiaBitmap; + bitmap.getSkBitmap(&skiaBitmap); + int scaledWidth = SkScalarCeilToInt(mProperties.getScaledWidth()); int scaledHeight = SkScalarCeilToInt(mProperties.getScaledHeight()); - SkRect src = SkRect::MakeWH(scaledWidth, scaledHeight); -#ifndef ANDROID_ENABLE_LINEAR_BLENDING - sk_sp<SkColorSpace> colorSpace = nullptr; -#else - sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeSRGB(); -#endif - SkImageInfo info = SkImageInfo::MakeN32(scaledWidth, scaledHeight, kPremul_SkAlphaType, - colorSpace); - sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(canvas->getGrContext(), - SkBudgeted::kYes, info); - draw(surface.get(), src); + canvas->drawBitmapRect(skiaBitmap, SkRect::MakeWH(scaledWidth, scaledHeight), + mutateProperties()->getBounds(), getPaint(), SkCanvas::kFast_SrcRectConstraint); mCache.clear(); - canvas->drawImageRect(surface->makeImageSnapshot().get(), mutateProperties()->getBounds(), - getPaint()); markDirty(); } } diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h index efbb695a14dd..10d3e05c067f 100644 --- a/libs/hwui/VectorDrawable.h +++ b/libs/hwui/VectorDrawable.h @@ -738,11 +738,6 @@ private: bool canReuseBitmap(Bitmap*, int width, int height); void updateBitmapCache(Bitmap& outCache, bool useStagingData); - /** - * Draws the root node into "surface" at a given "dst" position. - */ - void draw(SkSurface* surface, const SkRect& dst); - // Cap the bitmap size, such that it won't hurt the performance too much // and it won't crash due to a very large scale. // The drawable will look blurry above this size. diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h index 0b8155cc4887..fbd89606fc9d 100644 --- a/libs/hwui/hwui/Canvas.h +++ b/libs/hwui/hwui/Canvas.h @@ -20,6 +20,7 @@ #include <utils/Functor.h> #include "GlFunctorLifecycleListener.h" +#include "Properties.h" #include "utils/Macros.h" #include <androidfw/ResourceTypes.h> @@ -140,8 +141,7 @@ public: virtual uirenderer::DisplayList* finishRecording() = 0; virtual void insertReorderBarrier(bool enableReorder) = 0; - virtual void setHighContrastText(bool highContrastText) = 0; - virtual bool isHighContrastText() = 0; + bool isHighContrastText() const { return uirenderer::Properties::enableHighContrastText; } virtual void drawRoundRect(uirenderer::CanvasPropertyPrimitive* left, uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right, diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp index ba4e3a4df578..2b29542fb623 100644 --- a/libs/hwui/hwui/MinikinSkia.cpp +++ b/libs/hwui/hwui/MinikinSkia.cpp @@ -67,6 +67,17 @@ void MinikinFontSkia::GetBounds(minikin::MinikinRect* bounds, uint32_t glyph_id, bounds->mBottom = skBounds.fBottom; } +void MinikinFontSkia::GetFontExtent(minikin::MinikinExtent* extent, + const minikin::MinikinPaint& paint) const { + SkPaint skPaint; + MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint); + SkPaint::FontMetrics metrics; + skPaint.getFontMetrics(&metrics); + extent->ascent = metrics.fAscent; + extent->descent = metrics.fDescent; + extent->line_gap = metrics.fLeading; +} + SkTypeface *MinikinFontSkia::GetSkTypeface() const { return mTypeface.get(); } diff --git a/libs/hwui/hwui/MinikinSkia.h b/libs/hwui/hwui/MinikinSkia.h index 6c12485845fd..a19f4a769444 100644 --- a/libs/hwui/hwui/MinikinSkia.h +++ b/libs/hwui/hwui/MinikinSkia.h @@ -37,6 +37,9 @@ public: void GetBounds(minikin::MinikinRect* bounds, uint32_t glyph_id, const minikin::MinikinPaint &paint) const; + void GetFontExtent(minikin::MinikinExtent* extent, + const minikin::MinikinPaint &paint) const; + SkTypeface* GetSkTypeface() const; sk_sp<SkTypeface> RefSkTypeface() const; diff --git a/libs/hwui/hwui/MinikinUtils.cpp b/libs/hwui/hwui/MinikinUtils.cpp index 5e7f1cf2da1c..7da7f3876a3d 100644 --- a/libs/hwui/hwui/MinikinUtils.cpp +++ b/libs/hwui/hwui/MinikinUtils.cpp @@ -68,7 +68,8 @@ float MinikinUtils::measureText(const Paint* paint, int bidiFlags, const Typefac minikin::FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, paint, typeface); const Typeface* resolvedTypeface = Typeface::resolveDefault(typeface); return minikin::Layout::measureText(buf, start, count, bufSize, bidiFlags, minikinStyle, - minikinPaint, resolvedTypeface->fFontCollection, advances); + minikinPaint, resolvedTypeface->fFontCollection, advances, nullptr /* extent */, + nullptr /* overhangs */); } bool MinikinUtils::hasVariationSelector(const Typeface* typeface, uint32_t codepoint, uint32_t vs) { diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp index 374d364787de..c8207bc70dd4 100644 --- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp +++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp @@ -163,28 +163,22 @@ void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable* hwuiMatrix.copyTo(shadowMatrix); canvas->concat(shadowMatrix); - const SkPath* casterOutlinePath = casterProperties.getOutline().getPath(); - // holds temporary SkPath to store the result of intersections - SkPath tmpPath; - const SkPath* casterPath = casterOutlinePath; + // default the shadow-casting path to the outline of the caster + const SkPath* casterPath = casterProperties.getOutline().getPath(); + + // intersect the shadow-casting path with the clipBounds, if present + if (clippedToBounds && !casterClipRect.contains(casterPath->getBounds())) { + casterPath = caster->getRenderNode()->getClippedOutline(casterClipRect); + } - // TODO: In to following course of code that calculates the final shape, is there an optimal - // of doing the Op calculations? // intersect the shadow-casting path with the reveal, if present + SkPath tmpPath; // holds temporary SkPath to store the result of intersections if (revealClipPath) { Op(*casterPath, *revealClipPath, kIntersect_SkPathOp, &tmpPath); tmpPath.setIsVolatile(true); casterPath = &tmpPath; } - // intersect the shadow-casting path with the clipBounds, if present - if (clippedToBounds) { - SkPath clipBoundsPath; - clipBoundsPath.addRect(casterClipRect); - Op(*casterPath, clipBoundsPath, kIntersect_SkPathOp, &tmpPath); - tmpPath.setIsVolatile(true); - casterPath = &tmpPath; - } const Vector3 lightPos = SkiaPipeline::getLightCenter(); SkPoint3 skiaLightPos = SkPoint3::Make(lightPos.x, lightPos.y, lightPos.z); SkPoint3 zParams; diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp index df9409297ef7..9982a0cfe2bf 100644 --- a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp +++ b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp @@ -136,7 +136,8 @@ CopyResult SkiaOpenGLReadback::copyImageInto(EGLImageKHR eglImage, const Matrix4 SkPaint paint; paint.setBlendMode(SkBlendMode::kSrc); scaledSurface->getCanvas()->concat(textureMatrix); - scaledSurface->getCanvas()->drawImageRect(image, skiaSrcRect, skiaDestRect, &paint); + scaledSurface->getCanvas()->drawImageRect(image, skiaSrcRect, skiaDestRect, &paint, + SkCanvas::kFast_SrcRectConstraint); image = scaledSurface->makeImageSnapshot(); diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp index a8463ecc44d8..742f14d04db4 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp @@ -118,6 +118,8 @@ void SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers, return; } + ATRACE_FORMAT("drawLayer [%s] %.1f x %.1f", layerNode->getName(), bounds.width(), bounds.height()); + layerNode->getSkiaLayer()->hasRenderedSinceRepaint = false; layerCanvas->clear(SK_ColorTRANSPARENT); @@ -143,7 +145,6 @@ bool SkiaPipeline::createOrUpdateLayer(RenderNode* node, } SkSurfaceProps props(0, kUnknown_SkPixelGeometry); SkASSERT(mRenderThread.getGrContext() != nullptr); - // TODO: Handle wide color gamut requests node->setLayerSurface( SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), SkBudgeted::kYes, info, 0, &props)); @@ -194,10 +195,10 @@ void SkiaPipeline::renderVectorDrawableCache() { sp<VectorDrawableAtlas> atlas = mRenderThread.cacheManager().acquireVectorDrawableAtlas(); auto grContext = mRenderThread.getGrContext(); atlas->prepareForDraw(grContext); + ATRACE_NAME("Update VectorDrawables"); for (auto vd : mVectorDrawables) { vd->updateCache(atlas, grContext); } - grContext->flush(); mVectorDrawables.clear(); } } diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp index 4c1d67351161..0bdf15333647 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -203,7 +203,8 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop SkPaint tmpPaint; sk_sp<SkColorFilter> colorFilter; sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); - mRecorder.drawImageRect(image, srcRect, dstRect, bitmapPaint(paint, &tmpPaint, colorFilter)); + mRecorder.drawImageRect(image, srcRect, dstRect, bitmapPaint(paint, &tmpPaint, colorFilter), + SkCanvas::kFast_SrcRectConstraint); if (!bitmap.isImmutable() && image.get() && !image->unique() && !srcRect.isEmpty() && !dstRect.isEmpty()) { mDisplayList->mMutableImages.push_back(image.get()); diff --git a/libs/hwui/pipeline/skia/VectorDrawableAtlas.cpp b/libs/hwui/pipeline/skia/VectorDrawableAtlas.cpp index 437653a8dfa8..9c9e17d600bf 100644 --- a/libs/hwui/pipeline/skia/VectorDrawableAtlas.cpp +++ b/libs/hwui/pipeline/skia/VectorDrawableAtlas.cpp @@ -21,6 +21,7 @@ #include <cmath> #include "utils/TraceUtils.h" #include "renderthread/RenderProxy.h" +#include "renderthread/RenderThread.h" namespace android { namespace uirenderer { @@ -228,6 +229,15 @@ AtlasEntry VectorDrawableAtlas::getEntry(AtlasKey atlasKey) { void VectorDrawableAtlas::releaseEntry(AtlasKey atlasKey) { if (INVALID_ATLAS_KEY != atlasKey) { + if (!renderthread::RenderThread::isCurrent()) { + { + AutoMutex _lock(mReleaseKeyLock); + mKeysForRelease.push_back(atlasKey); + } + // invoke releaseEntry on the renderthread + renderthread::RenderProxy::releaseVDAtlasEntries(); + return; + } CacheEntry* entry = reinterpret_cast<CacheEntry*>(atlasKey); if (!entry->surface) { // Store freed atlas rectangles in "mFreeRects" and try to reuse them later, when atlas @@ -245,6 +255,14 @@ void VectorDrawableAtlas::releaseEntry(AtlasKey atlasKey) { } } +void VectorDrawableAtlas::delayedReleaseEntries() { + AutoMutex _lock(mReleaseKeyLock); + for (auto key : mKeysForRelease) { + releaseEntry(key); + } + mKeysForRelease.clear(); +} + sk_sp<SkSurface> VectorDrawableAtlas::createSurface(int width, int height, GrContext* context) { #ifndef ANDROID_ENABLE_LINEAR_BLENDING sk_sp<SkColorSpace> colorSpace = nullptr; @@ -252,7 +270,10 @@ sk_sp<SkSurface> VectorDrawableAtlas::createSurface(int width, int height, GrCon sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeSRGB(); #endif SkImageInfo info = SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType, colorSpace); - return SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info); + // This must have a top-left origin so that calls to surface->canvas->writePixels + // performs a basic texture upload instead of a more complex drawing operation + return SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0, + kTopLeft_GrSurfaceOrigin, nullptr); } void VectorDrawableAtlas::setStorageMode(StorageMode mode) { diff --git a/libs/hwui/pipeline/skia/VectorDrawableAtlas.h b/libs/hwui/pipeline/skia/VectorDrawableAtlas.h index 496c55742748..0683b3915850 100644 --- a/libs/hwui/pipeline/skia/VectorDrawableAtlas.h +++ b/libs/hwui/pipeline/skia/VectorDrawableAtlas.h @@ -20,6 +20,7 @@ #include <SkSurface.h> #include <utils/FatVector.h> #include <utils/RefBase.h> +#include <utils/Thread.h> #include <list> class GrRectanizer; @@ -103,12 +104,19 @@ public: /** * "releaseEntry" is invoked when a VectorDrawable is deleted. Passing a non-existing "atlasKey" - * is causing an undefined behaviour. + * is causing an undefined behaviour. This is the only function in the class that can be + * invoked from any thread. It will marshal internally to render thread if needed. */ void releaseEntry(AtlasKey atlasKey); void setStorageMode(StorageMode mode); + /** + * "delayedReleaseEntries" is indirectly invoked by "releaseEntry", when "releaseEntry" is + * invoked from a non render thread. + */ + void delayedReleaseEntries(); + private: struct CacheEntry { CacheEntry(const SkRect& newVDrect, const SkRect& newRect, @@ -182,6 +190,17 @@ private: */ StorageMode mStorageMode; + /** + * mKeysForRelease is used by releaseEntry implementation to pass atlas keys from an arbitrary + * calling thread to the render thread. + */ + std::vector<AtlasKey> mKeysForRelease; + + /** + * A lock used to protect access to mKeysForRelease. + */ + Mutex mReleaseKeyLock; + sk_sp<SkSurface> createSurface(int width, int height, GrContext* context); inline bool fitInAtlas(int width, int height) { diff --git a/libs/hwui/renderstate/Blend.cpp b/libs/hwui/renderstate/Blend.cpp index 8865c6efce8c..b1ca4a248a80 100644 --- a/libs/hwui/renderstate/Blend.cpp +++ b/libs/hwui/renderstate/Blend.cpp @@ -118,7 +118,7 @@ void Blend::getFactors(SkBlendMode mode, ModeOrderSwap modeUsage, GLenum* outSrc } void Blend::setFactors(GLenum srcMode, GLenum dstMode) { - if (srcMode == GL_ZERO && dstMode == GL_ZERO) { + if ((srcMode == GL_ZERO || srcMode == GL_ONE) && dstMode == GL_ZERO) { // disable blending if (mEnabled) { glDisable(GL_BLEND); diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp index ededffb0f4bb..5fc5cb275741 100644 --- a/libs/hwui/renderstate/RenderState.cpp +++ b/libs/hwui/renderstate/RenderState.cpp @@ -262,7 +262,8 @@ void RenderState::postDecStrong(VirtualLightRefBase* object) { // Render /////////////////////////////////////////////////////////////////////////////// -void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix) { +void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix, + bool overrideDisableBlending) { const Glop::Mesh& mesh = glop.mesh; const Glop::Mesh::Vertices& vertices = mesh.vertices; const Glop::Mesh::Indices& indices = mesh.indices; @@ -417,7 +418,11 @@ void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix) { // ------------------------------------ // ---------- GL state setup ---------- // ------------------------------------ - blend().setFactors(glop.blend.src, glop.blend.dst); + if (CC_UNLIKELY(overrideDisableBlending)) { + blend().setFactors(GL_ZERO, GL_ZERO); + } else { + blend().setFactors(glop.blend.src, glop.blend.dst); + } GL_CHECKPOINT(MODERATE); diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h index df81e864a0b5..315fa2db6878 100644 --- a/libs/hwui/renderstate/RenderState.h +++ b/libs/hwui/renderstate/RenderState.h @@ -106,7 +106,7 @@ public: // more thinking... void postDecStrong(VirtualLightRefBase* object); - void render(const Glop& glop, const Matrix4& orthoMatrix); + void render(const Glop& glop, const Matrix4& orthoMatrix, bool overrideDisableBlending); Blend& blend() { return *mBlend; } MeshState& meshState() { return *mMeshState; } diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp index 16d77364942e..87e5bfdc8ca5 100644 --- a/libs/hwui/renderthread/EglManager.cpp +++ b/libs/hwui/renderthread/EglManager.cpp @@ -138,7 +138,7 @@ void EglManager::initialize() { LOG_ALWAYS_FATAL_IF(!glInterface.get()); GrContextOptions options; - options.fGpuPathRenderers &= ~GrContextOptions::GpuPathRenderers::kDistanceField; + options.fDisableDistanceFieldPaths = true; mRenderThread.cacheManager().configureContext(&options); mRenderThread.setGrContext(GrContext::Create(GrBackend::kOpenGL_GrBackend, (GrBackendContext)glInterface.get(), options)); diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index 7fe966dde316..690474376bef 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -732,6 +732,18 @@ void RenderProxy::repackVectorDrawableAtlas() { thread.queue(task); } +CREATE_BRIDGE1(releaseVDAtlasEntries, RenderThread* thread) { + args->thread->cacheManager().acquireVectorDrawableAtlas()->delayedReleaseEntries(); + return nullptr; +} + +void RenderProxy::releaseVDAtlasEntries() { + RenderThread& thread = RenderThread::getInstance(); + SETUP_TASK(releaseVDAtlasEntries); + args->thread = &thread; + thread.queue(task); +} + void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) { void* retval; task->setReturnPtr(&retval); diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index 06eaebd066ee..9440b15f6062 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -143,6 +143,8 @@ public: static void repackVectorDrawableAtlas(); + static void releaseVDAtlasEntries(); + private: RenderThread& mRenderThread; CanvasContext* mContext; diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index 72a428f1c70c..51e937485fab 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -499,6 +499,10 @@ sk_sp<Bitmap> RenderThread::allocateHardwareBitmap(SkBitmap& skBitmap) { return nullptr; } +bool RenderThread::isCurrent() { + return gettid() == getInstance().getTid(); +} + } /* namespace renderthread */ } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h index bef47b3e27c5..30884b571b94 100644 --- a/libs/hwui/renderthread/RenderThread.h +++ b/libs/hwui/renderthread/RenderThread.h @@ -111,6 +111,14 @@ public: sk_sp<Bitmap> allocateHardwareBitmap(SkBitmap& skBitmap); void dumpGraphicsMemory(int fd); + /** + * isCurrent provides a way to query, if the caller is running on + * the render thread. + * + * @return true only if isCurrent is invoked from the render thread. + */ + static bool isCurrent(); + protected: virtual bool threadLoop() override; diff --git a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp index f166c5ceb974..3089447cbfc5 100644 --- a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp +++ b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp @@ -171,7 +171,6 @@ void BM_DisplayListCanvas_basicViewGroupDraw(benchmark::State& benchState) { while (benchState.KeepRunning()) { canvas->resetRecording(200, 200); - canvas->setHighContrastText(false); canvas->translate(0, 0); // mScrollX, mScrollY // Clip to padding diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp index d36bca031a87..c4e419591a4d 100644 --- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp +++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp @@ -822,8 +822,8 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, drawText) { } OPENGL_PIPELINE_TEST(RecordingCanvas, drawTextInHighContrast) { + Properties::enableHighContrastText = true; auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) { - canvas.setHighContrastText(true); Paint paint; paint.setColor(SK_ColorWHITE); paint.setAntiAlias(true); @@ -832,6 +832,7 @@ OPENGL_PIPELINE_TEST(RecordingCanvas, drawTextInHighContrast) { std::unique_ptr<uint16_t[]> dst = TestUtils::asciiToUtf16("HELLO"); canvas.drawText(dst.get(), 0, 5, 5, 25, 25, minikin::kBidi_Force_LTR, paint, NULL); }); + Properties::enableHighContrastText = false; int count = 0; playbackOps(*dl, [&count](const RecordedOp& op) { diff --git a/libs/incident/proto/android/privacy.proto b/libs/incident/proto/android/privacy.proto index ae5af0e4afa7..5fd75d6f2809 100644 --- a/libs/incident/proto/android/privacy.proto +++ b/libs/incident/proto/android/privacy.proto @@ -36,7 +36,7 @@ enum Destination { // off the device with an explicit user action. DEST_EXPLICIT = 1; - // Fields or messages annotated with DEST_LOCAL can be sent by + // Fields or messages annotated with DEST_AUTOMATIC can be sent by // automatic means, without per-sending user consent. The user // still must have previously accepted a consent to share this // information. @@ -47,8 +47,11 @@ enum Destination { message PrivacyFlags { optional Destination dest = 1 [ - default = DEST_LOCAL + default = DEST_EXPLICIT ]; + + // regex to filter pii sensitive info from a string field type + repeated string patterns = 2; } extend google.protobuf.FieldOptions { diff --git a/libs/incident/proto/android/section.proto b/libs/incident/proto/android/section.proto new file mode 100644 index 000000000000..d268cf4fc09a --- /dev/null +++ b/libs/incident/proto/android/section.proto @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto2"; + +option java_package = "android"; +option java_multiple_files = true; + +import "google/protobuf/descriptor.proto"; + +package android; + +// SectionType defines how incidentd gonna get the field's data +enum SectionType { + + // Default fields, not available in incidentd + SECTION_NONE = 0; + + // incidentd reads a file to get the data for annotated field + SECTION_FILE = 1; + + // incidentd executes the given command for annotated field + SECTION_COMMAND = 2; + + // incidentd calls dumpsys for annotated field + SECTION_DUMPSYS = 3; +} + +message SectionFlags { + optional SectionType type = 1 [default = SECTION_NONE]; + optional string args = 2; +} + +extend google.protobuf.FieldOptions { + // Flags for automatically section list generation + optional SectionFlags section = 155792027; +} diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java index f4039889aded..3b9a5de00707 100644 --- a/media/java/android/media/AudioAttributes.java +++ b/media/java/android/media/AudioAttributes.java @@ -842,8 +842,8 @@ public final class AudioAttributes implements Parcelable { @Override public String toString () { return new String("AudioAttributes:" - + " usage=" + mUsage - + " content=" + mContentType + + " usage=" + usageToString() + + " content=" + contentTypeToString() + " flags=0x" + Integer.toHexString(mFlags).toUpperCase() + " tags=" + mFormattedTags + " bundle=" + (mBundle == null ? "null" : mBundle.toString())); @@ -894,6 +894,19 @@ public final class AudioAttributes implements Parcelable { } } + /** @hide */ + public String contentTypeToString() { + switch(mContentType) { + case CONTENT_TYPE_UNKNOWN: + return new String("CONTENT_TYPE_UNKNOWN"); + case CONTENT_TYPE_SPEECH: return new String("CONTENT_TYPE_SPEECH"); + case CONTENT_TYPE_MUSIC: return new String("CONTENT_TYPE_MUSIC"); + case CONTENT_TYPE_MOVIE: return new String("CONTENT_TYPE_MOVIE"); + case CONTENT_TYPE_SONIFICATION: return new String("CONTENT_TYPE_SONIFICATION"); + default: return new String("unknown content type " + mContentType); + } + } + private static int usageForStreamType(int streamType) { switch(streamType) { case AudioSystem.STREAM_VOICE_CALL: diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 05be088fb2ac..157545746c21 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -16,12 +16,12 @@ package android.media; -import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; import android.app.NotificationManager; @@ -397,6 +397,19 @@ public class AudioManager { */ public static final int ADJUST_TOGGLE_MUTE = 101; + /** @hide */ + public static final String adjustToString(int adj) { + switch (adj) { + case ADJUST_RAISE: return "ADJUST_RAISE"; + case ADJUST_LOWER: return "ADJUST_LOWER"; + case ADJUST_SAME: return "ADJUST_SAME"; + case ADJUST_MUTE: return "ADJUST_MUTE"; + case ADJUST_UNMUTE: return "ADJUST_UNMUTE"; + case ADJUST_TOGGLE_MUTE: return "ADJUST_TOGGLE_MUTE"; + default: return new StringBuilder("unknown adjust mode ").append(adj).toString(); + } + } + // Flags should be powers of 2! /** @@ -1235,7 +1248,7 @@ public class AudioManager { //==================================================================== // Bluetooth SCO control /** - * Sticky broadcast intent action indicating that the bluetoooth SCO audio + * Sticky broadcast intent action indicating that the Bluetooth SCO audio * connection state has changed. The intent contains on extra {@link #EXTRA_SCO_AUDIO_STATE} * indicating the new state which is either {@link #SCO_AUDIO_STATE_DISCONNECTED} * or {@link #SCO_AUDIO_STATE_CONNECTED} @@ -1249,7 +1262,7 @@ public class AudioManager { "android.media.SCO_AUDIO_STATE_CHANGED"; /** - * Sticky broadcast intent action indicating that the bluetoooth SCO audio + * Sticky broadcast intent action indicating that the Bluetooth SCO audio * connection state has been updated. * <p>This intent has two extras: * <ul> @@ -2364,8 +2377,8 @@ public class AudioManager { * usecases such as voice memo recording, or speech recognition. * Use {@link #AUDIOFOCUS_GAIN} for a focus request of unknown duration such * as the playback of a song or a video. - * @param flags 0 or a combination of {link #AUDIOFOCUS_FLAG_DELAY_OK} - * and {@link #AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS}. + * @param flags 0 or a combination of {link #AUDIOFOCUS_FLAG_DELAY_OK}, + * {@link #AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS} and {@link #AUDIOFOCUS_FLAG_LOCK}. * <br>Use 0 when not using any flags for the request, which behaves like * {@link #requestAudioFocus(OnAudioFocusChangeListener, int, int)}, where either audio * focus is granted immediately, or the grant request fails because the system is in a @@ -2377,6 +2390,7 @@ public class AudioManager { * @throws IllegalArgumentException */ @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int requestAudioFocus(OnAudioFocusChangeListener l, @NonNull AudioAttributes requestAttributes, int durationHint, @@ -2416,6 +2430,10 @@ public class AudioManager { * @deprecated use {@link #requestAudioFocus(AudioFocusRequest, AudioPolicy)} */ @SystemApi + @RequiresPermission(anyOf= { + android.Manifest.permission.MODIFY_PHONE_STATE, + android.Manifest.permission.MODIFY_AUDIO_ROUTING + }) public int requestAudioFocus(OnAudioFocusChangeListener l, @NonNull AudioAttributes requestAttributes, int durationHint, @@ -2474,6 +2492,7 @@ public class AudioManager { * @throws IllegalArgumentException when trying to lock focus without an AudioPolicy */ @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int requestAudioFocus(@NonNull AudioFocusRequest afr, @Nullable AudioPolicy ap) { if (afr == null) { throw new NullPointerException("Illegal null AudioFocusRequest"); @@ -2571,6 +2590,7 @@ public class AudioManager { * @throws NullPointerException if the {@link AudioFocusInfo} or {@link AudioPolicy} are null. */ @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int dispatchAudioFocusChange(@NonNull AudioFocusInfo afi, int focusChange, @NonNull AudioPolicy ap) { if (afi == null) { @@ -2622,6 +2642,8 @@ public class AudioManager { * @deprecated use {@link #abandonAudioFocusRequest(AudioFocusRequest)} */ @SystemApi + @SuppressLint("Doclava125") // no permission enforcement, but only "undoes" what would have been + // done by a matching requestAudioFocus public int abandonAudioFocus(OnAudioFocusChangeListener l, AudioAttributes aa) { int status = AUDIOFOCUS_REQUEST_FAILED; unregisterAudioFocusRequest(l); @@ -3833,6 +3855,7 @@ public class AudioManager { * @hide */ @SystemApi + @SuppressLint("Doclava125") // FIXME is this still used? public boolean isHdmiSystemAudioSupported() { try { return getService().isHdmiSystemAudioSupported(); diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index bfb81a0427c3..e56944dff782 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -113,6 +113,17 @@ public class AudioSystem public static final int MODE_IN_COMMUNICATION = 3; public static final int NUM_MODES = 4; + public static String modeToString(int mode) { + switch (mode) { + case MODE_CURRENT: return "MODE_CURRENT"; + case MODE_IN_CALL: return "MODE_IN_CALL"; + case MODE_IN_COMMUNICATION: return "MODE_IN_COMMUNICATION"; + case MODE_INVALID: return "MODE_INVALID"; + case MODE_NORMAL: return "MODE_NORMAL"; + case MODE_RINGTONE: return "MODE_RINGTONE"; + default: return "unknown mode (" + mode + ")"; + } + } /* Routing bits for the former setRouting/getRouting API */ /** @deprecated */ @@ -498,6 +509,14 @@ public class AudioSystem public static final int DEVICE_STATE_AVAILABLE = 1; private static final int NUM_DEVICE_STATES = 1; + public static String deviceStateToString(int state) { + switch (state) { + case DEVICE_STATE_UNAVAILABLE: return "DEVICE_STATE_UNAVAILABLE"; + case DEVICE_STATE_AVAILABLE: return "DEVICE_STATE_AVAILABLE"; + default: return "unknown state (" + state + ")"; + } + } + public static final String DEVICE_OUT_EARPIECE_NAME = "earpiece"; public static final String DEVICE_OUT_SPEAKER_NAME = "speaker"; public static final String DEVICE_OUT_WIRED_HEADSET_NAME = "headset"; @@ -693,6 +712,27 @@ public class AudioSystem public static final int NUM_FORCE_CONFIG = 15; public static final int FORCE_DEFAULT = FORCE_NONE; + public static String forceUseConfigToString(int config) { + switch (config) { + case FORCE_NONE: return "FORCE_NONE"; + case FORCE_SPEAKER: return "FORCE_SPEAKER"; + case FORCE_HEADPHONES: return "FORCE_HEADPHONES"; + case FORCE_BT_SCO: return "FORCE_BT_SCO"; + case FORCE_BT_A2DP: return "FORCE_BT_A2DP"; + case FORCE_WIRED_ACCESSORY: return "FORCE_WIRED_ACCESSORY"; + case FORCE_BT_CAR_DOCK: return "FORCE_BT_CAR_DOCK"; + case FORCE_BT_DESK_DOCK: return "FORCE_BT_DESK_DOCK"; + case FORCE_ANALOG_DOCK: return "FORCE_ANALOG_DOCK"; + case FORCE_DIGITAL_DOCK: return "FORCE_DIGITAL_DOCK"; + case FORCE_NO_BT_A2DP: return "FORCE_NO_BT_A2DP"; + case FORCE_SYSTEM_ENFORCED: return "FORCE_SYSTEM_ENFORCED"; + case FORCE_HDMI_SYSTEM_AUDIO_ENFORCED: return "FORCE_HDMI_SYSTEM_AUDIO_ENFORCED"; + case FORCE_ENCODED_SURROUND_NEVER: return "FORCE_ENCODED_SURROUND_NEVER"; + case FORCE_ENCODED_SURROUND_ALWAYS: return "FORCE_ENCODED_SURROUND_ALWAYS"; + default: return "unknown config (" + config + ")" ; + } + } + // usage for setForceUse, must match audio_policy_force_use_t public static final int FOR_COMMUNICATION = 0; public static final int FOR_MEDIA = 1; @@ -703,6 +743,19 @@ public class AudioSystem public static final int FOR_ENCODED_SURROUND = 6; private static final int NUM_FORCE_USE = 7; + public static String forceUseUsageToString(int usage) { + switch (usage) { + case FOR_COMMUNICATION: return "FOR_COMMUNICATION"; + case FOR_MEDIA: return "FOR_MEDIA"; + case FOR_RECORD: return "FOR_RECORD"; + case FOR_DOCK: return "FOR_DOCK"; + case FOR_SYSTEM: return "FOR_SYSTEM"; + case FOR_HDMI_SYSTEM_AUDIO: return "FOR_HDMI_SYSTEM_AUDIO"; + case FOR_ENCODED_SURROUND: return "FOR_ENCODED_SURROUND"; + default: return "unknown usage (" + usage + ")" ; + } + } + // usage for AudioRecord.startRecordingSync(), must match AudioSystem::sync_event_t public static final int SYNC_EVENT_NONE = 0; public static final int SYNC_EVENT_PRESENTATION_COMPLETE = 1; diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java index 4c3e261242eb..1f5edfa07c66 100644 --- a/media/java/android/media/ExifInterface.java +++ b/media/java/android/media/ExifInterface.java @@ -442,6 +442,10 @@ public class ExifInterface { private static final int RAF_INFO_SIZE = 160; private static final int RAF_JPEG_LENGTH_VALUE_SIZE = 4; + private static final byte[] HEIF_TYPE_FTYP = new byte[] {'f', 't', 'y', 'p'}; + private static final byte[] HEIF_BRAND_MIF1 = new byte[] {'m', 'i', 'f', '1'}; + private static final byte[] HEIF_BRAND_HEIC = new byte[] {'h', 'e', 'i', 'c'}; + // See http://fileformats.archiveteam.org/wiki/Olympus_ORF private static final short ORF_SIGNATURE_1 = 0x4f52; private static final short ORF_SIGNATURE_2 = 0x5352; @@ -1264,6 +1268,7 @@ public class ExifInterface { private static final int IMAGE_TYPE_RAF = 9; private static final int IMAGE_TYPE_RW2 = 10; private static final int IMAGE_TYPE_SRW = 11; + private static final int IMAGE_TYPE_HEIF = 12; static { sFormatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss"); @@ -1691,6 +1696,10 @@ public class ExifInterface { getRafAttributes(inputStream); break; } + case IMAGE_TYPE_HEIF: { + getHeifAttributes(inputStream); + break; + } case IMAGE_TYPE_ORF: { getOrfAttributes(inputStream); break; @@ -2108,6 +2117,8 @@ public class ExifInterface { return IMAGE_TYPE_JPEG; } else if (isRafFormat(signatureCheckBytes)) { return IMAGE_TYPE_RAF; + } else if (isHeifFormat(signatureCheckBytes)) { + return IMAGE_TYPE_HEIF; } else if (isOrfFormat(signatureCheckBytes)) { return IMAGE_TYPE_ORF; } else if (isRw2Format(signatureCheckBytes)) { @@ -2146,6 +2157,78 @@ public class ExifInterface { return true; } + private boolean isHeifFormat(byte[] signatureCheckBytes) throws IOException { + ByteOrderedDataInputStream signatureInputStream = null; + try { + signatureInputStream = new ByteOrderedDataInputStream(signatureCheckBytes); + signatureInputStream.setByteOrder(ByteOrder.BIG_ENDIAN); + + long chunkSize = signatureInputStream.readInt(); + byte[] chunkType = new byte[4]; + signatureInputStream.read(chunkType); + + if (!Arrays.equals(chunkType, HEIF_TYPE_FTYP)) { + return false; + } + + long chunkDataOffset = 8; + if (chunkSize == 1) { + // This indicates that the next 8 bytes represent the chunk size, + // and chunk data comes after that. + chunkSize = signatureInputStream.readLong(); + if (chunkSize < 16) { + // The smallest valid chunk is 16 bytes long in this case. + return false; + } + chunkDataOffset += 8; + } + + // only sniff up to signatureCheckBytes.length + if (chunkSize > signatureCheckBytes.length) { + chunkSize = signatureCheckBytes.length; + } + + long chunkDataSize = chunkSize - chunkDataOffset; + + // It should at least have major brand (4-byte) and minor version (4-byte). + // The rest of the chunk (if any) is a list of (4-byte) compatible brands. + if (chunkDataSize < 8) { + return false; + } + + byte[] brand = new byte[4]; + boolean isMif1 = false; + boolean isHeic = false; + for (long i = 0; i < chunkDataSize / 4; ++i) { + if (signatureInputStream.read(brand) != brand.length) { + return false; + } + if (i == 1) { + // Skip this index, it refers to the minorVersion, not a brand. + continue; + } + if (Arrays.equals(brand, HEIF_BRAND_MIF1)) { + isMif1 = true; + } else if (Arrays.equals(brand, HEIF_BRAND_HEIC)) { + isHeic = true; + } + if (isMif1 && isHeic) { + return true; + } + } + } catch (Exception e) { + if (DEBUG) { + Log.d(TAG, "Exception parsing HEIF file type box.", e); + } + } finally { + if (signatureInputStream != null) { + signatureInputStream.close(); + signatureInputStream = null; + } + } + return false; + } + /** * ORF has a similar structure to TIFF but it contains a different signature at the TIFF Header. * This method looks at the 2 bytes following the Byte Order bytes to determine if this file is @@ -2438,6 +2521,101 @@ public class ExifInterface { } } + private void getHeifAttributes(ByteOrderedDataInputStream in) throws IOException { + MediaMetadataRetriever retriever = new MediaMetadataRetriever(); + try { + if (mSeekableFileDescriptor != null) { + retriever.setDataSource(mSeekableFileDescriptor); + } else { + retriever.setDataSource(new MediaDataSource() { + long mPosition; + + @Override + public void close() throws IOException {} + + @Override + public int readAt(long position, byte[] buffer, int offset, int size) + throws IOException { + if (size == 0) { + return 0; + } + if (position < 0) { + return -1; + } + if (mPosition != position) { + in.seek(position); + mPosition = position; + } + + int bytesRead = in.read(buffer, offset, size); + if (bytesRead < 0) { + mPosition = -1; // need to seek on next read + return -1; + } + + mPosition += bytesRead; + return bytesRead; + } + + @Override + public long getSize() throws IOException { + return -1; + } + }); + } + + String hasVideo = retriever.extractMetadata( + MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO); + + final String METADATA_HAS_VIDEO_VALUE_YES = "yes"; + if (METADATA_HAS_VIDEO_VALUE_YES.equals(hasVideo)) { + String width = retriever.extractMetadata( + MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH); + String height = retriever.extractMetadata( + MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT); + + if (width != null) { + mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH, + ExifAttribute.createUShort(Integer.parseInt(width), mExifByteOrder)); + } + + if (height != null) { + mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH, + ExifAttribute.createUShort(Integer.parseInt(height), mExifByteOrder)); + } + + // Note that the rotation angle from MediaMetadataRetriever for heif images + // are CCW, while rotation in ExifInterface orientations are CW. + String rotation = retriever.extractMetadata( + MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION); + if (rotation != null) { + int orientation = ExifInterface.ORIENTATION_NORMAL; + + switch (Integer.parseInt(rotation)) { + case 90: + orientation = ExifInterface.ORIENTATION_ROTATE_270; + break; + case 180: + orientation = ExifInterface.ORIENTATION_ROTATE_180; + break; + case 270: + orientation = ExifInterface.ORIENTATION_ROTATE_90; + break; + } + + mAttributes[IFD_TYPE_PRIMARY].put(TAG_ORIENTATION, + ExifAttribute.createUShort(orientation, mExifByteOrder)); + } + + if (DEBUG) { + Log.d(TAG, "Heif meta: " + width + "x" + height + ", rotation " + rotation); + } + } + } finally { + retriever.release(); + } + } + /** * ORF files contains a primary image data and a MakerNote data that contains preview/thumbnail * images. Both data takes the form of IFDs and can therefore be read with the @@ -2678,7 +2856,7 @@ public class ExifInterface { } if (getAttribute(TAG_ORIENTATION) == null) { mAttributes[IFD_TYPE_PRIMARY].put(TAG_ORIENTATION, - ExifAttribute.createULong(0, mExifByteOrder)); + ExifAttribute.createUShort(0, mExifByteOrder)); } if (getAttribute(TAG_LIGHT_SOURCE) == null) { mAttributes[IFD_TYPE_EXIF].put(TAG_LIGHT_SOURCE, diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 9c138e30e929..bb6ae9863d31 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -201,5 +201,7 @@ interface IAudioService { int dispatchFocusChange(in AudioFocusInfo afi, in int focusChange, in IAudioPolicyCallback pcb); + oneway void playerHasOpPlayAudio(in int piid, in boolean hasOpPlayAudio); + // WARNING: read warning at top of file, it is recommended to add new methods at the end } diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl index 3308fc929b03..dc7fa8c00f82 100644 --- a/media/java/android/media/IMediaRouterService.aidl +++ b/media/java/android/media/IMediaRouterService.aidl @@ -28,6 +28,7 @@ interface IMediaRouterService { MediaRouterClientState getState(IMediaRouterClient client); boolean isPlaybackActive(IMediaRouterClient client); + boolean isGlobalBluetoothA2doOn(); void setDiscoveryRequest(IMediaRouterClient client, int routeTypes, boolean activeScan); void setSelectedRoute(IMediaRouterClient client, String routeId, boolean explicit); diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java index 3e75759bdfce..fbe55614db52 100644 --- a/media/java/android/media/Image.java +++ b/media/java/android/media/Image.java @@ -31,7 +31,7 @@ import android.graphics.Rect; * {@link java.nio.ByteBuffer ByteBuffers}. Each buffer is encapsulated in a * {@link Plane} that describes the layout of the pixel data in that plane. Due * to this direct access, and unlike the {@link android.graphics.Bitmap Bitmap} class, - * Images are not directly usable as as UI resources.</p> + * Images are not directly usable as UI resources.</p> * * <p>Since Images are often directly produced or consumed by hardware * components, they are a limited resource shared across the system, and should diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index bf18a7d291a6..f85925d8d867 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -2095,6 +2095,7 @@ public final class MediaCodecInfo { errors |= ERROR_UNRECOGNIZED; } switch (profileLevel.profile) { + case CodecProfileLevel.AVCProfileConstrainedHigh: case CodecProfileLevel.AVCProfileHigh: BR *= 1250; break; case CodecProfileLevel.AVCProfileHigh10: @@ -2107,6 +2108,7 @@ public final class MediaCodecInfo { errors |= ERROR_UNSUPPORTED; supported = false; // fall through - treat as base profile + case CodecProfileLevel.AVCProfileConstrainedBaseline: case CodecProfileLevel.AVCProfileBaseline: case CodecProfileLevel.AVCProfileMain: BR *= 1000; break; diff --git a/media/java/android/media/MediaDescription.java b/media/java/android/media/MediaDescription.java index 14485d3c43a3..e6aea99ef50b 100644 --- a/media/java/android/media/MediaDescription.java +++ b/media/java/android/media/MediaDescription.java @@ -220,6 +220,33 @@ public class MediaDescription implements Parcelable { } @Override + public boolean equals(Object o) { + if (o == null) { + return false; + } + + if (!(o instanceof MediaDescription)){ + return false; + } + + final MediaDescription d = (MediaDescription) o; + + if (!String.valueOf(mTitle).equals(String.valueOf(d.mTitle))) { + return false; + } + + if (!String.valueOf(mSubtitle).equals(String.valueOf(d.mSubtitle))) { + return false; + } + + if (!String.valueOf(mDescription).equals(String.valueOf(d.mDescription))) { + return false; + } + + return true; + } + + @Override public String toString() { return mTitle + ", " + mSubtitle + ", " + mDescription; } diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java index 2f48ffbfdb5c..35937de287a3 100644 --- a/media/java/android/media/MediaFile.java +++ b/media/java/android/media/MediaFile.java @@ -80,8 +80,9 @@ public class MediaFile { public static final int FILE_TYPE_BMP = 34; public static final int FILE_TYPE_WBMP = 35; public static final int FILE_TYPE_WEBP = 36; + public static final int FILE_TYPE_HEIF = 37; private static final int FIRST_IMAGE_FILE_TYPE = FILE_TYPE_JPEG; - private static final int LAST_IMAGE_FILE_TYPE = FILE_TYPE_WEBP; + private static final int LAST_IMAGE_FILE_TYPE = FILE_TYPE_HEIF; // Raw image file types public static final int FILE_TYPE_DNG = 300; @@ -239,6 +240,8 @@ public class MediaFile { addFileType("BMP", FILE_TYPE_BMP, "image/x-ms-bmp", MtpConstants.FORMAT_BMP, true); addFileType("WBMP", FILE_TYPE_WBMP, "image/vnd.wap.wbmp", MtpConstants.FORMAT_DEFINED, false); addFileType("WEBP", FILE_TYPE_WEBP, "image/webp", MtpConstants.FORMAT_DEFINED, false); + addFileType("HEIC", FILE_TYPE_HEIF, "image/heif", MtpConstants.FORMAT_HEIF, true); + addFileType("HEIF", FILE_TYPE_HEIF, "image/heif", MtpConstants.FORMAT_HEIF, false); addFileType("DNG", FILE_TYPE_DNG, "image/x-adobe-dng", MtpConstants.FORMAT_DNG, true); addFileType("CR2", FILE_TYPE_CR2, "image/x-canon-cr2", MtpConstants.FORMAT_TIFF, false); @@ -267,7 +270,7 @@ public class MediaFile { addFileType("PDF", FILE_TYPE_PDF, "application/pdf"); addFileType("DOC", FILE_TYPE_MS_WORD, "application/msword", MtpConstants.FORMAT_MS_WORD_DOCUMENT, true); addFileType("XLS", FILE_TYPE_MS_EXCEL, "application/vnd.ms-excel", MtpConstants.FORMAT_MS_EXCEL_SPREADSHEET, true); - addFileType("PPT", FILE_TYPE_MS_POWERPOINT, "application/mspowerpoint", MtpConstants.FORMAT_MS_POWERPOINT_PRESENTATION, true); + addFileType("PPT", FILE_TYPE_MS_POWERPOINT, "application/vnd.ms-powerpoint", MtpConstants.FORMAT_MS_POWERPOINT_PRESENTATION, true); addFileType("FLAC", FILE_TYPE_FLAC, "audio/flac", MtpConstants.FORMAT_FLAC, true); addFileType("ZIP", FILE_TYPE_ZIP, "application/zip"); addFileType("MPG", FILE_TYPE_MP2PS, "video/mp2p"); diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 5a16c36545c8..0d99473c69b9 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -3408,7 +3408,7 @@ public class MediaPlayer extends PlayerBase private static void postEventFromNative(Object mediaplayer_ref, int what, int arg1, int arg2, Object obj) { - MediaPlayer mp = (MediaPlayer)((WeakReference)mediaplayer_ref).get(); + final MediaPlayer mp = (MediaPlayer)((WeakReference)mediaplayer_ref).get(); if (mp == null) { return; } @@ -3416,8 +3416,14 @@ public class MediaPlayer extends PlayerBase switch (what) { case MEDIA_INFO: if (arg1 == MEDIA_INFO_STARTED_AS_NEXT) { - // this acquires the wakelock if needed, and sets the client side state - mp.start(); + new Thread(new Runnable() { + @Override + public void run() { + // this acquires the wakelock if needed, and sets the client side state + mp.start(); + } + }).start(); + Thread.yield(); } break; diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java index 29b88a28294c..2894e8956c1c 100644 --- a/media/java/android/media/MediaRouter.java +++ b/media/java/android/media/MediaRouter.java @@ -88,7 +88,6 @@ public class MediaRouter { RouteInfo mBluetoothA2dpRoute; RouteInfo mSelectedRoute; - RouteInfo mSystemAudioRoute; final boolean mCanConfigureWifiDisplays; boolean mActivelyScanningWifiDisplays; @@ -150,7 +149,6 @@ public class MediaRouter { } addRouteStatic(mDefaultAudioVideo); - mSystemAudioRoute = mDefaultAudioVideo; // This will select the active wifi display route if there is one. updateWifiDisplayStatus(mDisplayService.getWifiDisplayStatus()); @@ -185,7 +183,7 @@ public class MediaRouter { } void updateAudioRoutes(AudioRoutesInfo newRoutes) { - boolean updated = false; + boolean audioRoutesChanged = false; if (newRoutes.mainType != mCurAudioRoutesInfo.mainType) { mCurAudioRoutesInfo.mainType = newRoutes.mainType; int name; @@ -201,11 +199,10 @@ public class MediaRouter { } mDefaultAudioVideo.mNameResId = name; dispatchRouteChanged(mDefaultAudioVideo); - updated = true; + audioRoutesChanged = true; } final int mainType = mCurAudioRoutesInfo.mainType; - if (!TextUtils.equals(newRoutes.bluetoothName, mCurAudioRoutesInfo.bluetoothName)) { mCurAudioRoutesInfo.bluetoothName = newRoutes.bluetoothName; if (mCurAudioRoutesInfo.bluetoothName != null) { @@ -219,8 +216,6 @@ public class MediaRouter { info.mDeviceType = RouteInfo.DEVICE_TYPE_BLUETOOTH; mBluetoothA2dpRoute = info; addRouteStatic(mBluetoothA2dpRoute); - mSystemAudioRoute = mBluetoothA2dpRoute; - selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mSystemAudioRoute, false); } else { mBluetoothA2dpRoute.mName = mCurAudioRoutesInfo.bluetoothName; dispatchRouteChanged(mBluetoothA2dpRoute); @@ -229,30 +224,32 @@ public class MediaRouter { // BT disconnected removeRouteStatic(mBluetoothA2dpRoute); mBluetoothA2dpRoute = null; - mSystemAudioRoute = mDefaultAudioVideo; - selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mSystemAudioRoute, false); - } - updated = true; - } - - if (mBluetoothA2dpRoute != null) { - final boolean a2dpEnabled = isBluetoothA2dpOn(); - if (mSelectedRoute == mBluetoothA2dpRoute && !a2dpEnabled) { - // A2DP off - mSystemAudioRoute = mDefaultAudioVideo; - updated = true; - } else if ((mSelectedRoute == mDefaultAudioVideo || mSelectedRoute == null) && - a2dpEnabled) { - // A2DP on or BT connected - mSystemAudioRoute = mBluetoothA2dpRoute; - updated = true; } + audioRoutesChanged = true; } - if (updated) { + + if (audioRoutesChanged) { + selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, getDefaultSystemAudioRoute(), false); Log.v(TAG, "Audio routes updated: " + newRoutes + ", a2dp=" + isBluetoothA2dpOn()); } } + RouteInfo getDefaultSystemAudioRoute() { + boolean globalBluetoothA2doOn = false; + try { + globalBluetoothA2doOn = mMediaRouterService.isGlobalBluetoothA2doOn(); + } catch (RemoteException ex) { + Log.e(TAG, "Unable to call isSystemBluetoothA2doOn.", ex); + } + return (globalBluetoothA2doOn && mBluetoothA2dpRoute != null) + ? mBluetoothA2dpRoute : mDefaultAudioVideo; + } + + RouteInfo getCurrentSystemAudioRoute() { + return (isBluetoothA2dpOn() && mBluetoothA2dpRoute != null) + ? mBluetoothA2dpRoute : mDefaultAudioVideo; + } + boolean isBluetoothA2dpOn() { try { return mAudioService.isBluetoothA2dpOn(); @@ -603,15 +600,13 @@ public class MediaRouter { @Override public void onRestoreRoute() { + // Skip restoring route if the selected route is not a system audio route, or + // MediaRouter is initializing. if ((mSelectedRoute != mDefaultAudioVideo && mSelectedRoute != mBluetoothA2dpRoute) - || mSelectedRoute == mSystemAudioRoute) { + || mSelectedRoute == null) { return; } - try { - sStatic.mAudioService.setBluetoothA2dpOn(mSelectedRoute == mBluetoothA2dpRoute); - } catch (RemoteException e) { - Log.e(TAG, "Error changing Bluetooth A2DP state", e); - } + mSelectedRoute.select(); } } } @@ -946,7 +941,7 @@ public class MediaRouter { boolean wasDefaultOrBluetoothRoute = (oldRoute == sStatic.mDefaultAudioVideo || oldRoute == sStatic.mBluetoothA2dpRoute); if (oldRoute == route - && (!wasDefaultOrBluetoothRoute || oldRoute == sStatic.mSystemAudioRoute)) { + && (!wasDefaultOrBluetoothRoute || route == sStatic.getCurrentSystemAudioRoute())) { return; } if (!route.matchesTypes(types)) { diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java index 9bd93aa31abf..4808d7a5aa6a 100644 --- a/media/java/android/media/PlayerBase.java +++ b/media/java/android/media/PlayerBase.java @@ -276,6 +276,7 @@ public abstract class PlayerBase { // volume used by the player try { if (oldHasAppOpsPlayAudio != mHasAppOpsPlayAudio) { + getService().playerHasOpPlayAudio(mPlayerIId, mHasAppOpsPlayAudio); if (mHasAppOpsPlayAudio) { if (DEBUG_APP_OPS) { Log.v(TAG, "updateAppOpsPlayAudio: unmuting player, vol=" + mLeftVolume diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java index 44bd252a349e..1291dfb59d2c 100644 --- a/media/java/android/media/session/MediaSession.java +++ b/media/java/android/media/session/MediaSession.java @@ -49,6 +49,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.util.List; +import java.util.Objects; /** * Allows interaction with media controllers, volume keys, media buttons, and @@ -1291,6 +1292,28 @@ public final class MediaSession { "Description=" + mDescription + ", Id=" + mId + " }"; } + + @Override + public boolean equals(Object o) { + if (o == null) { + return false; + } + + if (!(o instanceof QueueItem)) { + return false; + } + + final QueueItem item = (QueueItem) o; + if (mId != item.mId) { + return false; + } + + if (!Objects.equals(mDescription, item.mDescription)) { + return false; + } + + return true; + } } private static final class Command { diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java index 48fb5bffffd3..0f4609603eab 100644 --- a/media/java/android/media/tv/TvContract.java +++ b/media/java/android/media/tv/TvContract.java @@ -703,37 +703,37 @@ public final class TvContract { } /** - * Returns {@code true}, if {@code uri} is a channel URI. + * @return {@code true} if {@code uri} is a channel URI. */ - public static boolean isChannelUri(Uri uri) { + public static boolean isChannelUri(@NonNull Uri uri) { return isChannelUriForTunerInput(uri) || isChannelUriForPassthroughInput(uri); } /** - * Returns {@code true}, if {@code uri} is a channel URI for a tuner input. + * @return {@code true} if {@code uri} is a channel URI for a tuner input. */ - public static boolean isChannelUriForTunerInput(Uri uri) { + public static boolean isChannelUriForTunerInput(@NonNull Uri uri) { return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_CHANNEL); } /** - * Returns {@code true}, if {@code uri} is a channel URI for a pass-through input. + * @return {@code true} if {@code uri} is a channel URI for a pass-through input. */ - public static boolean isChannelUriForPassthroughInput(Uri uri) { + public static boolean isChannelUriForPassthroughInput(@NonNull Uri uri) { return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_PASSTHROUGH); } /** - * Returns {@code true}, if {@code uri} is a program URI. + * @return {@code true} if {@code uri} is a program URI. */ - public static boolean isProgramUri(Uri uri) { + public static boolean isProgramUri(@NonNull Uri uri) { return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_PROGRAM); } /** - * Returns {@code true}, if {@code uri} is a recorded program URI. + * @return {@code true} if {@code uri} is a recorded program URI. */ - public static boolean isRecordedProgramUri(Uri uri) { + public static boolean isRecordedProgramUri(@NonNull Uri uri) { return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_RECORDED_PROGRAM); } diff --git a/media/java/android/mtp/MtpConstants.java b/media/java/android/mtp/MtpConstants.java index 7d078d7a97cf..88e287e6264f 100644 --- a/media/java/android/mtp/MtpConstants.java +++ b/media/java/android/mtp/MtpConstants.java @@ -211,6 +211,8 @@ public final class MtpConstants { public static final int FORMAT_JPX = 0x3810; /** Format code for DNG files */ public static final int FORMAT_DNG = 0x3811; + /** Format code for HEIF files {@hide} */ + public static final int FORMAT_HEIF = 0x3812; /** Format code for firmware files */ public static final int FORMAT_UNDEFINED_FIRMWARE = 0xB802; /** Format code for Windows image files */ diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java index 698c9c96fe01..80fd5c03b929 100755 --- a/media/java/android/mtp/MtpDatabase.java +++ b/media/java/android/mtp/MtpDatabase.java @@ -52,6 +52,7 @@ import java.util.concurrent.atomic.AtomicBoolean; public class MtpDatabase implements AutoCloseable { private static final String TAG = "MtpDatabase"; + private final Context mUserContext; private final Context mContext; private final String mPackageName; private final ContentProviderClient mMediaProvider; @@ -159,13 +160,14 @@ public class MtpDatabase implements AutoCloseable { } }; - public MtpDatabase(Context context, String volumeName, String storagePath, + public MtpDatabase(Context context, Context userContext, String volumeName, String storagePath, String[] subDirectories) { native_setup(); mContext = context; + mUserContext = userContext; mPackageName = context.getPackageName(); - mMediaProvider = context.getContentResolver() + mMediaProvider = userContext.getContentResolver() .acquireContentProviderClient(MediaStore.AUTHORITY); mVolumeName = volumeName; mMediaStoragePath = storagePath; @@ -595,6 +597,7 @@ public class MtpDatabase implements AutoCloseable { MtpConstants.FORMAT_XML_DOCUMENT, MtpConstants.FORMAT_FLAC, MtpConstants.FORMAT_DNG, + MtpConstants.FORMAT_HEIF, }; } @@ -705,6 +708,7 @@ public class MtpDatabase implements AutoCloseable { case MtpConstants.FORMAT_PNG: case MtpConstants.FORMAT_BMP: case MtpConstants.FORMAT_DNG: + case MtpConstants.FORMAT_HEIF: return IMAGE_PROPERTIES; default: return FILE_PROPERTIES; @@ -1112,7 +1116,7 @@ public class MtpDatabase implements AutoCloseable { private void sessionEnded() { if (mDatabaseModified) { - mContext.sendBroadcast(new Intent(MediaStore.ACTION_MTP_SESSION_END)); + mUserContext.sendBroadcast(new Intent(MediaStore.ACTION_MTP_SESSION_END)); mDatabaseModified = false; } } diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp index cf4458a6fd49..5b874cd82678 100644 --- a/media/jni/android_mtp_MtpDatabase.cpp +++ b/media/jni/android_mtp_MtpDatabase.cpp @@ -849,6 +849,7 @@ MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle, // read EXIF data for thumbnail information switch (info.mFormat) { case MTP_FORMAT_EXIF_JPEG: + case MTP_FORMAT_HEIF: case MTP_FORMAT_JFIF: { ExifData *exifdata = exif_data_new_from_file(path); if (exifdata) { @@ -906,6 +907,7 @@ void* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) if (getObjectFilePath(handle, path, length, format) == MTP_RESPONSE_OK) { switch (format) { case MTP_FORMAT_EXIF_JPEG: + case MTP_FORMAT_HEIF: case MTP_FORMAT_JFIF: { ExifData *exifdata = exif_data_new_from_file(path); if (exifdata) { diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt index bbd27839d551..3d5ee39e37d3 100644 --- a/native/android/libandroid.map.txt +++ b/native/android/libandroid.map.txt @@ -208,11 +208,9 @@ LIBANDROID { ATrace_beginSection; # introduced=23 ATrace_endSection; # introduced=23 ATrace_isEnabled; # introduced=23 - android_getTtsEngine; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21 android_getaddrinfofornetwork; # introduced=23 android_setprocnetwork; # introduced=23 android_setsocknetwork; # introduced=23 - getTtsEngine; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21 local: *; }; diff --git a/packages/BackupRestoreConfirmation/res/values-hi/strings.xml b/packages/BackupRestoreConfirmation/res/values-hi/strings.xml index f758fa1c5495..06f9ebd2a506 100644 --- a/packages/BackupRestoreConfirmation/res/values-hi/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-hi/strings.xml @@ -18,19 +18,19 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="backup_confirm_title" msgid="827563724209303345">"पूर्ण सुरक्षा"</string> <string name="restore_confirm_title" msgid="5469365809567486602">"पूर्ण पुनर्स्थापना"</string> - <string name="backup_confirm_text" msgid="1878021282758896593">"कनेक्ट किए गए डेस्कटॉप कंप्यूटर से सभी डेटा के संपूर्ण सुरक्षा का अनुरोध किया गया है. क्या आप इसकी अनुमति देना चाहते हैं?\n\nयदि आपने स्वयं बैकअप का अनुरोध नहीं किया है, तो प्रक्रिया जारी रखने की अनुमति न दें."</string> + <string name="backup_confirm_text" msgid="1878021282758896593">"कनेक्ट किए गए डेस्कटॉप कंप्यूटर से पूरे डेटा के बैकअप का अनुरोध किया गया है. क्या आप इसकी अनुमति देना चाहते हैं?\n\nअगर आपने बैकअप का अनुरोध नहीं किया है, तो इस प्रक्रिया को जारी रखने की अनुमति न दें."</string> <string name="allow_backup_button_label" msgid="4217228747769644068">"मेरे डेटा का बैकअप लें"</string> <string name="deny_backup_button_label" msgid="6009119115581097708">"बैकअप न लें"</string> - <string name="restore_confirm_text" msgid="7499866728030461776">"कनेक्ट किए गए डेस्कटॉप कंप्यूटर से सभी डेटा की पूर्ण पुनर्स्थापना का अनुरोध किया गया है. क्या आप इसकी अनुमति देना चाहते हैं?\n\nयदि आपने स्वयं पुनर्प्राप्ति का अनुरोध नहीं किया है, तो प्रक्रिया जारी रखने की अनुमति न दें. इससे वर्तमान में आपके डिवाइस पर मौजूद डेटा बदल जाएगा!"</string> + <string name="restore_confirm_text" msgid="7499866728030461776">"कनेक्ट किए गए डेस्कटॉप कंप्यूटर से पूरे डेटा को बहाल करने का अनुरोध किया गया है. क्या आप इसकी अनुमति देना चाहते हैं?\n\nअगर आपने इसे बहाल करने का अनुरोध नहीं किया है, तो इस प्रक्रिया को जारी रखने की अनुमति न दें. इससे आपके डिवाइस पर इस वक्त जो भी डेटा मौजूद है वो बदल जाएगा!"</string> <string name="allow_restore_button_label" msgid="3081286752277127827">"मेरा डेटा पुनर्स्थापित करें"</string> <string name="deny_restore_button_label" msgid="1724367334453104378">"पुनर्स्थापित न करें"</string> <string name="current_password_text" msgid="8268189555578298067">"कृपया नीचे अपना वर्तमान सुरक्षित करने का पासवर्ड डालें:"</string> - <string name="device_encryption_restore_text" msgid="1570864916855208992">"कृपया नीचे अपना डिवाइस एन्क्रिप्शन पासवर्ड डालें."</string> + <string name="device_encryption_restore_text" msgid="1570864916855208992">"कृपया नीचे अपना डिवाइस सुरक्षित करने का पासवर्ड डालें."</string> <string name="device_encryption_backup_text" msgid="5866590762672844664">"कृपया अपना डिवाइस सुरक्षित तरीका पासवर्ड नीचे दर्ज करें. बैकअप मेमोरी को एन्क्रिप्ट करने के लिए भी इसका उपयोग किया जाएगा."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"कृपया संपूर्ण सुरक्षित डेटा को एन्क्रिप्ट करने में उपयोग के लिए पासवर्ड डालें. यदि यह खाली छोड़ दिया जाता है, तो आपके वर्तमान बैकअप पासवर्ड का उपयोग किया जाएगा:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"यदि आप संपूर्ण सुरक्षित डेटा को एन्क्रिप्ट करना चाहते हैं, तो नीचे पासवर्ड डालें:"</string> <string name="backup_enc_password_required" msgid="7889652203371654149">"चूंकि आपका डिवाइस एन्क्रिप्ट किया हुआ है, इसलिए आपको अपने बैकअप को एन्क्रिप्ट करना आवश्यक है. कृपया नीचे पासवर्ड डालें:"</string> - <string name="restore_enc_password_text" msgid="6140898525580710823">"यदि पुनर्स्थापित डेटा को एन्क्रिप्ट किया गया है, तो कृपया नीचे पासवर्ड डालें:"</string> + <string name="restore_enc_password_text" msgid="6140898525580710823">"अगर रिस्टोर किया गया डेटा सुरक्षित किया गया है, तो कृपया नीचे पासवर्ड डालें:"</string> <string name="toast_backup_started" msgid="550354281452756121">"सुरक्षित करना शुरु हो रहा है..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"सुरक्षित करना पूर्ण"</string> <string name="toast_restore_started" msgid="7881679218971277385">"पुनर्स्थापना प्रारंभ हो रही है..."</string> diff --git a/packages/BackupRestoreConfirmation/res/values-iw/strings.xml b/packages/BackupRestoreConfirmation/res/values-iw/strings.xml index 3ad7c96645eb..c060403c588e 100644 --- a/packages/BackupRestoreConfirmation/res/values-iw/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-iw/strings.xml @@ -21,7 +21,7 @@ <string name="backup_confirm_text" msgid="1878021282758896593">"הוגשה בקשה לגיבוי מלא של כל הנתונים במחשב שולחני מחובר. האם אתה רוצה לאפשר פעולה זו? \n\nאם לא ביקשת את הגיבוי בעצמך, אל תאפשר לפעולה להמשיך."</string> <string name="allow_backup_button_label" msgid="4217228747769644068">"גיבוי הנתונים שלי"</string> <string name="deny_backup_button_label" msgid="6009119115581097708">"אל תגבה"</string> - <string name="restore_confirm_text" msgid="7499866728030461776">"הוגשה בקשה לשחזור מלא של כל הנתונים ממחשב שולחני מחובר. האם אתה רוצה לאפשר פעולה זו? \n \n אם לא ביקשת את השחזור בעצמך, אל תאפשר לפעולה להמשיך. פעולה זו תחליף את כל הנתונים שנמצאים כעת במכשיר!"</string> + <string name="restore_confirm_text" msgid="7499866728030461776">"הוגשה בקשה לשחזור מלא של כל הנתונים ממחשב שולחני מחובר. האם ברצונך לאפשר פעולה זו? \n \n אם לא ביקשת את השחזור בעצמך, אל תאפשר לפעולה להמשיך. פעולה זו תחליף את כל הנתונים שנמצאים כעת במכשיר!"</string> <string name="allow_restore_button_label" msgid="3081286752277127827">"שחזר את הנתונים שלי"</string> <string name="deny_restore_button_label" msgid="1724367334453104378">"אל תשחזר"</string> <string name="current_password_text" msgid="8268189555578298067">"הזן את סיסמת הגיבוי הנוכחית למטה:"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-mr/strings.xml b/packages/BackupRestoreConfirmation/res/values-mr/strings.xml index f94ec4b1a027..ea3b2f05e8f3 100644 --- a/packages/BackupRestoreConfirmation/res/values-mr/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-mr/strings.xml @@ -18,19 +18,19 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="backup_confirm_title" msgid="827563724209303345">"पूर्ण बॅकअप"</string> <string name="restore_confirm_title" msgid="5469365809567486602">"पूर्ण पुनर्संचयन"</string> - <string name="backup_confirm_text" msgid="1878021282758896593">"कनेक्ट केलेल्या डेस्कटॉप संगणकावरील सर्व डेटाच्या पूर्ण बॅकअपची विनंती केली गेली आहे. आपण असे होण्यासाठी अनुमती देऊ इच्छिता?\n\nआपण स्वत: बॅकअपची विनंती केली नसल्यास, कार्य पुढे सुरु राहण्यास अनुमती देऊ नका."</string> + <string name="backup_confirm_text" msgid="1878021282758896593">"कनेक्ट केलेल्या डेस्कटॉप काँप्युटरवरील सर्व डेटाच्या पूर्ण बॅकअपची विनंती केली गेली आहे. आपण असे होण्यासाठी अनुमती देऊ इच्छिता?\n\nआपण स्वत: बॅकअपची विनंती केली नसल्यास, कार्य पुढे सुरु राहण्यास अनुमती देऊ नका."</string> <string name="allow_backup_button_label" msgid="4217228747769644068">"माझ्या डेटाचा बॅकअप घ्या"</string> <string name="deny_backup_button_label" msgid="6009119115581097708">"बॅकअप घेऊ नका"</string> - <string name="restore_confirm_text" msgid="7499866728030461776">"कनेक्ट केलेल्या डेस्कटॉप संगणकावरील सर्व डेटाच्या पूर्ण पुनर्संचयनाची विनंती केली गेली आहे. आपण असे होण्यासाठी अनुमती देऊ इच्छिता?\n\nआपण स्वत: पुनर्संचयनाची विनंती केली नसल्यास, कार्य पुढे सुरु राहण्यास अनुमती देऊ नका. हे आपल्या डिव्हाइसवरील कोणत्याही वर्तमान डेटास पुनर्स्थित करेल!"</string> + <string name="restore_confirm_text" msgid="7499866728030461776">"कनेक्ट केलेल्या डेस्कटॉप काँप्युटरवरील सर्व डेटाच्या पूर्ण पुनर्संचयनाची विनंती केली गेली आहे. आपण असे होण्यासाठी अनुमती देऊ इच्छिता?\n\nआपण स्वत: पुनर्संचयनाची विनंती केली नसल्यास, कार्य पुढे सुरु राहण्यास अनुमती देऊ नका. हे आपल्या डिव्हाइसवरील कोणत्याही वर्तमान डेटास पुनर्स्थित करेल!"</string> <string name="allow_restore_button_label" msgid="3081286752277127827">"माझा डेटा पुनर्संचयित करा"</string> <string name="deny_restore_button_label" msgid="1724367334453104378">"पुनर्संचयित करू नका"</string> <string name="current_password_text" msgid="8268189555578298067">"कृपया आपला वर्तमान बॅकअप संकेतशब्द खाली प्रविष्ट करा:"</string> <string name="device_encryption_restore_text" msgid="1570864916855208992">"कृपया तुमचे डीव्हाइस एंक्रिप्शन पासवर्ड खाली एंटर करा."</string> <string name="device_encryption_backup_text" msgid="5866590762672844664">"कृपया तुमचे डीव्हाइस एंक्रिप्शन पासवर्ड खाली एंटर करा. हा बॅकअप संग्रह एंक्रिप्ट करण्यासाठी देखील वापरला जाईल."</string> - <string name="backup_enc_password_text" msgid="4981585714795233099">"कृपया पूर्ण बॅकअप डेटा कूटबद्ध करण्यासाठी वापरण्याकरिता संकेतशब्द प्रविष्ट करा. हे रिक्त सोडल्यास, आपला वर्तमान बॅकअप संकेतशब्द वापरला जाईल:"</string> - <string name="backup_enc_password_optional" msgid="1350137345907579306">"आपण पूर्ण बॅकअप डेटा कूटबद्ध करू इच्छित असल्यास, खालील संकेतशब्द प्रविष्ट करा:"</string> + <string name="backup_enc_password_text" msgid="4981585714795233099">"कृपया पूर्ण बॅकअप डेटा एंक्रिप्ट करण्यासाठी वापरण्याकरिता पासवर्ड एंटर करा. हे रिक्त सोडल्यास, आपला वर्तमान बॅकअप पासवर्ड वापरला जाईल:"</string> + <string name="backup_enc_password_optional" msgid="1350137345907579306">"तुम्ही पूर्ण बॅकअप डेटा एंक्रिप्ट करू इच्छित असल्यास, खालील पासवर्ड एंटर करा:"</string> <string name="backup_enc_password_required" msgid="7889652203371654149">"तुमचे डीव्हाइस एंक्रिप्ट केले असल्यामुळे, तुम्हाला तुमचा बॅक अप एंक्रिप्ट करणे आवश्यक आहे. कृपया खाली एक पासवर्ड एंटर करा:"</string> - <string name="restore_enc_password_text" msgid="6140898525580710823">"पुनर्संचयित डेटा कूटबद्ध केला असल्यास, कृपया संकेतशब्द खाली प्रविष्ट करा:"</string> + <string name="restore_enc_password_text" msgid="6140898525580710823">"पुनर्स्टोअर केलेला डेटा एंक्रिप्ट केला असल्यास, कृपया पासवर्ड खाली एंटर करा:"</string> <string name="toast_backup_started" msgid="550354281452756121">"बॅकअप सुरू होत आहे..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"बॅकअप समाप्त झाले"</string> <string name="toast_restore_started" msgid="7881679218971277385">"पुनर्संचयन सुरू होत आहे..."</string> diff --git a/packages/CaptivePortalLogin/res/values-bn/strings.xml b/packages/CaptivePortalLogin/res/values-bn/strings.xml index c6a044d6af9a..886a667a6145 100644 --- a/packages/CaptivePortalLogin/res/values-bn/strings.xml +++ b/packages/CaptivePortalLogin/res/values-bn/strings.xml @@ -4,7 +4,7 @@ <string name="app_name" msgid="5934709770924185752">"CaptivePortalLogin"</string> <string name="action_use_network" msgid="6076184727448466030">"যেভাবে আছে সেভাবেই এই নেটওয়ার্ক ব্যবহার করুন"</string> <string name="action_do_not_use_network" msgid="4577366536956516683">"এই নেটওয়ার্ক ব্যবহার করবেন না"</string> - <string name="action_bar_label" msgid="917235635415966620">"নেটওয়ার্কে প্রবেশ করুন"</string> + <string name="action_bar_label" msgid="917235635415966620">"নেটওয়ার্কে সাইন-ইন করুন"</string> <string name="action_bar_title" msgid="5645564790486983117">"%1$s তে সাইন-ইন করুন"</string> <string name="ssl_error_warning" msgid="6653188881418638872">"আপনি যে নেটওয়ার্কে যোগ দেওয়ার চেষ্টা করছেন তাতে নিরাপত্তার সমস্যা আছে।"</string> <string name="ssl_error_example" msgid="647898534624078900">"উদাহরণস্বরূপ, লগইন পৃষ্ঠাটি প্রদর্শিত প্রতিষ্ঠানের অন্তর্গত নাও হতে পারে৷"</string> diff --git a/packages/CarrierDefaultApp/res/values-bn/strings.xml b/packages/CarrierDefaultApp/res/values-bn/strings.xml index 9a0f68c28b36..e69183906595 100644 --- a/packages/CarrierDefaultApp/res/values-bn/strings.xml +++ b/packages/CarrierDefaultApp/res/values-bn/strings.xml @@ -10,7 +10,7 @@ <string name="no_mobile_data_connection_title" msgid="7449525772416200578">"কোনও মোবাইল ডেটা সংযোগ নেই"</string> <string name="no_mobile_data_connection" msgid="544980465184147010">"%s এর মাধ্যমে ডেটা অথবা রোমিং পরিকল্পনা যোগ করুন"</string> <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"মোবাইল ডেটার স্ট্যাটাস"</string> - <string name="action_bar_label" msgid="4290345990334377177">"মোবাইল নেটওয়ার্কে প্রবেশ করুন"</string> + <string name="action_bar_label" msgid="4290345990334377177">"মোবাইল নেটওয়ার্কে সাইন-ইন করুন"</string> <string name="ssl_error_warning" msgid="3127935140338254180">"আপনি যে নেটওয়ার্কে যোগ দেওয়ার চেষ্টা করছেন সেটিতে নিরাপত্তাজনিত সমস্যা আছে।"</string> <string name="ssl_error_example" msgid="6188711843183058764">"যেমন, লগইন পৃষ্ঠাটি যে প্রতিষ্ঠানের পৃষ্ঠা বলে দেখানো আছে, আসলে তা নাও হতে পারে৷"</string> <string name="ssl_error_continue" msgid="1138548463994095584">"যাই হোক, ব্রাউজারের মাধ্যমে চালিয়ে যান"</string> diff --git a/packages/CarrierDefaultApp/res/values-pa/strings.xml b/packages/CarrierDefaultApp/res/values-pa/strings.xml index 4f77b5d27214..df052af8b487 100644 --- a/packages/CarrierDefaultApp/res/values-pa/strings.xml +++ b/packages/CarrierDefaultApp/res/values-pa/strings.xml @@ -3,13 +3,13 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_name" msgid="5247871339820894594">"CarrierDefaultApp"</string> <string name="android_system_label" msgid="2797790869522345065">"ਮੋਬਾਈਲ ਕੈਰੀਅਰ"</string> - <string name="portal_notification_id" msgid="5155057562457079297">"ਮੋਬਾਈਲ ਡੈਟਾ ਖਤਮ ਹੋ ਗਿਆ ਹੈ"</string> - <string name="no_data_notification_id" msgid="668400731803969521">"ਤੁਹਾਡਾ ਮੋਬਾਈਲ ਡੈਟਾ ਅਕਿਰਿਆਸ਼ੀਲ ਕਰ ਦਿੱਤਾ ਗਿਆ ਹੈ"</string> + <string name="portal_notification_id" msgid="5155057562457079297">"ਮੋਬਾਈਲ ਡਾਟਾ ਖਤਮ ਹੋ ਗਿਆ ਹੈ"</string> + <string name="no_data_notification_id" msgid="668400731803969521">"ਤੁਹਾਡਾ ਮੋਬਾਈਲ ਡਾਟਾ ਅਕਿਰਿਆਸ਼ੀਲ ਕਰ ਦਿੱਤਾ ਗਿਆ ਹੈ"</string> <string name="portal_notification_detail" msgid="2295729385924660881">"%s ਵੈੱਬਸਾਈਟ \'ਤੇ ਜਾਣ ਲਈ ਟੈਪ ਕਰੋ"</string> <string name="no_data_notification_detail" msgid="3112125343857014825">"ਕਿਰਪਾ ਕਰਕੇ ਆਪਣੇ ਸੇਵਾ ਪ੍ਰਦਾਨਕ %s ਨੂੰ ਸੰਪਰਕ ਕਰੋ"</string> <string name="no_mobile_data_connection_title" msgid="7449525772416200578">"ਕੋਈ ਮੋਬਾਈਲ ਡਾਟਾ ਕਨੈਕਸ਼ਨ ਨਹੀਂ"</string> <string name="no_mobile_data_connection" msgid="544980465184147010">"%s ਰਾਹੀਂ ਡੈਟਾ ਜਾਂ ਰੋਮਿੰਗ ਯੋਜਨਾ ਸ਼ਾਮਲ ਕਰੋ"</string> - <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"ਮੋਬਾਈਲ ਡੈਟੇ ਦੀ ਅਵਸਥਾ"</string> + <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"ਮੋਬਾਈਲ ਡਾਟੇ ਦੀ ਸਥਿਤੀ"</string> <string name="action_bar_label" msgid="4290345990334377177">"ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਵਿੱਚ ਸਾਈਨ-ਇਨ ਕਰੋ"</string> <string name="ssl_error_warning" msgid="3127935140338254180">"ਤੁਸੀਂ ਜਿਸ ਨੈੱਟਵਰਕ ਵਿੱਚ ਸ਼ਾਮਲ ਹੋਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰ ਰਹੇ ਹੋ ਉਸ ਵਿੱਚ ਸੁਰੱਖਿਆ ਸਬੰਧੀ ਸਮੱਸਿਆਵਾਂ ਹਨ।"</string> <string name="ssl_error_example" msgid="6188711843183058764">"ਉਦਾਹਰਣ ਵਜੋਂ, ਹੋ ਸਕਦਾ ਹੈ ਲੌਗਇਨ ਪੰਨਾ ਦਿਖਾਈ ਗਈ ਸੰਸਥਾ ਨਾਲ ਸਬੰਧਿਤ ਨਾ ਹੋਵੇ।"</string> diff --git a/packages/DefaultContainerService/res/values-te/strings.xml b/packages/DefaultContainerService/res/values-te/strings.xml index 58671eae2581..5be53e5409e6 100644 --- a/packages/DefaultContainerService/res/values-te/strings.xml +++ b/packages/DefaultContainerService/res/values-te/strings.xml @@ -20,5 +20,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="service_name" msgid="4841491635055379553">"ప్యాకేజీ ప్రాప్యత సహాయకం"</string> + <string name="service_name" msgid="4841491635055379553">"ప్యాకేజీ యాక్సెస్ సహాయకం"</string> </resources> diff --git a/packages/InputDevices/res/raw/keyboard_layout_persian.kcm b/packages/InputDevices/res/raw/keyboard_layout_persian.kcm new file mode 100644 index 000000000000..e7dd6c6d68c8 --- /dev/null +++ b/packages/InputDevices/res/raw/keyboard_layout_persian.kcm @@ -0,0 +1,501 @@ +# Copyright (C) 2017 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + + +type FULL + +### Basic QWERTY keys ### + +key A { + label: '\u0634' + base: '\u0634' + shift, capslock: '\u0624' + ctrl, alt, meta: none +} + +key B { + label: '\u0630' + base: '\u0630' + shift, capslock: '\u200C' + ctrl, alt, meta: none +} + +key C { + label: '\u0632' + base: '\u0632' + shift, capslock: '\u0698' + ctrl, alt, meta: none +} + +key D { + label: '\u06CC' + base: '\u06CC' + shift, capslock: '\u064A' + ctrl, alt, meta: none +} + +key E { + label: '\u062B' + base: '\u062B' + shift, capslock: '\u064D' + ctrl, alt, meta: none +} + +key F { + label: '\u0628' + base: '\u0628' + shift, capslock: '\u0625' + ctrl, alt, meta: none +} + +key G { + label: '\u0644' + base: '\u0644' + shift, capslock: '\u0623' + ctrl, alt, meta: none +} + +key H { + label: '\u0627' + base: '\u0627' + shift, capslock: '\u0622' + ctrl, alt, meta: none +} + +key I { + label: '\u0647' + base: '\u0647' + shift, capslock: '\u0651' + ctrl, alt, meta: none +} + +key J { + label: '\u062A' + base: '\u062A' + shift, capslock: '\u0629' + ctrl, alt, meta: none +} + +key K { + label: '\u0646' + base: '\u0646' + shift, capslock: '\u00AB' + ctrl, alt, meta: none +} + +key L { + label: '\u0645' + base: '\u0645' + shift, capslock: '\u00BB' + ctrl, alt, meta: none +} + +key M { + label: '\u067E' + base: '\u067E' + shift, capslock: '\u0621' + ctrl, alt, meta: none +} + +key N { + label: '\u062F' + base: '\u062F' + shift, capslock: '\u0654' + ctrl, alt, meta: none +} + +key O { + label: '\u062E' + base: '\u062E' + shift, capslock: ']' + ctrl, alt, meta: none +} + +key P { + label: '\u062D' + base: '\u062D' + shift, capslock: '[' + ctrl, alt, meta: none +} + +key Q { + label: '\u0636' + base: '\u0636' + shift, capslock: '\u0652' + ctrl, alt, meta: none +} + +key R { + label: '\u0642' + base: '\u0642' + shift, capslock: '\u064B' + ctrl, alt, meta: none +} + +key S { + label: '\u0633' + base: '\u0633' + shift, capslock: '\u0626' + ctrl, alt, meta: none +} + +key T { + label: '\u0641' + base: '\u0641' + shift, capslock: '\u064F' + ctrl, alt, meta: none +} + +key U { + label: '\u0639' + base: '\u0639' + shift, capslock: '\u064E' + ctrl, alt, meta: none +} + +key V { + label: '\u0631' + base: '\u0631' + shift, capslock: '\u0670' + ctrl, alt, meta: none +} + +key W { + label: '\u0635' + base: '\u0635' + shift, capslock: '\u064C' + ctrl, alt, meta: none +} + +key X { + label: '\u0637' + base: '\u0637' + shift, capslock: '\u0653' + ctrl, alt, meta: none +} + +key Y { + label: '\u063A' + base: '\u063A' + shift, capslock: '\u0650' + ctrl, alt, meta: none +} + +key Z { + label: '\u0638' + base: '\u0638' + shift, capslock: '\u0643' + ctrl, alt, meta: none +} + +key 0 { + label, number: '\u06F0' + base: '\u06F0' + shift: '(' + ctrl, alt, meta: none +} + +key 1 { + label, number: '\u06F1' + base: '\u06F1' + shift: '!' + ctrl, alt, meta: none +} + +key 2 { + label, number: '\u06F2' + base: '\u06F2' + shift: '\u066C' + ctrl, alt, meta: none + +} +key 3 { + label, number: '\u06F3' + base: '\u06F3' + shift: '\u066B' + ctrl, alt, meta: none +} + +key 4 { + label, number: '\u06F4' + base: '\u06F4' + shift: '\uFDFC' + ctrl, alt, meta: none +} + +key 5 { + label, number: '\u06F5' + base: '\u06F5' + shift: '\u066A' + ctrl, alt, meta: none +} + +key 6 { + label, number: '\u06F6' + base: '\u06F6' + shift: '\u00D7' + ctrl, alt, meta: none +} + + +key 7 { + label, number: '\u06F7' + base: '\u06F7' + shift: '\u060C' + ctrl, alt, meta: none +} + +key 8 { + label, number: '\u06F8' + base: '\u06F8' + shift: '*' + ctrl, alt, meta: none +} + +key 9 { + label, number: '\u06F9' + base: '\u06F9' + shift: ')' + ctrl, alt, meta: none +} + +key SPACE { + label: ' ' + base: ' ' + ctrl, alt, meta: none +} + +key ENTER { + label: '\n' + base: '\n' + ctrl, alt, meta: none +} + +key TAB { + label: '\t' + base: '\t' + ctrl, alt, meta: none +} + +key COMMA { + label, number: '\u0648' + base: '\u0648' + shift: '<' + ctrl, alt, meta: none +} + +key PERIOD { + label, number: '.' + base: '.' + shift: '>' + ctrl, alt, meta: none +} + +key SLASH { + label, number: '/' + base: '/' + shift: '\u061F' + ctrl, alt, meta: none +} + +key GRAVE { + label, number: '`' + base: '`' + shift: '\u00F7' + ctrl, alt, meta: none +} + + +key MINUS { + label, number: '-' + base: '-' + shift: '_' + ctrl, alt, meta: none +} + +key EQUALS { + label, number: '=' + base: '=' + shift: '+' + ctrl, alt, meta: none +} + +key LEFT_BRACKET { + label, number: '\u062C' + base: '\u062C' + shift: '}' + ctrl, alt, meta: none +} + +key RIGHT_BRACKET { + label, number: '\u0686' + base: '\u0686' + shift: '{' + ctrl, alt, meta: none +} + +key BACKSLASH { + label, number: '\\' + base: '\\' + shift: '|' + ctrl, alt, meta: none +} + +key SEMICOLON { + label, number: '\u06A9' + base: '\u06A9' + shift: ':' + ctrl, alt, meta: none +} + +key APOSTROPHE { + label, number: '\'' + base: '\'' + shift: '\"' + ctrl, alt, meta: none +} + +### Numeric keypad ### + +key NUMPAD_0 { + label, number: '0' + base: fallback INSERT + numlock: '0' + ctrl, alt, meta: none +} + +key NUMPAD_1 { + label, number: '1' + base: fallback MOVE_END + numlock: '1' + ctrl, alt, meta: none +} + +key NUMPAD_2 { + label, number: '2' + base: fallback DPAD_DOWN + numlock: '2' + ctrl, alt, meta: none +} + +key NUMPAD_3 { + label, number: '3' + base: fallback PAGE_DOWN + numlock: '3' + ctrl, alt, meta: none +} + +key NUMPAD_4 { + label, number: '4' + base: fallback DPAD_LEFT + numlock: '4' + ctrl, alt, meta: none +} + +key NUMPAD_5 { + label, number: '5' + base: fallback DPAD_CENTER + numlock: '5' + ctrl, alt, meta: none +} + +key NUMPAD_6 { + label, number: '6' + base: fallback DPAD_RIGHT + numlock: '6' + ctrl, alt, meta: none +} + +key NUMPAD_7 { + label, number: '7' + base: fallback MOVE_HOME + numlock: '7' + ctrl, alt, meta: none +} + +key NUMPAD_8 { + label, number: '8' + base: fallback DPAD_UP + numlock: '8' + ctrl, alt, meta: none +} + +key NUMPAD_9 { + label, number: '9' + base: fallback PAGE_UP + numlock: '9' + ctrl, alt, meta: none +} + +key NUMPAD_LEFT_PAREN { + label, number: '(' + base: '(' + ctrl, alt, meta: none +} + +key NUMPAD_RIGHT_PAREN { + label, number: ')' + base: ')' + ctrl, alt, meta: none +} + +key NUMPAD_DIVIDE { + label, number: '/' + base: '/' + ctrl, alt, meta: none +} + +key NUMPAD_MULTIPLY { + label, number: '*' + base: '*' + ctrl, alt, meta: none +} + +key NUMPAD_SUBTRACT { + label, number: '-' + base: '-' + ctrl, alt, meta: none +} + +key NUMPAD_ADD { + label, number: '+' + base: '+' + ctrl, alt, meta: none +} + +key NUMPAD_DOT { + label, number: '.' + base: fallback FORWARD_DEL + numlock: '.' + ctrl, alt, meta: none +} + +key NUMPAD_COMMA { + label, number: ',' + base: ',' + ctrl, alt, meta: none +} + +key NUMPAD_EQUALS { + label, number: '=' + base: '=' + ctrl, alt, meta: none +} + +key NUMPAD_ENTER { + label: '\n' + base: '\n' fallback ENTER + ctrl, alt, meta: none fallback ENTER +} diff --git a/packages/InputDevices/res/values-af/strings.xml b/packages/InputDevices/res/values-af/strings.xml index a36d01e02a7a..43010192e454 100644 --- a/packages/InputDevices/res/values-af/strings.xml +++ b/packages/InputDevices/res/values-af/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litaus"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spaans (Latyn)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Letties"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persies"</string> </resources> diff --git a/packages/InputDevices/res/values-am/strings.xml b/packages/InputDevices/res/values-am/strings.xml index 3186addcf64e..ce3659ab38a5 100644 --- a/packages/InputDevices/res/values-am/strings.xml +++ b/packages/InputDevices/res/values-am/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ሊቱዌኒያኛ"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"ስፓኒሽ (ላቲን)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"ላትቪያኛ"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"ፋርስኛ"</string> </resources> diff --git a/packages/InputDevices/res/values-ar/strings.xml b/packages/InputDevices/res/values-ar/strings.xml index 1d3d9f545511..2b0a6f99b03e 100644 --- a/packages/InputDevices/res/values-ar/strings.xml +++ b/packages/InputDevices/res/values-ar/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"الليتوانية"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"الإسبانية (اللاتينية)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"اللاتفية"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"الفارسية"</string> </resources> diff --git a/packages/InputDevices/res/values-az/strings.xml b/packages/InputDevices/res/values-az/strings.xml index 25d7c9151bfb..a1f7c1c95b34 100644 --- a/packages/InputDevices/res/values-az/strings.xml +++ b/packages/InputDevices/res/values-az/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litva"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"İspan (Latın)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Latış"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Fars Dili"</string> </resources> diff --git a/packages/InputDevices/res/values-b+sr+Latn/strings.xml b/packages/InputDevices/res/values-b+sr+Latn/strings.xml index 88a977f4aed8..c60b59e34e0f 100644 --- a/packages/InputDevices/res/values-b+sr+Latn/strings.xml +++ b/packages/InputDevices/res/values-b+sr+Latn/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"litvanski"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"španski (Latinska Amerika)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"letonski"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"persijska"</string> </resources> diff --git a/packages/InputDevices/res/values-be/strings.xml b/packages/InputDevices/res/values-be/strings.xml index a552fa57419d..e93d03a72abe 100644 --- a/packages/InputDevices/res/values-be/strings.xml +++ b/packages/InputDevices/res/values-be/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Літоўская"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Іспанская (Лацінская Амерыка)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Латышская"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Персідская"</string> </resources> diff --git a/packages/InputDevices/res/values-bg/strings.xml b/packages/InputDevices/res/values-bg/strings.xml index e5e2c967d311..ee5cfa890610 100644 --- a/packages/InputDevices/res/values-bg/strings.xml +++ b/packages/InputDevices/res/values-bg/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Литовска клавиатурна подредба"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Исп. клав. подредба (Лат. Америка)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"латвийски"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"персийски"</string> </resources> diff --git a/packages/InputDevices/res/values-bn/strings.xml b/packages/InputDevices/res/values-bn/strings.xml index e9540b64f894..945c89138e54 100644 --- a/packages/InputDevices/res/values-bn/strings.xml +++ b/packages/InputDevices/res/values-bn/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"লিথুয়ানিয়ান"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"স্প্যানিশ (ল্যাটিন)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"লাটভিও"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"ফার্সী"</string> </resources> diff --git a/packages/InputDevices/res/values-bs/strings.xml b/packages/InputDevices/res/values-bs/strings.xml index 9672ae84a0a7..ca1b8ff67d5e 100644 --- a/packages/InputDevices/res/values-bs/strings.xml +++ b/packages/InputDevices/res/values-bs/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"litvanski"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"španski (Latinska Amerika)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"latvijski"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"perzijski"</string> </resources> diff --git a/packages/InputDevices/res/values-ca/strings.xml b/packages/InputDevices/res/values-ca/strings.xml index ee25a74d7daa..3c6ea158a2a3 100644 --- a/packages/InputDevices/res/values-ca/strings.xml +++ b/packages/InputDevices/res/values-ca/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituà"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Espanyol (llatí)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Letó"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persa"</string> </resources> diff --git a/packages/InputDevices/res/values-cs/strings.xml b/packages/InputDevices/res/values-cs/strings.xml index 3e7b9c84aecc..a78663b4ab36 100644 --- a/packages/InputDevices/res/values-cs/strings.xml +++ b/packages/InputDevices/res/values-cs/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"litevština"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"španělština (Latinská Amerika)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Lotyšská klávesnice"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"perština"</string> </resources> diff --git a/packages/InputDevices/res/values-da/strings.xml b/packages/InputDevices/res/values-da/strings.xml index 08fdee5e0be3..334952c8f35d 100644 --- a/packages/InputDevices/res/values-da/strings.xml +++ b/packages/InputDevices/res/values-da/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litauisk"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spansk (latinamerika)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Lettisk"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persisk"</string> </resources> diff --git a/packages/InputDevices/res/values-de/strings.xml b/packages/InputDevices/res/values-de/strings.xml index 6af00309071d..1543ef2d3726 100644 --- a/packages/InputDevices/res/values-de/strings.xml +++ b/packages/InputDevices/res/values-de/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litauisch"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanisch (Lateinisch)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Lettisch"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persisch"</string> </resources> diff --git a/packages/InputDevices/res/values-el/strings.xml b/packages/InputDevices/res/values-el/strings.xml index da6dca2fe242..e5d14090acb4 100644 --- a/packages/InputDevices/res/values-el/strings.xml +++ b/packages/InputDevices/res/values-el/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Λιθουανικά"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Ισπανικά (Λατινικής Αμερικής)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Λετονικά"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Περσικά"</string> </resources> diff --git a/packages/InputDevices/res/values-en-rAU/strings.xml b/packages/InputDevices/res/values-en-rAU/strings.xml index 01c2979ec107..9217bc49a21c 100644 --- a/packages/InputDevices/res/values-en-rAU/strings.xml +++ b/packages/InputDevices/res/values-en-rAU/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lithuanian"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanish (Latin)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Latvian"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persian"</string> </resources> diff --git a/packages/InputDevices/res/values-en-rCA/strings.xml b/packages/InputDevices/res/values-en-rCA/strings.xml index 01c2979ec107..9217bc49a21c 100644 --- a/packages/InputDevices/res/values-en-rCA/strings.xml +++ b/packages/InputDevices/res/values-en-rCA/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lithuanian"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanish (Latin)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Latvian"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persian"</string> </resources> diff --git a/packages/InputDevices/res/values-en-rGB/strings.xml b/packages/InputDevices/res/values-en-rGB/strings.xml index 01c2979ec107..9217bc49a21c 100644 --- a/packages/InputDevices/res/values-en-rGB/strings.xml +++ b/packages/InputDevices/res/values-en-rGB/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lithuanian"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanish (Latin)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Latvian"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persian"</string> </resources> diff --git a/packages/InputDevices/res/values-en-rIN/strings.xml b/packages/InputDevices/res/values-en-rIN/strings.xml index 01c2979ec107..9217bc49a21c 100644 --- a/packages/InputDevices/res/values-en-rIN/strings.xml +++ b/packages/InputDevices/res/values-en-rIN/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lithuanian"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanish (Latin)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Latvian"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persian"</string> </resources> diff --git a/packages/InputDevices/res/values-en-rXC/strings.xml b/packages/InputDevices/res/values-en-rXC/strings.xml index b9de6e7616b9..43d76770a522 100644 --- a/packages/InputDevices/res/values-en-rXC/strings.xml +++ b/packages/InputDevices/res/values-en-rXC/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lithuanian"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanish (Latin)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Latvian"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persian"</string> </resources> diff --git a/packages/InputDevices/res/values-es-rUS/strings.xml b/packages/InputDevices/res/values-es-rUS/strings.xml index 6acf07b5a630..68fcfd7d6035 100644 --- a/packages/InputDevices/res/values-es-rUS/strings.xml +++ b/packages/InputDevices/res/values-es-rUS/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituano"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Español (latino)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Letón"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persa"</string> </resources> diff --git a/packages/InputDevices/res/values-es/strings.xml b/packages/InputDevices/res/values-es/strings.xml index af1492a00623..86c82ed75ab4 100644 --- a/packages/InputDevices/res/values-es/strings.xml +++ b/packages/InputDevices/res/values-es/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituano"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Español (Latinoamérica)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Letón"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persa"</string> </resources> diff --git a/packages/InputDevices/res/values-et/strings.xml b/packages/InputDevices/res/values-et/strings.xml index d03b82ebd29a..8bc5c2535ab5 100644 --- a/packages/InputDevices/res/values-et/strings.xml +++ b/packages/InputDevices/res/values-et/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Leedu"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Hispaania (Ladina-Ameerika)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"läti keel"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"pärsia"</string> </resources> diff --git a/packages/InputDevices/res/values-eu/strings.xml b/packages/InputDevices/res/values-eu/strings.xml index d18c6f8ab59a..4fadb97329d2 100644 --- a/packages/InputDevices/res/values-eu/strings.xml +++ b/packages/InputDevices/res/values-eu/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituaniera"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Espainiera (Latinoamerika)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Letoniera"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Pertsiera"</string> </resources> diff --git a/packages/InputDevices/res/values-fa/strings.xml b/packages/InputDevices/res/values-fa/strings.xml index f2848a978eba..037e04473f9f 100644 --- a/packages/InputDevices/res/values-fa/strings.xml +++ b/packages/InputDevices/res/values-fa/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"لیتوانیایی"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"اسپانیایی (لاتین)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"لتونیایی"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"فارسی"</string> </resources> diff --git a/packages/InputDevices/res/values-fi/strings.xml b/packages/InputDevices/res/values-fi/strings.xml index 284efc8a93a7..65bd8d3cc491 100644 --- a/packages/InputDevices/res/values-fi/strings.xml +++ b/packages/InputDevices/res/values-fi/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"liettua"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"espanja (Latinalainen Amerikka)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"latvialainen"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"persia"</string> </resources> diff --git a/packages/InputDevices/res/values-fr-rCA/strings.xml b/packages/InputDevices/res/values-fr-rCA/strings.xml index b26a0eac16e1..8b132fa90fba 100644 --- a/packages/InputDevices/res/values-fr-rCA/strings.xml +++ b/packages/InputDevices/res/values-fr-rCA/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituanien"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Espagnol (latin)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Letton"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persan"</string> </resources> diff --git a/packages/InputDevices/res/values-fr/strings.xml b/packages/InputDevices/res/values-fr/strings.xml index a428a23c091b..baf749db9652 100644 --- a/packages/InputDevices/res/values-fr/strings.xml +++ b/packages/InputDevices/res/values-fr/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituanien"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Espagnol (latin)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Letton"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persan"</string> </resources> diff --git a/packages/InputDevices/res/values-gl/strings.xml b/packages/InputDevices/res/values-gl/strings.xml index bb0f2a06ec1f..c5bddc5fab70 100644 --- a/packages/InputDevices/res/values-gl/strings.xml +++ b/packages/InputDevices/res/values-gl/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituano"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Español (América Latina)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Letón"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persa"</string> </resources> diff --git a/packages/InputDevices/res/values-gu/strings.xml b/packages/InputDevices/res/values-gu/strings.xml index e83b0ca49dad..0f8c7520d243 100644 --- a/packages/InputDevices/res/values-gu/strings.xml +++ b/packages/InputDevices/res/values-gu/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"લિથુનિયન"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"સ્પેનિશ (લેટિન)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"લાતવિયન"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"પર્શિયન"</string> </resources> diff --git a/packages/InputDevices/res/values-hi/strings.xml b/packages/InputDevices/res/values-hi/strings.xml index 41966e403f25..c1bbd9d059a9 100644 --- a/packages/InputDevices/res/values-hi/strings.xml +++ b/packages/InputDevices/res/values-hi/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"लिथुआनियाई"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"स्पेनिश (लैटिन)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"लातवियाई"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"फ़ारसी"</string> </resources> diff --git a/packages/InputDevices/res/values-hr/strings.xml b/packages/InputDevices/res/values-hr/strings.xml index 27066adb4162..ec029349b6de 100644 --- a/packages/InputDevices/res/values-hr/strings.xml +++ b/packages/InputDevices/res/values-hr/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"litavski"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"španjolski (Latinska Amerika)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"latvijska"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"perzijski"</string> </resources> diff --git a/packages/InputDevices/res/values-hu/strings.xml b/packages/InputDevices/res/values-hu/strings.xml index 6fbc3ebf3e17..a5412d4e1d8b 100644 --- a/packages/InputDevices/res/values-hu/strings.xml +++ b/packages/InputDevices/res/values-hu/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"litván"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"spanyol (latin-amerikai)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"lett"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"perzsa"</string> </resources> diff --git a/packages/InputDevices/res/values-hy/strings.xml b/packages/InputDevices/res/values-hy/strings.xml index 0d116457c3ab..b152b0f1e8f9 100644 --- a/packages/InputDevices/res/values-hy/strings.xml +++ b/packages/InputDevices/res/values-hy/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Լիտվերեն"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Իսպաներեն (Լատինական)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"լատիշերեն"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"պարսկերեն"</string> </resources> diff --git a/packages/InputDevices/res/values-in/strings.xml b/packages/InputDevices/res/values-in/strings.xml index b2cbd6e71c4a..33b9ae35a122 100644 --- a/packages/InputDevices/res/values-in/strings.xml +++ b/packages/InputDevices/res/values-in/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lithuania"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanyol (Latin)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Latvi"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persia"</string> </resources> diff --git a/packages/InputDevices/res/values-is/strings.xml b/packages/InputDevices/res/values-is/strings.xml index de91275044fa..0e80bd4243b6 100644 --- a/packages/InputDevices/res/values-is/strings.xml +++ b/packages/InputDevices/res/values-is/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litháískt"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spænskt (latneskt)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Lettneska"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persneska"</string> </resources> diff --git a/packages/InputDevices/res/values-it/strings.xml b/packages/InputDevices/res/values-it/strings.xml index c1c7faa9e6fa..5da935b32dbf 100644 --- a/packages/InputDevices/res/values-it/strings.xml +++ b/packages/InputDevices/res/values-it/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituano"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spagnolo (America Latina)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Lettone"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persiano"</string> </resources> diff --git a/packages/InputDevices/res/values-iw/strings.xml b/packages/InputDevices/res/values-iw/strings.xml index b3bd576c5c1a..5cbc4f4c9c62 100644 --- a/packages/InputDevices/res/values-iw/strings.xml +++ b/packages/InputDevices/res/values-iw/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ליטאית"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"ספרדית (לטינית)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"לטבית"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"פרסית"</string> </resources> diff --git a/packages/InputDevices/res/values-ja/strings.xml b/packages/InputDevices/res/values-ja/strings.xml index 2b3daf53ef4c..aa77ddc3b6f8 100644 --- a/packages/InputDevices/res/values-ja/strings.xml +++ b/packages/InputDevices/res/values-ja/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"リトアニア語"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"スペイン語(中南米)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"ラトビア語"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"ペルシャ語"</string> </resources> diff --git a/packages/InputDevices/res/values-ka/strings.xml b/packages/InputDevices/res/values-ka/strings.xml index 66d147e0f335..0b899c7489d0 100644 --- a/packages/InputDevices/res/values-ka/strings.xml +++ b/packages/InputDevices/res/values-ka/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ლიტვური"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"ესპანური (ლათინური)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"ლატვიური"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"სპარსული"</string> </resources> diff --git a/packages/InputDevices/res/values-kk/strings.xml b/packages/InputDevices/res/values-kk/strings.xml index d25354233062..659f5717be30 100644 --- a/packages/InputDevices/res/values-kk/strings.xml +++ b/packages/InputDevices/res/values-kk/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Литван"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Испан (латын)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Латыш"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Парсы"</string> </resources> diff --git a/packages/InputDevices/res/values-km/strings.xml b/packages/InputDevices/res/values-km/strings.xml index acd01ee6c3a1..a3a789c63a85 100644 --- a/packages/InputDevices/res/values-km/strings.xml +++ b/packages/InputDevices/res/values-km/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"លីទុយអានី"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"អេស្ប៉ាញ (ឡាតាំង)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"ឡាតវីយ៉ា"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"ពីស៊ាន"</string> </resources> diff --git a/packages/InputDevices/res/values-kn/strings.xml b/packages/InputDevices/res/values-kn/strings.xml index 966818dbc885..f07b439bdf72 100644 --- a/packages/InputDevices/res/values-kn/strings.xml +++ b/packages/InputDevices/res/values-kn/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ಲಿಥುವೇನಿಯನ್"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"ಸ್ಪ್ಯಾನಿಶ್ (ಲ್ಯಾಟಿನ್)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"ಲ್ಯಾಟ್ವಿಯನ್"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"ಪರ್ಶಿಯನ್"</string> </resources> diff --git a/packages/InputDevices/res/values-ko/strings.xml b/packages/InputDevices/res/values-ko/strings.xml index 775821094925..28dde4557551 100644 --- a/packages/InputDevices/res/values-ko/strings.xml +++ b/packages/InputDevices/res/values-ko/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"리투아니아어"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"스페인어(라틴)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"라트비아어"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"페르시아어"</string> </resources> diff --git a/packages/InputDevices/res/values-ky/strings.xml b/packages/InputDevices/res/values-ky/strings.xml index 578f70bc4076..e12b69fe158b 100644 --- a/packages/InputDevices/res/values-ky/strings.xml +++ b/packages/InputDevices/res/values-ky/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Литвача"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Испанча (Латын)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Латвияча"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Фарсиче"</string> </resources> diff --git a/packages/InputDevices/res/values-lo/strings.xml b/packages/InputDevices/res/values-lo/strings.xml index 05b1b8351513..8c040be3081c 100644 --- a/packages/InputDevices/res/values-lo/strings.xml +++ b/packages/InputDevices/res/values-lo/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ລິທົວນຽນ"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"ສະແປນນິດ (ລາຕິນ)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"ລັດວຽນ"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"ເປີຊຽນ"</string> </resources> diff --git a/packages/InputDevices/res/values-lt/strings.xml b/packages/InputDevices/res/values-lt/strings.xml index 1dae850ee1f0..0cd696f6f188 100644 --- a/packages/InputDevices/res/values-lt/strings.xml +++ b/packages/InputDevices/res/values-lt/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lietuvių"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Ispanų (Lotynų Amerika)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Latvių k."</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persų"</string> </resources> diff --git a/packages/InputDevices/res/values-lv/strings.xml b/packages/InputDevices/res/values-lv/strings.xml index 96dc53ba1aff..52a0751697ba 100644 --- a/packages/InputDevices/res/values-lv/strings.xml +++ b/packages/InputDevices/res/values-lv/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lietuviešu"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spāņu (latīņu)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Latviešu"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persiešu"</string> </resources> diff --git a/packages/InputDevices/res/values-mk/strings.xml b/packages/InputDevices/res/values-mk/strings.xml index 2fae1cf50cd1..2f9befe2c678 100644 --- a/packages/InputDevices/res/values-mk/strings.xml +++ b/packages/InputDevices/res/values-mk/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"литвански"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"шпански (латиница)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"латвиски"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"персиски"</string> </resources> diff --git a/packages/InputDevices/res/values-ml/strings.xml b/packages/InputDevices/res/values-ml/strings.xml index 51866673bdcd..6b5ed06dc3c3 100644 --- a/packages/InputDevices/res/values-ml/strings.xml +++ b/packages/InputDevices/res/values-ml/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ലിത്വാനിയന്"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"സ്പാനിഷ് (ലാറ്റിൻ)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"ലാറ്റ്വിയന്"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"പേര്ഷ്യന്"</string> </resources> diff --git a/packages/InputDevices/res/values-mn/strings.xml b/packages/InputDevices/res/values-mn/strings.xml index f1354fede5f6..82e664e4f5c0 100644 --- a/packages/InputDevices/res/values-mn/strings.xml +++ b/packages/InputDevices/res/values-mn/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Литви"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Испани (Латин)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Латви"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Перс"</string> </resources> diff --git a/packages/InputDevices/res/values-mr/strings.xml b/packages/InputDevices/res/values-mr/strings.xml index 33d01e97ef6e..70b7c77b69e9 100644 --- a/packages/InputDevices/res/values-mr/strings.xml +++ b/packages/InputDevices/res/values-mr/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"लिथुआनियन"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"स्पॅनिश (लॅटिन)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"लाट्वियन"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"पर्शियन"</string> </resources> diff --git a/packages/InputDevices/res/values-ms/strings.xml b/packages/InputDevices/res/values-ms/strings.xml index 04983e360a50..0f402e7b850d 100644 --- a/packages/InputDevices/res/values-ms/strings.xml +++ b/packages/InputDevices/res/values-ms/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Bahasa Lithuania"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Bahasa Sepanyol (Latin)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Bahasa Latvia"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Bahasa Parsi"</string> </resources> diff --git a/packages/InputDevices/res/values-my/strings.xml b/packages/InputDevices/res/values-my/strings.xml index f3762b4d6a10..246735375ef5 100644 --- a/packages/InputDevices/res/values-my/strings.xml +++ b/packages/InputDevices/res/values-my/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"လီသွေနီယံ"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"စပိန် (လက်တင်)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"လာတ်ဗီယံ"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"ပါရှန်"</string> </resources> diff --git a/packages/InputDevices/res/values-nb/strings.xml b/packages/InputDevices/res/values-nb/strings.xml index 37604e333c1c..bd2879ec7f23 100644 --- a/packages/InputDevices/res/values-nb/strings.xml +++ b/packages/InputDevices/res/values-nb/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litauisk"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spansk (latinsk)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Latvisk"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persisk"</string> </resources> diff --git a/packages/InputDevices/res/values-ne/strings.xml b/packages/InputDevices/res/values-ne/strings.xml index 4c3dec37f40c..55969c9e0565 100644 --- a/packages/InputDevices/res/values-ne/strings.xml +++ b/packages/InputDevices/res/values-ne/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"लिथुआनियन"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"स्पेनेली(ल्याटिन)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"लातभियन"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"फारसी"</string> </resources> diff --git a/packages/InputDevices/res/values-nl/strings.xml b/packages/InputDevices/res/values-nl/strings.xml index 31ade0555bd7..e40248f271c1 100644 --- a/packages/InputDevices/res/values-nl/strings.xml +++ b/packages/InputDevices/res/values-nl/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litouws"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spaans (Latijns-Amerika)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Lets"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Perzisch"</string> </resources> diff --git a/packages/InputDevices/res/values-pa/strings.xml b/packages/InputDevices/res/values-pa/strings.xml index 574ce810c8b1..951adc8c6e80 100644 --- a/packages/InputDevices/res/values-pa/strings.xml +++ b/packages/InputDevices/res/values-pa/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ਲੀਥੂਨੀਅਨ"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"ਸਪੇਨੀ (ਲਾਤੀਨੀ)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"ਲਾਤਵੀਅਨ"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"ਫ਼ਾਰਸੀ"</string> </resources> diff --git a/packages/InputDevices/res/values-pl/strings.xml b/packages/InputDevices/res/values-pl/strings.xml index 2ae815e32456..a307940f232d 100644 --- a/packages/InputDevices/res/values-pl/strings.xml +++ b/packages/InputDevices/res/values-pl/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"litewski"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"hiszpański (Ameryka Łacińska)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"łotewski"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Perski"</string> </resources> diff --git a/packages/InputDevices/res/values-pt-rBR/strings.xml b/packages/InputDevices/res/values-pt-rBR/strings.xml index a1503a4ebcb3..ad2abe1ca9de 100644 --- a/packages/InputDevices/res/values-pt-rBR/strings.xml +++ b/packages/InputDevices/res/values-pt-rBR/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituano"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Espanhol (América Latina)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Letão"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persa"</string> </resources> diff --git a/packages/InputDevices/res/values-pt-rPT/strings.xml b/packages/InputDevices/res/values-pt-rPT/strings.xml index b806fc2519f3..a5beee46123f 100644 --- a/packages/InputDevices/res/values-pt-rPT/strings.xml +++ b/packages/InputDevices/res/values-pt-rPT/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituano"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Espanhol (América Latina)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Letão"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persa"</string> </resources> diff --git a/packages/InputDevices/res/values-pt/strings.xml b/packages/InputDevices/res/values-pt/strings.xml index a1503a4ebcb3..ad2abe1ca9de 100644 --- a/packages/InputDevices/res/values-pt/strings.xml +++ b/packages/InputDevices/res/values-pt/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituano"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Espanhol (América Latina)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Letão"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persa"</string> </resources> diff --git a/packages/InputDevices/res/values-ro/strings.xml b/packages/InputDevices/res/values-ro/strings.xml index 795e9a2abd05..a933a7094b35 100644 --- a/packages/InputDevices/res/values-ro/strings.xml +++ b/packages/InputDevices/res/values-ro/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituaniană"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spaniolă (America Latină)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Letonă"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persană"</string> </resources> diff --git a/packages/InputDevices/res/values-ru/strings.xml b/packages/InputDevices/res/values-ru/strings.xml index ac4c81b490be..127a84dad8b0 100644 --- a/packages/InputDevices/res/values-ru/strings.xml +++ b/packages/InputDevices/res/values-ru/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Литовский"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Испанский (Латинская Америка)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"латышский"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Персидский"</string> </resources> diff --git a/packages/InputDevices/res/values-si/strings.xml b/packages/InputDevices/res/values-si/strings.xml index 945a097bba97..8192c18e751a 100644 --- a/packages/InputDevices/res/values-si/strings.xml +++ b/packages/InputDevices/res/values-si/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ලිතුවේනියානු"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"ස්පාඤ්ඤය (ලතින්)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"ලැට්වියානු"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"පර්සියානු"</string> </resources> diff --git a/packages/InputDevices/res/values-sk/strings.xml b/packages/InputDevices/res/values-sk/strings.xml index 2e76024f24f6..c631095aa982 100644 --- a/packages/InputDevices/res/values-sk/strings.xml +++ b/packages/InputDevices/res/values-sk/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litovčina"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Španielčina (Latinská Amerika)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Lotyština"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Perzština"</string> </resources> diff --git a/packages/InputDevices/res/values-sl/strings.xml b/packages/InputDevices/res/values-sl/strings.xml index a643c8ee5e0e..c5a19be9ef02 100644 --- a/packages/InputDevices/res/values-sl/strings.xml +++ b/packages/InputDevices/res/values-sl/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"litovščina"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"španščina (Latinska Amerika)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"latvijščina"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"perzijščina"</string> </resources> diff --git a/packages/InputDevices/res/values-sq/strings.xml b/packages/InputDevices/res/values-sq/strings.xml index 8a9000db65c5..dbc5b4d6286f 100644 --- a/packages/InputDevices/res/values-sq/strings.xml +++ b/packages/InputDevices/res/values-sq/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"lituanisht"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"spanjisht (latine)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"letonisht"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persisht"</string> </resources> diff --git a/packages/InputDevices/res/values-sr/strings.xml b/packages/InputDevices/res/values-sr/strings.xml index b06f6fc9bd6f..29eea72b9f2f 100644 --- a/packages/InputDevices/res/values-sr/strings.xml +++ b/packages/InputDevices/res/values-sr/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"литвански"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"шпански (Латинска Америка)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"летонски"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"персијска"</string> </resources> diff --git a/packages/InputDevices/res/values-sv/strings.xml b/packages/InputDevices/res/values-sv/strings.xml index 89cb54eee02b..9954a2b74661 100644 --- a/packages/InputDevices/res/values-sv/strings.xml +++ b/packages/InputDevices/res/values-sv/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litauiska"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanska (latinamerikansk)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"lettiska"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"persiska"</string> </resources> diff --git a/packages/InputDevices/res/values-sw/strings.xml b/packages/InputDevices/res/values-sw/strings.xml index 90516850443a..13b3954d21d3 100644 --- a/packages/InputDevices/res/values-sw/strings.xml +++ b/packages/InputDevices/res/values-sw/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Kilithuania"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Kihispania (Kilatini)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Kilatvia"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Kiajemi"</string> </resources> diff --git a/packages/InputDevices/res/values-ta/strings.xml b/packages/InputDevices/res/values-ta/strings.xml index 32efe7b2ff7c..fec9d8c00b99 100644 --- a/packages/InputDevices/res/values-ta/strings.xml +++ b/packages/InputDevices/res/values-ta/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"லிதுவேனியன்"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"ஸ்பானிஷ் (லத்தீன்)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"லத்வியன்"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"பெர்சியன்"</string> </resources> diff --git a/packages/InputDevices/res/values-te/strings.xml b/packages/InputDevices/res/values-te/strings.xml index e07d4c876d72..922868dbaec8 100644 --- a/packages/InputDevices/res/values-te/strings.xml +++ b/packages/InputDevices/res/values-te/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"లిథువేనియన్"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"స్పానిష్ (లాటిన్)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"లాత్వియన్"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"పర్షియన్"</string> </resources> diff --git a/packages/InputDevices/res/values-th/strings.xml b/packages/InputDevices/res/values-th/strings.xml index 50dc1e4d93d7..69d9ddf6065c 100644 --- a/packages/InputDevices/res/values-th/strings.xml +++ b/packages/InputDevices/res/values-th/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ลิทัวเนีย"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"สเปน (ละติน)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"ลัตเวีย"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"เปอร์เซีย"</string> </resources> diff --git a/packages/InputDevices/res/values-tl/strings.xml b/packages/InputDevices/res/values-tl/strings.xml index 0c3f1ff8864d..44821287906e 100644 --- a/packages/InputDevices/res/values-tl/strings.xml +++ b/packages/InputDevices/res/values-tl/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lithuanian"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanish (Latin)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Latvian"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Persian"</string> </resources> diff --git a/packages/InputDevices/res/values-tr/strings.xml b/packages/InputDevices/res/values-tr/strings.xml index a8d9a0f10a2f..08e5e3e6e5cd 100644 --- a/packages/InputDevices/res/values-tr/strings.xml +++ b/packages/InputDevices/res/values-tr/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litvanca"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"İspanyolca (Latin)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Letonca"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Farsça"</string> </resources> diff --git a/packages/InputDevices/res/values-uk/strings.xml b/packages/InputDevices/res/values-uk/strings.xml index c818001b5bec..b81f6726d209 100644 --- a/packages/InputDevices/res/values-uk/strings.xml +++ b/packages/InputDevices/res/values-uk/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Литовська"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Іспанська (латиниця)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Латвійська"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Перська"</string> </resources> diff --git a/packages/InputDevices/res/values-ur/strings.xml b/packages/InputDevices/res/values-ur/strings.xml index 2f2b84f1d8e3..2508d5d30748 100644 --- a/packages/InputDevices/res/values-ur/strings.xml +++ b/packages/InputDevices/res/values-ur/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"لتھوانیائی"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"ہسپانوی (لاطینی)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"لاتویائی"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"فارسی"</string> </resources> diff --git a/packages/InputDevices/res/values-uz/strings.xml b/packages/InputDevices/res/values-uz/strings.xml index 9c55615af30a..4b9d08b66052 100644 --- a/packages/InputDevices/res/values-uz/strings.xml +++ b/packages/InputDevices/res/values-uz/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litvan"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Ispan (lotin)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Latish"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Fors"</string> </resources> diff --git a/packages/InputDevices/res/values-vi/strings.xml b/packages/InputDevices/res/values-vi/strings.xml index 3ca715bab599..35c596056fbb 100644 --- a/packages/InputDevices/res/values-vi/strings.xml +++ b/packages/InputDevices/res/values-vi/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Tiếng Lithuania"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Tiếng Tây Ban Nha (La tinh)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Tiếng Latvia"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Tiếng Ba Tư"</string> </resources> diff --git a/packages/InputDevices/res/values-zh-rCN/strings.xml b/packages/InputDevices/res/values-zh-rCN/strings.xml index c61dccb66674..5f1fc17a9d00 100644 --- a/packages/InputDevices/res/values-zh-rCN/strings.xml +++ b/packages/InputDevices/res/values-zh-rCN/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"立陶宛语"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"西班牙语(拉丁美洲)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"拉脱维亚语"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"波斯语"</string> </resources> diff --git a/packages/InputDevices/res/values-zh-rHK/strings.xml b/packages/InputDevices/res/values-zh-rHK/strings.xml index 9385df8f4032..086f9664bff0 100644 --- a/packages/InputDevices/res/values-zh-rHK/strings.xml +++ b/packages/InputDevices/res/values-zh-rHK/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"立陶宛文"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"西班牙文 (拉丁美洲)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"拉脫維亞文"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"波斯文"</string> </resources> diff --git a/packages/InputDevices/res/values-zh-rTW/strings.xml b/packages/InputDevices/res/values-zh-rTW/strings.xml index 89ef55857878..5e2890f7bc79 100644 --- a/packages/InputDevices/res/values-zh-rTW/strings.xml +++ b/packages/InputDevices/res/values-zh-rTW/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"立陶宛文"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"西班牙文 (拉丁美洲)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"拉脫維亞文"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"波斯文"</string> </resources> diff --git a/packages/InputDevices/res/values-zu/strings.xml b/packages/InputDevices/res/values-zu/strings.xml index 0dcffb0518f8..18d26a25f524 100644 --- a/packages/InputDevices/res/values-zu/strings.xml +++ b/packages/InputDevices/res/values-zu/strings.xml @@ -41,4 +41,5 @@ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Isi-Lithuanian"</string> <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Isi-Spanish (Latin)"</string> <string name="keyboard_layout_latvian" msgid="4405417142306250595">"Isi-Latvian"</string> + <string name="keyboard_layout_persian" msgid="3920643161015888527">"Isi-Persian"</string> </resources> diff --git a/packages/InputDevices/res/values/strings.xml b/packages/InputDevices/res/values/strings.xml index 5644c9a9ddfb..1e262260a6c7 100644 --- a/packages/InputDevices/res/values/strings.xml +++ b/packages/InputDevices/res/values/strings.xml @@ -119,4 +119,7 @@ <!-- Latvian keyboard layout label. [CHAR LIMIT=35] --> <string name="keyboard_layout_latvian">Latvian</string> + + <!-- Persian keyboard layout label. [CHAR LIMIT=35] --> + <string name="keyboard_layout_persian">Persian</string> </resources> diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml index a302162a00f1..c55711a4e716 100644 --- a/packages/InputDevices/res/xml/keyboard_layouts.xml +++ b/packages/InputDevices/res/xml/keyboard_layouts.xml @@ -151,4 +151,8 @@ <keyboard-layout android:name="keyboard_layout_latvian" android:label="@string/keyboard_layout_latvian" android:keyboardLayout="@raw/keyboard_layout_latvian_qwerty" /> + + <keyboard-layout android:name="keyboard_layout_persian" + android:label="@string/keyboard_layout_persian" + android:keyboardLayout="@raw/keyboard_layout_persian" /> </keyboard-layouts> diff --git a/packages/MtpDocumentsProvider/res/values-te/strings.xml b/packages/MtpDocumentsProvider/res/values-te/strings.xml index 7add85835da7..b3436bf7ebb0 100644 --- a/packages/MtpDocumentsProvider/res/values-te/strings.xml +++ b/packages/MtpDocumentsProvider/res/values-te/strings.xml @@ -19,7 +19,7 @@ <string name="app_label" msgid="6271216747302322594">"MTP హోస్ట్"</string> <string name="downloads_app_label" msgid="7120690641874849726">"డౌన్లోడ్లు"</string> <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string> - <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> నుండి ఫైల్లను ప్రాప్యత చేస్తోంది"</string> + <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> నుండి ఫైల్లను యాక్సెస్ చేస్తోంది"</string> <string name="error_busy_device" msgid="3997316850357386589">"ఇతర పరికరం బిజీగా ఉంది. అది అందుబాటులోకి వచ్చే వరకు మీరు ఫైల్లను బదిలీ చేయలేరు."</string> <string name="error_locked_device" msgid="7557872102188356147">"ఫైల్లు ఏవీ కనుగొనబడలేదు. ఇతర పరికరం లాక్ చేయబడి ఉండవచ్చు. అలా జరిగి ఉంటే, దాన్ని అన్లాక్ చేసి, ఆపై మళ్లీ ప్రయత్నించండి."</string> </resources> diff --git a/packages/PrintSpooler/res/values-bn/strings.xml b/packages/PrintSpooler/res/values-bn/strings.xml index 88ba6ee5b9c1..1791358efcc4 100644 --- a/packages/PrintSpooler/res/values-bn/strings.xml +++ b/packages/PrintSpooler/res/values-bn/strings.xml @@ -31,11 +31,11 @@ <string name="template_all_pages" msgid="3322235982020148762">"সমস্ত <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string> <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> এর পরিসর"</string> <string name="pages_range_example" msgid="8558694453556945172">"যেমন, ১—৫,৮,১১—১৩"</string> - <string name="print_preview" msgid="8010217796057763343">"প্রিন্ট পূর্বরূপ"</string> - <string name="install_for_print_preview" msgid="6366303997385509332">"পূর্বরূপ দেখার জন্য PDF ভিউয়ার ইনস্টল করুন"</string> + <string name="print_preview" msgid="8010217796057763343">"প্রিন্ট প্রিভিউ"</string> + <string name="install_for_print_preview" msgid="6366303997385509332">"প্রিভিউ দেখার জন্য PDF ভিউয়ার ইনস্টল করুন"</string> <string name="printing_app_crashed" msgid="854477616686566398">"প্রিন্ট অ্যাপ্লিকেশান ক্র্যাশ করছে"</string> <string name="generating_print_job" msgid="3119608742651698916">"প্রিন্ট কার্য তৈরি করা হচ্ছে"</string> - <string name="save_as_pdf" msgid="5718454119847596853">"PDF হিসাবে সংরক্ষণ করুন"</string> + <string name="save_as_pdf" msgid="5718454119847596853">"PDF হিসেবে সংরক্ষণ করুন"</string> <string name="all_printers" msgid="5018829726861876202">"সমস্ত মুদ্রক…"</string> <string name="print_dialog" msgid="32628687461331979">"প্রিন্ট ডায়লগ"</string> <string name="current_page_template" msgid="5145005201131935302">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string> @@ -44,7 +44,7 @@ <string name="expand_handle" msgid="7282974448109280522">"প্রসারিত করার হ্যান্ডেল"</string> <string name="collapse_handle" msgid="6886637989442507451">"সঙ্কুচিত করার হ্যান্ডেল"</string> <string name="print_button" msgid="645164566271246268">"প্রিন্ট করুন"</string> - <string name="savetopdf_button" msgid="2976186791686924743">"PDF হিসাবে সংরক্ষণ করুন"</string> + <string name="savetopdf_button" msgid="2976186791686924743">"PDF হিসেবে সংরক্ষণ করুন"</string> <string name="print_options_expanded" msgid="6944679157471691859">"প্রিন্ট বিকল্প প্রসারিত হয়েছে"</string> <string name="print_options_collapsed" msgid="7455930445670414332">"প্রিন্ট বিকল্প সংকুচিত হয়েছে"</string> <string name="search" msgid="5421724265322228497">"অনুসন্ধান করুন"</string> @@ -99,13 +99,13 @@ <item msgid="79513688117503758">"সংক্ষিপ্ত প্রান্ত"</item> </string-array> <string-array name="orientation_labels"> - <item msgid="4061931020926489228">"প্রতিকৃতি"</item> + <item msgid="4061931020926489228">"পোর্ট্রেট"</item> <item msgid="3199660090246166812">"ভূদৃশ্য"</item> </string-array> <string name="print_write_error_message" msgid="5787642615179572543">"ফাইলে লেখা যায়নি"</string> <string name="print_error_default_message" msgid="8602678405502922346">"দুঃখিত, এটি কাজ করেনি৷ আবার চেষ্টা করুন৷"</string> <string name="print_error_retry" msgid="1426421728784259538">"আবার চেষ্টা করুন"</string> <string name="print_error_printer_unavailable" msgid="8985614415253203381">"এই মূহুর্তে প্রিন্টার উপলব্ধ নয়।"</string> - <string name="print_cannot_load_page" msgid="6179560924492912009">"পূর্বরূপ প্রদর্শন করা যাবে না"</string> - <string name="print_preparing_preview" msgid="3939930735671364712">"পূর্বরূপ প্রস্তুত করছে..."</string> + <string name="print_cannot_load_page" msgid="6179560924492912009">"প্রিভিউ প্রদর্শন করা যাবে না"</string> + <string name="print_preparing_preview" msgid="3939930735671364712">"প্রিভিউ প্রস্তুত করা হচ্ছে..."</string> </resources> diff --git a/packages/PrintSpooler/res/values-hi/strings.xml b/packages/PrintSpooler/res/values-hi/strings.xml index bfe558c37679..454834cc1898 100644 --- a/packages/PrintSpooler/res/values-hi/strings.xml +++ b/packages/PrintSpooler/res/values-hi/strings.xml @@ -17,7 +17,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="4469836075319831821">"प्रिंट स्पूलर"</string> - <string name="more_options_button" msgid="2243228396432556771">"अधिक विकल्प"</string> + <string name="more_options_button" msgid="2243228396432556771">"ज़्यादा विकल्प"</string> <string name="label_destination" msgid="9132510997381599275">"गंतव्य"</string> <string name="label_copies" msgid="3634531042822968308">"प्रतियां"</string> <string name="label_copies_summary" msgid="3861966063536529540">"प्रतियां:"</string> @@ -30,12 +30,12 @@ <string name="destination_default_text" msgid="5422708056807065710">"कोई प्रिंटर चुनें"</string> <string name="template_all_pages" msgid="3322235982020148762">"सभी <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string> <string name="template_page_range" msgid="428638530038286328">"पेज संख्या <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string> - <string name="pages_range_example" msgid="8558694453556945172">"उदा. 1—5,8,11—13"</string> - <string name="print_preview" msgid="8010217796057763343">"प्रिंट पूर्वावलोकन"</string> - <string name="install_for_print_preview" msgid="6366303997385509332">"पूर्वावलोकन के लिए PDF व्यूअर इंस्टॉल करें"</string> + <string name="pages_range_example" msgid="8558694453556945172">"उदाहरण 1—5,8,11—13"</string> + <string name="print_preview" msgid="8010217796057763343">"प्रिंट की झलक"</string> + <string name="install_for_print_preview" msgid="6366303997385509332">"झलक के लिए पीडीएफ़ व्यूअर इंस्टॉल करें"</string> <string name="printing_app_crashed" msgid="854477616686566398">"प्रिंटिंग ऐप्लिकेशन क्रैश हो गया"</string> <string name="generating_print_job" msgid="3119608742651698916">"प्रिंट कार्य जनरेट हो रहा है"</string> - <string name="save_as_pdf" msgid="5718454119847596853">"PDF के रूप में जोड़ें"</string> + <string name="save_as_pdf" msgid="5718454119847596853">"पीडीएफ़ के तौर पर सेव करें"</string> <string name="all_printers" msgid="5018829726861876202">"सभी प्रिंटर..."</string> <string name="print_dialog" msgid="32628687461331979">"प्रिंट डॉयलॉग"</string> <string name="current_page_template" msgid="5145005201131935302">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string> @@ -44,14 +44,14 @@ <string name="expand_handle" msgid="7282974448109280522">"हैंडल विस्तृत करें"</string> <string name="collapse_handle" msgid="6886637989442507451">"हैंडल संक्षिप्त करें"</string> <string name="print_button" msgid="645164566271246268">"प्रिंट करें"</string> - <string name="savetopdf_button" msgid="2976186791686924743">"PDF में जोड़ें"</string> + <string name="savetopdf_button" msgid="2976186791686924743">"पीडीएफ़ में सेव करें"</string> <string name="print_options_expanded" msgid="6944679157471691859">"प्रिंट विकल्पों को विस्तृत किया गया"</string> <string name="print_options_collapsed" msgid="7455930445670414332">"प्रिंट विकल्पों को संक्षिप्त किया गया"</string> - <string name="search" msgid="5421724265322228497">"खोजें"</string> + <string name="search" msgid="5421724265322228497">"सर्च करें"</string> <string name="all_printers_label" msgid="3178848870161526399">"सभी प्रिंटर"</string> <string name="add_print_service_label" msgid="5356702546188981940">"सेवा जोड़ें"</string> - <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"खोज बॉक्स प्रदर्शित है"</string> - <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"खोज बॉक्स छिपा हुआ है"</string> + <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"सर्च बॉक्स दिखाई दे रहा है"</string> + <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"सर्च बॉक्स छिपा हुआ है"</string> <string name="print_add_printer" msgid="1088656468360653455">"प्रिंटर जोड़ें"</string> <string name="print_select_printer" msgid="7388760939873368698">"प्रिंटर चुनें"</string> <string name="print_forget_printer" msgid="5035287497291910766">"प्रिंटर को भूल जाएं"</string> @@ -60,12 +60,12 @@ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिंटर मिले</item> </plurals> <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string> - <string name="printer_info_desc" msgid="7181988788991581654">"इस प्रिंटर के बारे में अधिक जानकारी"</string> + <string name="printer_info_desc" msgid="7181988788991581654">"इस प्रिंटर के बारे में ज़्यादा जानकारी"</string> <string name="notification_channel_progress" msgid="872788690775721436">"चल रहे प्रिंट कार्य"</string> <string name="notification_channel_failure" msgid="9042250774797916414">"असफल रहे प्रिंट कार्य"</string> <string name="could_not_create_file" msgid="3425025039427448443">"फ़ाइल नहीं बनाई जा सकी"</string> <string name="print_services_disabled_toast" msgid="9089060734685174685">"कुछ प्रिंट सेवाएं अक्षम हैं"</string> - <string name="print_searching_for_printers" msgid="6550424555079932867">"प्रिंटर खोज रहा है"</string> + <string name="print_searching_for_printers" msgid="6550424555079932867">"प्रिंटर सर्च कर रहा है"</string> <string name="print_no_print_services" msgid="8561247706423327966">"कोई भी प्रिंट सेवा सक्षम नहीं है"</string> <string name="print_no_printers" msgid="4869403323900054866">"कोई प्रिंटर नहीं मिले"</string> <string name="cannot_add_printer" msgid="7840348733668023106">"प्रिंटर जोड़े नहीं जा सकते"</string> @@ -83,7 +83,7 @@ <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> रद्द हो रहा है"</string> <string name="failed_notification_title_template" msgid="2256217208186530973">"प्रिंटर गड़बड़ी <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string> <string name="blocked_notification_title_template" msgid="1175435827331588646">"प्रिंटर अवरोधित <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string> - <string name="cancel" msgid="4373674107267141885">"अभी नहीं"</string> + <string name="cancel" msgid="4373674107267141885">"रद्द करें"</string> <string name="restart" msgid="2472034227037808749">"पुन: आरंभ करें"</string> <string name="no_connection_to_printer" msgid="2159246915977282728">"प्रिंटर के लिए कोई कनेक्शन नहीं"</string> <string name="reason_unknown" msgid="5507940196503246139">"अज्ञात"</string> @@ -106,6 +106,6 @@ <string name="print_error_default_message" msgid="8602678405502922346">"क्षमा करें, उससे बात नहीं बनी. पुन: प्रयास करें."</string> <string name="print_error_retry" msgid="1426421728784259538">"फिर से प्रयास करें"</string> <string name="print_error_printer_unavailable" msgid="8985614415253203381">"यह प्रिंटर इस समय उपलब्ध नहीं है."</string> - <string name="print_cannot_load_page" msgid="6179560924492912009">"पूर्वावलोकन प्रदर्शित नहीं किया जा सकता"</string> - <string name="print_preparing_preview" msgid="3939930735671364712">"पूर्वावलोकन तैयार हो रहा है..."</string> + <string name="print_cannot_load_page" msgid="6179560924492912009">"झलक नहीं दिखाई जा सकती"</string> + <string name="print_preparing_preview" msgid="3939930735671364712">"झलक तैयार हो रही है..."</string> </resources> diff --git a/packages/PrintSpooler/res/values-iw/strings.xml b/packages/PrintSpooler/res/values-iw/strings.xml index 60005003e451..6540ca1af312 100644 --- a/packages/PrintSpooler/res/values-iw/strings.xml +++ b/packages/PrintSpooler/res/values-iw/strings.xml @@ -47,9 +47,9 @@ <string name="savetopdf_button" msgid="2976186791686924743">"שמור כ-PDF"</string> <string name="print_options_expanded" msgid="6944679157471691859">"אפשרויות ההדפסה הורחבו"</string> <string name="print_options_collapsed" msgid="7455930445670414332">"אפשרויות ההדפסה כווצו"</string> - <string name="search" msgid="5421724265322228497">"חפש"</string> + <string name="search" msgid="5421724265322228497">"חיפוש"</string> <string name="all_printers_label" msgid="3178848870161526399">"כל המדפסות"</string> - <string name="add_print_service_label" msgid="5356702546188981940">"הוסף שירות"</string> + <string name="add_print_service_label" msgid="5356702546188981940">"הוספת שירות"</string> <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"תיבת החיפוש מוצגת"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"תיבת החיפוש מוסתרת"</string> <string name="print_add_printer" msgid="1088656468360653455">"הוסף מדפסת"</string> diff --git a/packages/PrintSpooler/res/values-kn/strings.xml b/packages/PrintSpooler/res/values-kn/strings.xml index c8eaf6e49b55..2f8e6e088612 100644 --- a/packages/PrintSpooler/res/values-kn/strings.xml +++ b/packages/PrintSpooler/res/values-kn/strings.xml @@ -99,7 +99,7 @@ <item msgid="79513688117503758">"ಚಿಕ್ಕದಾದ ಅಂಚು"</item> </string-array> <string-array name="orientation_labels"> - <item msgid="4061931020926489228">"ಪೋಟ್ರೇಟ್"</item> + <item msgid="4061931020926489228">"ಪೋರ್ಟ್ರೇಟ್"</item> <item msgid="3199660090246166812">"ಲ್ಯಾಂಡ್ಸ್ಕೇಪ್"</item> </string-array> <string name="print_write_error_message" msgid="5787642615179572543">"ಫೈಲ್ಗೆ ರೈಟ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ"</string> diff --git a/packages/PrintSpooler/res/values-mr/strings.xml b/packages/PrintSpooler/res/values-mr/strings.xml index 1ccc721d3eb3..05eb8539444f 100644 --- a/packages/PrintSpooler/res/values-mr/strings.xml +++ b/packages/PrintSpooler/res/values-mr/strings.xml @@ -32,10 +32,10 @@ <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> ची श्रेणी"</string> <string name="pages_range_example" msgid="8558694453556945172">"उदा. 1—5,8,11—13"</string> <string name="print_preview" msgid="8010217796057763343">"मुद्रण पूर्वावलोकन"</string> - <string name="install_for_print_preview" msgid="6366303997385509332">"पूर्वावलोकनासाठी PDF दर्शक स्थापित करा"</string> - <string name="printing_app_crashed" msgid="854477616686566398">"मुद्रण करण्याचा अॅप क्रॅश झाला"</string> + <string name="install_for_print_preview" msgid="6366303997385509332">"पूर्वावलोकनासाठी पीडीएफ व्ह्यूअर इंस्टॉल करा"</string> + <string name="printing_app_crashed" msgid="854477616686566398">"प्रिंटिंग अॅप क्रॅश झाले"</string> <string name="generating_print_job" msgid="3119608742651698916">"मुद्रण कार्य व्युत्पन्न करीत आहे"</string> - <string name="save_as_pdf" msgid="5718454119847596853">"PDF म्हणून जतन करा"</string> + <string name="save_as_pdf" msgid="5718454119847596853">"पीडीएफ म्हणून सेव्ह करा"</string> <string name="all_printers" msgid="5018829726861876202">"सर्व प्रिंटर..."</string> <string name="print_dialog" msgid="32628687461331979">"मुद्रण संवाद"</string> <string name="current_page_template" msgid="5145005201131935302">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string> @@ -44,7 +44,7 @@ <string name="expand_handle" msgid="7282974448109280522">"विस्तृत करण्याचे हँडल"</string> <string name="collapse_handle" msgid="6886637989442507451">"संक्षिप्त करण्याचे हँडल"</string> <string name="print_button" msgid="645164566271246268">"मुद्रण करा"</string> - <string name="savetopdf_button" msgid="2976186791686924743">"PDF वर जतन करा"</string> + <string name="savetopdf_button" msgid="2976186791686924743">"पीडीएफ वर सेव्ह करा"</string> <string name="print_options_expanded" msgid="6944679157471691859">"मुद्रण पर्याय विस्तृत झाले"</string> <string name="print_options_collapsed" msgid="7455930445670414332">"मुद्रण पर्याय संक्षिप्त झाले"</string> <string name="search" msgid="5421724265322228497">"शोध"</string> @@ -76,12 +76,12 @@ <string name="disabled_services_title" msgid="7313253167968363211">"अक्षम केलल्या सेवा"</string> <string name="all_services_title" msgid="5578662754874906455">"सर्व सेवा"</string> <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138"> - <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिंटर शोधण्यासाठी स्थापित करा</item> - <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिंटर शोधण्यासाठी स्थापित करा</item> + <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिंटर शोधण्यासाठी इंस्टॉल करा</item> + <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिंटर शोधण्यासाठी इंस्टॉल करा</item> </plurals> <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> मुद्रण करीत आहे"</string> <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> रद्द करीत आहे"</string> - <string name="failed_notification_title_template" msgid="2256217208186530973">"प्रिंटर त्रुटी <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string> + <string name="failed_notification_title_template" msgid="2256217208186530973">"प्रिंटर एरर <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string> <string name="blocked_notification_title_template" msgid="1175435827331588646">"प्रिंटरने <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> अवरोधित केले"</string> <string name="cancel" msgid="4373674107267141885">"रद्द करा"</string> <string name="restart" msgid="2472034227037808749">"रीस्टार्ट करा"</string> @@ -100,7 +100,7 @@ </string-array> <string-array name="orientation_labels"> <item msgid="4061931020926489228">"पोट्रेट"</item> - <item msgid="3199660090246166812">"भूदृश्य"</item> + <item msgid="3199660090246166812">"लॅंडस्केप"</item> </string-array> <string name="print_write_error_message" msgid="5787642615179572543">"फायलीवर लिहू शकलो नाही"</string> <string name="print_error_default_message" msgid="8602678405502922346">"क्षमस्व, त्याने कार्य केले नाही. पुन्हा प्रयत्न करा."</string> diff --git a/packages/PrintSpooler/res/values-te/strings.xml b/packages/PrintSpooler/res/values-te/strings.xml index 2a20fc8d44b1..110bd49c9131 100644 --- a/packages/PrintSpooler/res/values-te/strings.xml +++ b/packages/PrintSpooler/res/values-te/strings.xml @@ -47,7 +47,7 @@ <string name="savetopdf_button" msgid="2976186791686924743">"PDF వలె సేవ్ చేయి"</string> <string name="print_options_expanded" msgid="6944679157471691859">"ముద్రణ ఎంపికలు విస్తరించబడ్డాయి"</string> <string name="print_options_collapsed" msgid="7455930445670414332">"ముద్రణ ఎంపికలు కుదించబడ్డాయి"</string> - <string name="search" msgid="5421724265322228497">"శోధించు"</string> + <string name="search" msgid="5421724265322228497">"వెతుకు"</string> <string name="all_printers_label" msgid="3178848870161526399">"అన్ని ప్రింటర్లు"</string> <string name="add_print_service_label" msgid="5356702546188981940">"సేవను జోడించు"</string> <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"శోధన పెట్టె చూపబడింది"</string> @@ -81,7 +81,7 @@ </plurals> <string name="printing_notification_title_template" msgid="295903957762447362">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ను ముద్రిస్తోంది"</string> <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ను రద్దు చేస్తోంది"</string> - <string name="failed_notification_title_template" msgid="2256217208186530973">"ప్రింటర్ లోపం <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string> + <string name="failed_notification_title_template" msgid="2256217208186530973">"ప్రింటర్ ఎర్రర్ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string> <string name="blocked_notification_title_template" msgid="1175435827331588646">"ప్రింటర్ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ను బ్లాక్ చేసింది"</string> <string name="cancel" msgid="4373674107267141885">"రద్దు చేయి"</string> <string name="restart" msgid="2472034227037808749">"పునఃప్రారంభించు"</string> diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java index f11a9cde9520..b6a003de0eb9 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java +++ b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java @@ -136,7 +136,12 @@ public final class RemotePrintDocument { mState = STATE_CANCELED; notifyUpdateCanceled(); } - runPendingCommand(); + if (mNextCommand != null) { + runPendingCommand(); + } else { + // The update was not performed, hence the spec is stale + mUpdateSpec.reset(); + } } } }; diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java index ad46b60f2f5b..d592c306ad99 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java @@ -486,6 +486,12 @@ public final class PageAdapter extends Adapter<ViewHolder> { loadingContent.layout(0, 0, loadingContent.getMeasuredWidth(), loadingContent.getMeasuredHeight()); + // To create a bitmap, height & width should be larger than 0 + if (mPageContentHeight <= 0 || mPageContentWidth <= 0) { + Log.w(LOG_TAG, "Unable to create bitmap, height or width smaller than 0!"); + return; + } + Bitmap loadingBitmap = Bitmap.createBitmap(mPageContentWidth, mPageContentHeight, Bitmap.Config.ARGB_8888); loadingContent.draw(new Canvas(loadingBitmap)); diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java index 1b7a1b8b9567..951d196dabe1 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java @@ -642,7 +642,9 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - mMediaSizeComparator.onConfigurationChanged(newConfig); + if (mMediaSizeComparator != null) { + mMediaSizeComparator.onConfigurationChanged(newConfig); + } if (mPrintPreviewController != null) { mPrintPreviewController.onOrientationChanged(); diff --git a/packages/SettingsLib/res/drawable/ic_info_outline_24dp.xml b/packages/SettingsLib/res/drawable/ic_info_outline_24dp.xml index 3fe1e9e5ca9f..5a7f954e0dfd 100644 --- a/packages/SettingsLib/res/drawable/ic_info_outline_24dp.xml +++ b/packages/SettingsLib/res/drawable/ic_info_outline_24dp.xml @@ -21,6 +21,12 @@ android:viewportHeight="24.0" android:tint="?android:attr/textColorSecondary"> <path - android:fillColor="#000000" - android:pathData="M11,17h2v-6h-2v6zM12,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,8zM11,9h2L13,7h-2v2z"/> + android:fillColor="#FF000000" + android:pathData="M12,17L12,17c0.55,0 1,-0.45 1,-1v-4c0,-0.55 -0.45,-1 -1,-1l0,0c-0.55,0 -1,0.45 -1,1v4C11,16.55 11.45,17 12,17z"/> + <path + android:fillColor="#FF000000" + android:pathData="M12,2c-5.52,0 -10,4.48 -10,10s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8s8,3.59 8,8S16.41,20 12,20z"/> + <path + android:fillColor="#FF000000" + android:pathData="M12,9.1L12,9.1c0.61,0 1.1,-0.49 1.1,-1.1l0,0c0,-0.61 -0.49,-1.1 -1.1,-1.1l0,0c-0.61,0 -1.1,0.49 -1.1,1.1l0,0C10.9,8.61 11.39,9.1 12,9.1z"/> </vector> diff --git a/packages/SettingsLib/res/values-af/arrays.xml b/packages/SettingsLib/res/values-af/arrays.xml index bc27c301cc8f..3c76395f2d09 100644 --- a/packages/SettingsLib/res/values-af/arrays.xml +++ b/packages/SettingsLib/res/values-af/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Gebruik stelselkeuse (verstek)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX-HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Aktiveer opsionele kodekke"</item> - <item msgid="3304843301758635896">"Deaktiveer opsionele kodekke"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Gebruik stelselkeuse (verstek)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX-HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Aktiveer opsionele kodekke"</item> - <item msgid="741805482892725657">"Deaktiveer opsionele kodekke"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Gebruik stelselkeuse (verstek)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index 866aa0fa31d0..2cb374a58386 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Laat altyd Wi-Fi-swerfskanderings toe"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiele data is altyd aktief"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardewareversnelling vir verbinding"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Deaktiveer absolute volume"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Aktiveer inband-luitoon"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP-weergawe"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Hierdie instellings is bedoel net vir ontwikkelinggebruik. Dit kan jou toestel en die programme daarop breek of vreemde dinge laat doen."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verifieer programme oor USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontroleer programme wat via ADB/ADT geïnstalleer is vir skadelike gedrag."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Deaktiveer die Bluetooth-kenmerk vir absolute volume indien daar volumeprobleme met afgeleë toestelle is, soos onaanvaarbare harde klank of geen beheer nie."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Laat toe dat luitone op die foon op Bluetooth-kopstukke gespeel word"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Plaaslike terminaal"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> oor"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> tot vol gelaai"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Onbekend"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Laai"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"laai tans"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Laai nie"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Ingeprop; kan nie op die oomblik laai nie"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Vol"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Beheer deur administrateur"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Geaktiveer deur administrateur"</string> diff --git a/packages/SettingsLib/res/values-am/arrays.xml b/packages/SettingsLib/res/values-am/arrays.xml index 79dad14e59c7..49a0123a0c23 100644 --- a/packages/SettingsLib/res/values-am/arrays.xml +++ b/packages/SettingsLib/res/values-am/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"አማራጭ ኮዴኮችን አንቃ"</item> - <item msgid="3304843301758635896">"አማራጭ ኮዴኮችን አሰናክል"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"አማራጭ ኮዴኮችን አንቃ"</item> - <item msgid="741805482892725657">"አማራጭ ኮዴኮችን አሰናክል"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item> <item msgid="8895532488906185219">"44.1 ኪኸ"</item> diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml index 100a5b239e35..c57f9b0d9339 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ሁልጊዜ የWi‑Fi ማንቀሳቀስ ቅኝቶችን ይፍቀዱ"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"የተንቀሳቃሽ ስልክ ውሂብ ሁልጊዜ ገቢር ነው"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"የሃርድዌር ማቀላጠፊያን በማስተሳሰር ላይ"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ፍጹማዊ ድምፅን አሰናክል"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"የውስጠ-ሞገድ ማስጮህን አንቃ"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"የብሉቱዝ AVRCP ስሪት"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"እነዚህ ቅንብሮች የታሰቡት ለግንባታ አጠቃቀም ብቻ ናቸው። መሳሪያህን እና በሱ ላይ ያሉትን መተግበሪያዎች እንዲበለሹ ወይም በትክክል እንዳይሰሩ ሊያደርጉ ይችላሉ።"</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"መተግበሪያዎች በUSB በኩል ያረጋግጡ"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"በADB/ADT በኩል የተጫኑ መተግበሪያዎች ጎጂ ባህሪ ካላቸው ያረጋግጡ።"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"እንደ ተቀባይነት በሌለው ደረጃ ድምፁ ከፍ ማለት ወይም መቆጣጠር አለመቻል ያሉ ከሩቅ መሣሪያዎች ጋር የድምፅ ችግር በሚኖርበት ጊዜ የብሉቱዝ ፍጹማዊ ድምፅን ባሕሪ ያሰናክላል።"</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"በስልኩ ላይ ያሉ የጥሪ ቅላጼዎች በብሉቱዝ ጆሮ ማዳመጫዎች ላይ እንዲጫወቱ ፍቀድ"</string> <string name="enable_terminal_title" msgid="95572094356054120">"አካባቢያዊ ተርሚናል"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> ይቀራል"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - ሙሉ ለሙሉ እስኪሞላ ድረስ <xliff:g id="TIME">^2</xliff:g>"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"ያልታወቀ"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"ኃይል በመሙላት ላይ"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ኃይል በመሙላት ላይ"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"ባትሪ እየሞላ አይደለም"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"ተሰክቷል፣ አሁን ኃይል መሙላት አይቻልም"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"ሙሉነው"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"በአስተዳዳሪ ቁጥጥር የተደረገበት"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"በአስተዳዳሪ ነቅቷል"</string> diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml index ea31dbe7ebc0..0af10771da0f 100644 --- a/packages/SettingsLib/res/values-ar/arrays.xml +++ b/packages/SettingsLib/res/values-ar/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"استخدام اختيار النظام (افتراضي)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"تمكين برامج الترميز الاختيارية"</item> - <item msgid="3304843301758635896">"تعطيل برامج الترميز الاختيارية"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"استخدام اختيار النظام (افتراضي)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"تمكين برامج الترميز الاختيارية"</item> - <item msgid="741805482892725657">"تعطيل برامج الترميز الاختيارية"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"استخدام اختيار النظام (افتراضي)"</item> <item msgid="8895532488906185219">"44.1 كيلو هرتز"</item> diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index 67d0a918decf..e59ad8fe9767 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -116,13 +116,13 @@ <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"ربط"</string> <string name="tether_settings_title_all" msgid="8356136101061143841">"الربط ونقطة الاتصال المحمولة"</string> <string name="managed_user_title" msgid="8109605045406748842">"كل تطبيقات العمل"</string> - <string name="user_guest" msgid="8475274842845401871">"مدعو"</string> + <string name="user_guest" msgid="8475274842845401871">"ضيف"</string> <string name="unknown" msgid="1592123443519355854">"غير معروف"</string> <string name="running_process_item_user_label" msgid="3129887865552025943">"المستخدم: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string> <string name="launch_defaults_some" msgid="313159469856372621">"تم تعيين بعض الإعدادات الافتراضية"</string> <string name="launch_defaults_none" msgid="4241129108140034876">"لم يتم تعيين إعدادات تلقائية"</string> <string name="tts_settings" msgid="8186971894801348327">"إعدادات تحويل النص إلى كلام"</string> - <string name="tts_settings_title" msgid="1237820681016639683">"إخراج تحويل النص إلى كلام"</string> + <string name="tts_settings_title" msgid="1237820681016639683">"تحويل النص إلى كلام"</string> <string name="tts_default_rate_title" msgid="6030550998379310088">"معدل سرعة الكلام"</string> <string name="tts_default_rate_summary" msgid="4061815292287182801">"سرعة نطق الكلام"</string> <string name="tts_default_pitch_title" msgid="6135942113172488671">"درجة الصوت"</string> @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"السماح دائمًا بعمليات فحص Wi-Fi للتجوال"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"بيانات الجوّال نشطة دائمًا"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"تسريع الأجهزة للتوصيل"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"تعطيل مستوى الصوت المطلق"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"تمكين الرنين ضمن النطاق الأساسي"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"إصدار Bluetooth AVRCP"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"هذه الإعدادات مخصصة لاستخدام التطوير فقط. قد يتسبب هذا في حدوث أعطال أو خلل في أداء الجهاز والتطبيقات المثبتة عليه."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"التحقق من التطبيقات عبر USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"التحقق من التطبيقات المثبتة عبر ADB/ADT لكشف السلوك الضار"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"لتعطيل ميزة مستوى الصوت المطلق للبلوتوث في حالة حدوث مشكلات متعلقة بمستوى الصوت مع الأجهزة البعيدة مثل مستوى صوت عالٍ بشكل غير مقبول أو نقص إمكانية التحكم في الصوت."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"السماح بتشغيل نغمات الرنين على الهاتف من خلال سماعات الرأس البلوتوث"</string> <string name="enable_terminal_title" msgid="95572094356054120">"تطبيق طرفي محلي"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - يتبقى <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> حتى يكتمل الشحن"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"غير معروف"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"جارٍ الشحن"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"جارٍ الشحن"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"لا يتم الشحن"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"تم التوصيل، ولكن يتعذّر الشحن الآن"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"ممتلئة"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"إعدادات يتحكم فيها المشرف"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"تم تمكين الإعداد بواسطة المشرف"</string> @@ -375,7 +377,7 @@ <string name="charge_length_format" msgid="8978516217024434156">"قبل <xliff:g id="ID_1">%1$s</xliff:g>"</string> <string name="remaining_length_format" msgid="7886337596669190587">"يتبقى <xliff:g id="ID_1">%1$s</xliff:g>"</string> <string name="screen_zoom_summary_small" msgid="5867245310241621570">"صغير"</string> - <string name="screen_zoom_summary_default" msgid="2247006805614056507">"افتراضي"</string> + <string name="screen_zoom_summary_default" msgid="2247006805614056507">"تلقائي"</string> <string name="screen_zoom_summary_large" msgid="4835294730065424084">"كبير"</string> <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"أكبر"</string> <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"أكبر مستوى"</string> diff --git a/packages/SettingsLib/res/values-az/arrays.xml b/packages/SettingsLib/res/values-az/arrays.xml index b25b38252c53..38e94ec820e5 100644 --- a/packages/SettingsLib/res/values-az/arrays.xml +++ b/packages/SettingsLib/res/values-az/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Sistem Seçimini istifadə edin (Defolt)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Şəxsi Kodekləri Aktiv edin"</item> - <item msgid="3304843301758635896">"Şəxsi Kodekləri Deaktiv edin"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Sistem Seçimini istifadə edin (Defolt)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Şəxsi Kodekləri Aktiv edin"</item> - <item msgid="741805482892725657">"Şəxsi Kodekləri Deaktiv edin"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Sistem Seçimini istifadə edin (Defolt)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml index 1732c87212c5..1ec5d62e088d 100644 --- a/packages/SettingsLib/res/values-az/strings.xml +++ b/packages/SettingsLib/res/values-az/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi axtarışlarına həmişə icazə verin"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobil data həmişə aktiv"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Birləşmə üçün avadanlıq akselerasiyası"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Mütləq səs həcmi deaktiv edin"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Diapazon daxili zəngi aktiv edin"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP Versiya"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Bu parametrlər yalnız inkişafetdirici istifadə üçün nəzərdə tutulub. Onlar cihaz və tətbiqlərinizin sınması və ya pis işləməsinə səbəb ola bilər."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB üzərindən tətbiqləri yoxlayın"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT vasitəsi ilə quraşdırılmış tətbiqləri zərərli davranış üzrə yoxlayın."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Uzaqdan idarə olunan cihazlarda dözülməz yüksək səs həcmi və ya nəzarət çatışmazlığı kimi səs problemləri olduqda Bluetooth mütləq səs həcmi xüsusiyyətini deaktiv edir."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Telefondakı bütün melodiyaların Bluetooth qulaqlıqlarında oxudulmasına icazə verin"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Yerli terminal"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> qalıb"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> tam enerji yığana kimi"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Naməlum"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Enerji doldurma"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"enerji yığır"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Doldurulmur"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Cihaz hazırda batareya yığa bilmir"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Tam"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Admin tərəfindən nəzarət olunur"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Admin tərəfindən aktiv edildi"</string> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml index 0bfda36a37d6..884f55bbecf8 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Koristi izbor sistema (podrazumevano)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Omogući opcionalne kodeke"</item> - <item msgid="3304843301758635896">"Onemogući opcionalne kodeke"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Koristi izbor sistema (podrazumevano)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Omogući opcionalne kodeke"</item> - <item msgid="741805482892725657">"Onemogući opcionalne kodeke"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Koristi izbor sistema (podrazumevano)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml index 3336164bacfb..d0427c9ecc5c 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvek dozvoli skeniranje Wi‑Fi-ja u romingu"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilni podaci su uvek aktivni"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzanje privezivanja"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogući glavno podešavanje jačine zvuka"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Omogućavanje zvonjave na istom kanalu"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Verzija Bluetooth AVRCP-a"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Ova podešavanja su namenjena samo za programiranje. Mogu da izazovu prestanak funkcionisanja ili neočekivano ponašanje uređaja i aplikacija na njemu."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verifikuj aplikacije preko USB-a"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Proverava da li su aplikacije instalirane preko ADB-a/ADT-a štetne."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Onemogućava glavno podešavanje jačine zvuka na Bluetooth uređaju u slučaju problema sa jačinom zvuka na daljinskim uređajima, kao što su izuzetno velika jačina zvuka ili nedostatak kontrole."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Omogućite da se melodija zvona na telefonu pušta preko Bluetooth slušalica"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Lokalni terminal"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"Preostalo je <xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> do potpunog punjenja"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Punjenje"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"puni se"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Ne puni se"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Priključeno je, ali punjenje trenutno nije moguće"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Puno"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontroliše administrator"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Omogućio je administrator"</string> diff --git a/packages/SettingsLib/res/values-be/arrays.xml b/packages/SettingsLib/res/values-be/arrays.xml index 8ea31e58943e..0e887e53b99a 100644 --- a/packages/SettingsLib/res/values-be/arrays.xml +++ b/packages/SettingsLib/res/values-be/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Выбар сістэмы (стандартны)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Уключыць дадатковыя кодэкі"</item> - <item msgid="3304843301758635896">"Адключыць дадатковыя кодэкі"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Выбар сістэмы (стандартны)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Уключыць дадатковыя кодэкі"</item> - <item msgid="741805482892725657">"Адключыць дадатковыя кодэкі"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Выбар сістэмы (стандартны)"</item> <item msgid="8895532488906185219">"44,1 кГц"</item> diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml index b50285f04bc6..363a904cc9b2 100644 --- a/packages/SettingsLib/res/values-be/strings.xml +++ b/packages/SettingsLib/res/values-be/strings.xml @@ -119,7 +119,7 @@ <string name="user_guest" msgid="8475274842845401871">"Госць"</string> <string name="unknown" msgid="1592123443519355854">"Невядома"</string> <string name="running_process_item_user_label" msgid="3129887865552025943">"Карыстальнiк: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string> - <string name="launch_defaults_some" msgid="313159469856372621">"Некат. параметры па змаўч. усталяваныя"</string> + <string name="launch_defaults_some" msgid="313159469856372621">"Усталяваны некаторыя стандартныя налады"</string> <string name="launch_defaults_none" msgid="4241129108140034876">"Параметры па змаўчанні не ўсталяваныя"</string> <string name="tts_settings" msgid="8186971894801348327">"Налады Text-to-speech"</string> <string name="tts_settings_title" msgid="1237820681016639683">"Сінтэз маўлення"</string> @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Заўсёды дазваляць роўмінгавае сканіраванне Wi‑Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Мабільная перадача даных заўсёды актыўная"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Апаратнае паскарэнне ў рэжыме мадэма"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Адключыць абсалютны гук"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Уключыць унутрыпалосны празвон"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Версія Bluetooth AVRCP"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Гэтыя налады прызначаны толькi для распрацоўшыкаў. Яны могуць выклікаць збоi прылад i ўсталяваных на iх прыкладанняў, а таксама перашкаджаць iх працы."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Праверце прыкладаннi па USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Праверце прыкладаннi, усталяваныя з дапамогай ADB/ADT, на нестабiльныя паводзiны."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Адключыць функцыю абсалютнага гуку Bluetooth у выпадку праблем з гукам на аддаленых прыладах, напр., пры непрымальна высокай гучнасці або адсутнасці кіравання."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Дазволіць прайграванне рынгтонаў на тэлефоне праз гарнітуры Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Лакальны тэрмінал"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – засталося <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> да поўнай зарадкі"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Невядома"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Зарадка"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ідзе зарадка"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Не зараджаецца"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Падключана да сеткі сілкавання, зарадзіць зараз немагчыма"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Поўная"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Кантралюецца адміністратарам"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Уключана адміністратарам"</string> diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml index 3f25978791ec..2017886f929e 100644 --- a/packages/SettingsLib/res/values-bg/arrays.xml +++ b/packages/SettingsLib/res/values-bg/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"Използване на сист. избор (стандартно)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"Разширено аудиокодиране (AAC)"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"Аудио: <xliff:g id="APTX">aptX™</xliff:g> от <xliff:g id="QUALCOMM">Qualcomm®</xliff:g>"</item> + <item msgid="2091430979086738145">"Аудио: <xliff:g id="APTX_HD">aptX™ HD</xliff:g> от <xliff:g id="QUALCOMM">Qualcomm®</xliff:g>"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"Активиране на кодеците по избор"</item> <item msgid="3304843301758635896">"Деактивиране на кодеците по избор"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"Използване на сист. избор (стандартно)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"Разширено аудиокодиране (AAC)"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"Аудио: <xliff:g id="APTX">aptX™</xliff:g> от <xliff:g id="QUALCOMM">Qualcomm®</xliff:g>"</item> + <item msgid="298198075927343893">"Аудио: <xliff:g id="APTX_HD">aptX™ HD</xliff:g> от <xliff:g id="QUALCOMM">Qualcomm®</xliff:g>"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"Активиране на кодеците по избор"</item> <item msgid="741805482892725657">"Деактивиране на кодеците по избор"</item> diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index ef3f1f6b6abc..43859e0c87df 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Сканирането за роуминг на Wi-Fi да е разрешено винаги"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Винаги активни мобилни данни"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Хардуерно ускорение за тетъринга"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Деактивиране на пълната сила на звука"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Активиране на звъненето в една и съща честотна лента"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Версия на AVRCP за Bluetooth"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Тези настройки са предназначени само за програмиране. Те могат да доведат до прекъсване на работата или неправилно функциониране на устройството ви и приложенията в него."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Потвържд. на прил. през USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Проверка на инсталираните чрез ADB/ADT приложения за опасно поведение."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Деактивира функцията на Bluetooth за пълна сила на звука в случай на проблеми със звука на отдалечени устройства, като например неприемливо висока сила на звука или липса на управление."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Разрешаване на мелодиите на телефона да се възпроизвеждат на слушалките с Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Локален терминал"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – оставащо време: <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> до пълно зареждане"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Неизвестно"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Зарежда се"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"зарежда се"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Не се зарежда"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Включена в захранването, в момента не се зарежда"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Пълна"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Контролира се от администратор"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Активирано от администратора"</string> diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml index 4d5c1f19b726..9f35159a8801 100644 --- a/packages/SettingsLib/res/values-bn/arrays.xml +++ b/packages/SettingsLib/res/values-bn/arrays.xml @@ -24,7 +24,7 @@ <item msgid="1922181315419294640"></item> <item msgid="8934131797783724664">"স্ক্যান করা হচ্ছে…"</item> <item msgid="8513729475867537913">"সংযুক্ত হচ্ছে..."</item> - <item msgid="515055375277271756">"প্রমাণীকরণ হচ্ছে..."</item> + <item msgid="515055375277271756">"যাচাইকরণ হচ্ছে..."</item> <item msgid="1943354004029184381">"IP ঠিকানা প্রাপ্ত করা হচ্ছে..."</item> <item msgid="4221763391123233270">"সংযুক্ত হয়েছে"</item> <item msgid="624838831631122137">"স্থগিত করা হয়েছে"</item> @@ -38,7 +38,7 @@ <item msgid="7714855332363650812"></item> <item msgid="8878186979715711006">"স্ক্যান করা হচ্ছে…"</item> <item msgid="355508996603873860">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> এর সাথে সংযুক্ত হচ্ছে…"</item> - <item msgid="554971459996405634">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> দিয়ে প্রমাণীকরণ করা হচ্ছে..."</item> + <item msgid="554971459996405634">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> দিয়ে যাচাইকরণ করা হচ্ছে..."</item> <item msgid="7928343808033020343">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> থেকে IP ঠিকানা জানা হচ্ছে…"</item> <item msgid="8937994881315223448">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> তে সংযুক্ত হয়েছে"</item> <item msgid="1330262655415760617">"স্থগিত করা হয়েছে"</item> @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"ঐচ্ছিক কোডেক সক্ষম করুন"</item> - <item msgid="3304843301758635896">"ঐচ্ছিক কোডেক অক্ষম করুন"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"ঐচ্ছিক কোডেক সক্ষম করুন"</item> - <item msgid="741805482892725657">"ঐচ্ছিক কোডেক অক্ষম করুন"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item> <item msgid="8895532488906185219">"৪৪.১ kHz"</item> @@ -224,7 +208,7 @@ </string-array> <string-array name="track_frame_time_entries"> <item msgid="2193584639058893150">"বন্ধ করুন"</item> - <item msgid="2751513398307949636">"দন্ড হিসাবে স্ক্রীনে"</item> + <item msgid="2751513398307949636">"দন্ড হিসেবে স্ক্রীনে"</item> <item msgid="2355151170975410323">"<xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g> এ"</item> </string-array> <string-array name="debug_hw_overdraw_entries"> diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml index 2cf27305b708..593f5ca5ad18 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -27,7 +27,7 @@ <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP কনফিগারেশনের ব্যর্থতা"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"খারাপ নেটওয়ার্কের কারণে সংযুক্ত নয়"</string> <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"ওয়াই ফাই সংযোগের ব্যর্থতা"</string> - <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"প্রমাণীকরণ সমস্যা"</string> + <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"যাচাইকরণ সমস্যা"</string> <string name="wifi_cant_connect" msgid="5410016875644565884">"সংযোগ স্থাপন করা যাচ্ছে না"</string> <string name="wifi_cant_connect_to_ap" msgid="1222553274052685331">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\'এ যোগ করা যায়নি"</string> <string name="wifi_check_password_try_again" msgid="516958988102584767">"পাসওয়ার্ড দেখে আবার চেষ্টা করুন"</string> @@ -54,7 +54,7 @@ <string name="bluetooth_disconnecting" msgid="8913264760027764974">"সংযোগ বিচ্ছিন্ন হচ্ছে..."</string> <string name="bluetooth_connecting" msgid="8555009514614320497">"সংযুক্ত হচ্ছে..."</string> <string name="bluetooth_connected" msgid="6038755206916626419">"সংযুক্ত হয়েছে"</string> - <string name="bluetooth_pairing" msgid="1426882272690346242">"যুক্ত করা হচ্ছে..."</string> + <string name="bluetooth_pairing" msgid="1426882272690346242">"চেনানো হচ্ছে..."</string> <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"সংযুক্ত (কোনো ফোন নেই)"</string> <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"সংযুক্ত (কোনো মিডিয়া নেই)"</string> <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"সংযুক্ত (কোনো বার্তা অ্যাক্সেস নেই)"</string> @@ -94,11 +94,11 @@ <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"যুক্ত করুন"</string> <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"যুক্ত করুন"</string> <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"বাতিল করুন"</string> - <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"যুক্ত করা থাকলে তা সংযুক্ত থাকাকালীন অবস্থায় আপনার পরিচিতিগুলি এবং কলের ইতিহাসকে অ্যাক্সেস করতে অনুমোদিত করে৷"</string> - <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> এর সাথে যুক্ত করা যায়নি।"</string> - <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"ভুল পিন বা পাস কী দেওয়ার কারণে <xliff:g id="DEVICE_NAME">%1$s</xliff:g> এর সঙ্গে যুক্ত করা যায়নি।"</string> + <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"চেনানো থাকলে তা সংযুক্ত থাকাকালীন অবস্থায় আপনার পরিচিতিগুলি এবং কলের ইতিহাসকে অ্যাক্সেস করতে অনুমোদিত করে৷"</string> + <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> এর সাথে চেনানো যায়নি।"</string> + <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"ভুল পিন বা কোড দেওয়ার কারণে <xliff:g id="DEVICE_NAME">%1$s</xliff:g> এর সঙ্গে চেনানো যায়নি।"</string> <string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> এর সঙ্গে যোগাযোগ করতে পারবেন না।"</string> - <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"যুক্ত করা <xliff:g id="DEVICE_NAME">%1$s</xliff:g> প্রত্যাখ্যান করেছে।"</string> + <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"চেনানো <xliff:g id="DEVICE_NAME">%1$s</xliff:g> প্রত্যাখ্যান করেছে।"</string> <string name="accessibility_wifi_off" msgid="1166761729660614716">"ওয়াই ফাই বন্ধ৷"</string> <string name="accessibility_no_wifi" msgid="8834610636137374508">"ওয়াই ফাই এর সংযোগ বিচ্ছিন্ন হয়েছে৷"</string> <string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"ওয়াই ফাই এ একটি দণ্ড৷"</string> @@ -148,7 +148,7 @@ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"পছন্দের ইঞ্জিন"</string> <string name="tts_general_section_title" msgid="4402572014604490502">"সাধারণ"</string> <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"ভাষ্য়ের শব্দ মাত্রাকে আবার সেট করুন"</string> - <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"ডিফল্ট হিসাবে যে মাত্রায় পাঠ্য উচ্চারিত হয়, সেই শব্দ মাত্রাকে আবার সেট করুন৷"</string> + <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"ডিফল্ট হিসেবে যে মাত্রায় পাঠ্য উচ্চারিত হয়, সেই শব্দ মাত্রাকে আবার সেট করুন৷"</string> <string-array name="tts_rate_entries"> <item msgid="6695494874362656215">"অত্যন্ত ধীরে"</item> <item msgid="4795095314303559268">"ধীর"</item> @@ -163,10 +163,10 @@ <string name="choose_profile" msgid="6921016979430278661">"প্রোফাইল বেছে নিন"</string> <string name="category_personal" msgid="1299663247844969448">"ব্যক্তিগত"</string> <string name="category_work" msgid="8699184680584175622">"কর্মক্ষেত্র"</string> - <string name="development_settings_title" msgid="215179176067683667">"বিকাশকারী বিকল্পগুলি"</string> - <string name="development_settings_enable" msgid="542530994778109538">"বিকাশকারী বিকল্পগুলি সক্ষম করুন"</string> + <string name="development_settings_title" msgid="215179176067683667">"ডেভেলপার বিকল্প"</string> + <string name="development_settings_enable" msgid="542530994778109538">"ডেভেলপার বিকল্প সক্ষম করুন"</string> <string name="development_settings_summary" msgid="1815795401632854041">"অ্যাপ্লিকেশান উন্নয়নের জন্য বিকল্পগুলি সেট করুন"</string> - <string name="development_settings_not_available" msgid="4308569041701535607">"এই ব্যবহারকারীর জন্য বিকাশকারী বিকল্পগুলি উপলব্ধ নয়"</string> + <string name="development_settings_not_available" msgid="4308569041701535607">"এই ব্যবহারকারীর জন্য ডেভেলপার বিকল্প উপলব্ধ নয়"</string> <string name="vpn_settings_not_available" msgid="956841430176985598">"এই ব্যবহারকারীর জন্য VPN সেটিংস উপলব্ধ নয়"</string> <string name="tethering_settings_not_available" msgid="6765770438438291012">"এই ব্যবহারকারীর জন্য টেদারিং সেটিংস উপলব্ধ নয়"</string> <string name="apn_settings_not_available" msgid="7873729032165324000">"এই ব্যবহারকারীর জন্য অ্যাক্সেস পয়েন্ট নাম সেটিংস উপলব্ধ নয়"</string> @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"সর্বদা ওয়াই ফাই রোম স্ক্যানকে অনুমতি দিন"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"মোবাইল ডেটা সব সময় সক্রিয় থাক"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"টিথারিং হার্ডওয়্যার অ্যাক্সিলারেশন"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"চূড়ান্ত ভলিউম অক্ষম করুন"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"ইন-ব্যান্ড রিং করা সক্ষম করুন"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ব্লুটুথ AVRCP সংস্করণ"</string> @@ -230,8 +232,10 @@ <string name="adb_keys_warning_message" msgid="5659849457135841625">"আপনি আগে যে সব কম্পিউটার USB ডিবাগিং এর অ্যাক্সেসের অনুমতি দিয়েছিলেন তা প্রত্যাহার করবেন?"</string> <string name="dev_settings_warning_title" msgid="7244607768088540165">"উন্নতি সেটিংসের অনুমতি দেবেন?"</string> <string name="dev_settings_warning_message" msgid="2298337781139097964">"এইসব সেটিংস কেবলমাত্র উন্নত করার উদ্দেশ্য। সেগুলি কারণে আপনার ডিভাইস ভেঙ্গে এবং অ্যাপ্লিকেশানগুলি ভালো ভাবে কাজ করা নাও কারতে পারে।"</string> - <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB এর অ্যাপ্লিকেশানগুলি যাচাই করুন"</string> + <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB এর অ্যাপ্লিকেশনগুলি যাচাই করুন"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ক্ষতিকারক ক্রিয়াকলাপ করছে কিনা তার জন্য ADB/ADT মারফত ইনস্টল করা অ্যাপ্লিকেশানগুলি চেক করুন।"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"অপ্রত্যাশিত উচ্চ ভলিউম বা নিয়ন্ত্রণের অভাবের মত দূরবর্তী ডিভাইসের ভলিউম সমস্যাগুলির ক্ষেত্রে, ব্লুটুথ চুড়ান্ত ভলিউম বৈশিষ্ট্য অক্ষম করে৷"</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ফোনের রিংটোন ব্লুটুথ হেডসেটে শোনা সক্ষম করুন"</string> <string name="enable_terminal_title" msgid="95572094356054120">"স্থানীয় টার্মিনাল"</string> @@ -247,7 +251,7 @@ <string name="wait_for_debugger" msgid="1202370874528893091">"ডিবাগারের জন্য অপেক্ষা করুন"</string> <string name="wait_for_debugger_summary" msgid="1766918303462746804">"চালানোর আগে সংযুক্ত করতে জন্য ডিবাগ করা অ্যাপ্লিকেশনটি ডিবাগারের জন্য অপেক্ষা করছে"</string> <string name="telephony_monitor_switch" msgid="1764958220062121194">"টেলিফোনি মনিটর"</string> - <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"টেলিফোনি মনিটর টেলিফোনি/মোডেমের কার্যকারিতায় কোনো সমস্যা শনাক্ত করলে সমস্যাটি লগ করবে এবং সমস্যাটি জানাতে একটি বাগ ফাইল করার জন্য ব্যবহারকারিকে বিজ্ঞপ্তি পাঠাবে"</string> + <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"টেলিফোনি মনিটর টেলিফোনি/মোডেমের কার্যকারিতায় কোনও সমস্যা শনাক্ত করলে সমস্যাটি লগ করবে এবং সমস্যাটি জানাতে একটি বাগ ফাইল করার জন্য ব্যবহারকারিকে বিজ্ঞপ্তি পাঠাবে"</string> <string name="debug_input_category" msgid="1811069939601180246">"ইনপুট"</string> <string name="debug_drawing_category" msgid="6755716469267367852">"অঙ্কন"</string> <string name="debug_hw_drawing_category" msgid="6220174216912308658">"হার্ডওয়্যার দ্বারা চালিত রেন্ডারিং"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> বাকী আছে"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - সম্পূর্ণ চার্জ হতে <xliff:g id="TIME">^2</xliff:g> লাগবে"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"অজানা"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"চার্জ হচ্ছে"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"চার্জ হচ্ছে"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"চার্জ হচ্ছে না"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"প্লাগ-ইন করা হয়েছে কিন্তু এখনই চার্জ করা যাবে না"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"পূর্ণ"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"প্রশাসকের দ্বারা নিয়ন্ত্রিত"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"প্রশাসক দ্বারা সক্ষম করা হয়েছে"</string> diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml index 2bfb4a574970..c27f4e819727 100644 --- a/packages/SettingsLib/res/values-bs/arrays.xml +++ b/packages/SettingsLib/res/values-bs/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Koristi odabir sistema (Zadano)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Omogućite opcionalne kodeke"</item> - <item msgid="3304843301758635896">"Onemogućite opcionalne kodeke"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Koristi odabir sistema (Zadano)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Omogućite opcionalne kodeke"</item> - <item msgid="741805482892725657">"Onemogućite opcionalne kodeke"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Koristi odabir sistema (Zadano)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml index 614bdb1ba3ac..bbea335abf94 100644 --- a/packages/SettingsLib/res/values-bs/strings.xml +++ b/packages/SettingsLib/res/values-bs/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvijek dopustiti Wi-Fi lutajuće skeniranje"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilna mreža za prijenos podataka je uvijek aktivna"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzavanje dijeljenja veze"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogućite apsolutnu jačinu zvuka"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Omogući zvono unutar pojasa"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP verzija"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Ove postavke su namijenjene samo za svrhe razvoja. Mogu izazvati pogrešno ponašanje uređaja i aplikacija na njemu."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verifikuj aplikacije putem USB-a"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Provjerava da li se u aplikacijama instaliranim putem ADB-a/ADT-a javlja zlonamerno ponašanje."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Onemogućava opciju Bluetooth apsolutne jačine zvuka u slučaju problema s jačinom zvuka na udaljenim uređajima, kao što je neprihvatljivo glasan zvuk ili nedostatak kontrole."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Dopusti da se melodije zvona reproduciranju na Bluetooth slušalicama"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Lokalni terminal"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - imate još <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> do potpune napunjenosti"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Punjenje"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"punjenje"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Ne puni se"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Priključen, trenutno se ne može puniti"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Puna"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Pod kontrolom administratora"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Omogućio administrator"</string> diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml index bdc2cacd4a86..ca910cdc5f55 100644 --- a/packages/SettingsLib/res/values-ca/arrays.xml +++ b/packages/SettingsLib/res/values-ca/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"Utilitza selecció del sistema (predeterminada)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="2091430979086738145">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"Activa els còdecs opcionals"</item> <item msgid="3304843301758635896">"Desactiva els còdecs opcionals"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"Utilitza selecció del sistema (predeterminada)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="298198075927343893">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"Activa els còdecs opcionals"</item> <item msgid="741805482892725657">"Desactiva els còdecs opcionals"</item> diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index b2b2b1cc372a..a0261231b5a8 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permet sempre cerca de Wi-Fi en ininerància"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Dades mòbils sempre actives"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Acceleració per maquinari per compartir la xarxa"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desactiva el volum absolut"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Activa el so al mateix canal"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versió AVRCP de Bluetooth"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Aquesta configuració només està prevista per a usos de desenvolupament. Pot fer que el dispositiu i que les aplicacions s\'interrompin o tinguin un comportament inadequat."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verifica aplicacions per USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Comprova les aplicacions instal·lades mitjançant ADB/ADT per detectar possibles comportaments perillosos"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desactiva la funció de volum absolut de Bluetooth en cas que es produeixin problemes de volum amb dispositius remots, com ara un volum massa alt o una manca de control."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Permet que els sons de trucada del telèfon es reprodueixin en auriculars amb Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g>; temps restant: <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g>: <xliff:g id="TIME">^2</xliff:g> per completar la càrrega"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g>: <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconegut"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"S\'està carregant"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"s\'està carregant"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"No s\'està carregant"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"El dispositiu està endollat però en aquests moments no es pot carregar"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Plena"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlat per l\'administrador"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Activada per l\'administrador"</string> diff --git a/packages/SettingsLib/res/values-cs/arrays.xml b/packages/SettingsLib/res/values-cs/arrays.xml index 7457308b80a8..73e41f34e1ba 100644 --- a/packages/SettingsLib/res/values-cs/arrays.xml +++ b/packages/SettingsLib/res/values-cs/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Použít systémový výběr (výchozí)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Povolit volitelné kodeky"</item> - <item msgid="3304843301758635896">"Zakázat volitelné kodeky"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Použít systémový výběr (výchozí)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Povolit volitelné kodeky"</item> - <item msgid="741805482892725657">"Zakázat volitelné kodeky"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Použít systémový výběr (výchozí)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index fcb0b028a251..e6e91cd9a20a 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vždy povolit Wi-Fi roaming"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilní data jsou vždy aktivní"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwarová akcelerace tetheringu"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Zakázat absolutní hlasitost"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Povolit vyzvánění v hovorovém pásmu"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Verze profilu Bluetooth AVRCP"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Tato nastavení jsou určena pouze pro vývojáře. Mohou způsobit rozbití nebo nesprávné fungování zařízení a nainstalovaných aplikací."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Ověřit aplikace z USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrolovat škodlivost aplikací nainstalovaných pomocí nástroje ADB/ADT"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Zakáže funkci absolutní hlasitosti Bluetooth. Zabrání tak problémům s hlasitostí vzdálených zařízení (jako je příliš vysoká hlasitost nebo nemožnost ovládání)."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Umožňuje přehrávat vyzváněcí tóny z telefonu v náhlavní soupravě Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Místní terminál"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – zbývá <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – plně se nabije za <xliff:g id="TIME">^2</xliff:g>"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Neznámé"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Nabíjí se"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"nabíjení"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Nenabíjí se"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Zapojeno, ale nelze nabíjet"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Nabitá"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Spravováno administrátorem"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Zapnuto administrátorem"</string> diff --git a/packages/SettingsLib/res/values-da/arrays.xml b/packages/SettingsLib/res/values-da/arrays.xml index 6c322ed741bb..fe0b1fc4eafa 100644 --- a/packages/SettingsLib/res/values-da/arrays.xml +++ b/packages/SettingsLib/res/values-da/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Brug systemvalg (standard)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Aktivér Optional Codecs"</item> - <item msgid="3304843301758635896">"Deaktiver Optional Codecs"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Brug systemvalg (standard)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Aktivér Optional Codecs"</item> - <item msgid="741805482892725657">"Deaktiver Optional Codecs"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Brug systemvalg (standard)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index 1c40c524db06..a18a4a452653 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillad altid scanning af Wi-Fi-roaming"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobildata er altid aktiveret"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwareacceleration ved netdeling"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Deaktiver absolut lydstyrke"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Afspil ringetone via Bluetooth"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"AVRCP-version for Bluetooth"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Disse indstillinger er kun beregnet til brug i forbindelse med udvikling. De kan forårsage, at din enhed og dens applikationer går ned eller ikke fungerer korrekt."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificer apps via USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Tjek apps, der er installeret via ADB/ADT, for skadelig adfærd."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Deaktiverer funktionen til absolut lydstyrke via Bluetooth i tilfælde af problemer med lydstyrken på eksterne enheder, f.eks. uacceptabel høj lyd eller manglende kontrol."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Tillad, at ringetoner på telefonen kan afspilles i Bluetooth-headset"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Lokal terminal"</string> @@ -303,7 +307,7 @@ <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Aktivér understøttelse af eksperimentelle vinduer i frit format."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Kode til lokal sikkerhedskopi"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Lokale fuldstændige sikkerhedskopieringer er i øjeblikket ikke beskyttet"</string> - <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tryk for at skifte eller fjerne adgangskoden til fuld lokal sikkerhedskopiering"</string> + <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tryk for at skifte eller fjerne adgangskoden til fuld lokal backup"</string> <string name="local_backup_password_toast_success" msgid="582016086228434290">"Ny adgangskode til sikkerhedskopi er angivet"</string> <string name="local_backup_password_toast_confirmation_mismatch" msgid="7805892532752708288">"Ny adgangskode og bekræftelse matcher ikke"</string> <string name="local_backup_password_toast_validation_failure" msgid="5646377234895626531">"Fejl ved angivelse af adgangskode til sikkerhedskopi"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> tilbage"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> til det er fuldt opladet"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Ukendt"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Oplader"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"oplader"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Oplader ikke"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Enheden er tilsluttet en strømkilde. Det er ikke muligt at oplade på nuværende tidspunkt."</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Fuld"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontrolleret af administratoren"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Aktiveret af administratoren"</string> diff --git a/packages/SettingsLib/res/values-de/arrays.xml b/packages/SettingsLib/res/values-de/arrays.xml index 2c441a508117..14d9bf1d9be4 100644 --- a/packages/SettingsLib/res/values-de/arrays.xml +++ b/packages/SettingsLib/res/values-de/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Systemauswahl verwenden (Standard)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Optionale Codecs aktivieren"</item> - <item msgid="3304843301758635896">"Optionale Codecs deaktivieren"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Systemauswahl verwenden (Standard)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Optionale Codecs aktivieren"</item> - <item msgid="741805482892725657">"Optionale Codecs deaktivieren"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Systemauswahl verwenden (Standard)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index 8c0e7271b0c8..309b75b5d8c5 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"WLAN-Roamingsuchen immer zulassen"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile Datennutzung immer aktiviert"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwarebeschleunigung für Tethering"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Maximallautstärke deaktivieren"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"In-Band-Klingeln aktivieren"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP-Version"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Diese Einstellungen sind ausschließlich für Entwicklungszwecke gedacht. Sie können dein Gerät und die darauf installierten Apps beschädigen oder zu unerwünschtem Verhalten führen."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Apps über USB bestätigen"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Überprüft installierte Apps über ADB/ADT auf schädliches Verhalten"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Deaktiviert die Bluetooth-Maximallautstärkefunktion, falls auf Remote-Geräten Probleme mit der Lautstärke auftreten, wie beispielsweise übermäßig laute Wiedergabe oder fehlende Kontrolle bei der Steuerung."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Wiedergabe von Smartphone-Klingeltönen auf Bluetooth-Headsets zulassen"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Lokales Terminal"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – noch <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> bis vollständig geladen"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Unbekannt"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Wird aufgeladen"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"wird aufgeladen..."</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Wird nicht geladen"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Angeschlossen, kann derzeit nicht geladen werden"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Voll"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Durch den Administrator verwaltet"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Vom Administrator aktiviert"</string> diff --git a/packages/SettingsLib/res/values-el/arrays.xml b/packages/SettingsLib/res/values-el/arrays.xml index 2f86aa755ac4..a900b240fb62 100644 --- a/packages/SettingsLib/res/values-el/arrays.xml +++ b/packages/SettingsLib/res/values-el/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="2091430979086738145">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"Ενεργοποίηση προαιρετικών κωδικοποιητών"</item> <item msgid="3304843301758635896">"Απενεργοποίηση προαιρετικών κωδικοποιητών"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="298198075927343893">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"Ενεργοποίηση προαιρετικών κωδικοποιητών"</item> <item msgid="741805482892725657">"Απενεργοποίηση προαιρετικών κωδικοποιητών"</item> diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml index 46aa2c5a23c5..bfaa7789287c 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Να επιτρέπεται πάντα η σάρωση Wi-Fi κατά την περιαγωγή"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Πάντα ενεργά δεδομένα κινητής τηλεφωνίας"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Σύνδεση επιτάχυνσης υλικού"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Απενεργοποίηση απόλυτης έντασης"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Ενεργοποίηση κλήσης εντός εύρους"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Έκδοση AVRCP Bluetooth"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Αυτές οι ρυθμίσεις προορίζονται για χρήση κατά την ανάπτυξη. Μπορούν να προκαλέσουν προβλήματα στη λειτουργία της συσκευής και των εφαρμογών σας."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Επαλήθευση εφαρμογών μέσω USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Έλεγχος εφαρμογών που έχουν εγκατασταθεί μέσω ADB/ADT για επιβλαβή συμπεριφορά."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Απενεργοποιεί τη δυνατότητα απόλυτης έντασης του Bluetooth σε περίπτωση προβλημάτων έντασης με απομακρυσμένες συσκευές, όπως όταν υπάρχει μη αποδεκτά υψηλή ένταση ή απουσία ελέγχου."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Να επιτρέπεται η αναπαραγωγή των ήχων κλήσης του τηλεφώνου στα ακουστικά Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Τοπική τερματική εφαρμογή"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - απομένει/ουν <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> για πλήρη φόρτιση"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Άγνωστο"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Φόρτιση"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"φόρτιση"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Δεν φορτίζει"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Συνδέθηκε, δεν είναι δυνατή η φόρτιση αυτήν τη στιγμή"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Πλήρης"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Ελέγχονται από το διαχειριστή"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Ενεργοποιήθηκε από τον διαχειριστή"</string> diff --git a/packages/SettingsLib/res/values-en-rAU/arrays.xml b/packages/SettingsLib/res/values-en-rAU/arrays.xml index 77af30ecb6f8..55feafa87a95 100644 --- a/packages/SettingsLib/res/values-en-rAU/arrays.xml +++ b/packages/SettingsLib/res/values-en-rAU/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"Use System Selection (Default)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> + <item msgid="2091430979086738145">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"Enable Optional Codecs"</item> <item msgid="3304843301758635896">"Disable Optional Codecs"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"Use System Selection (Default)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> + <item msgid="298198075927343893">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"Enable Optional Codecs"</item> <item msgid="741805482892725657">"Disable Optional Codecs"</item> diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml index bbc114463582..db8cfa1fa436 100644 --- a/packages/SettingsLib/res/values-en-rAU/strings.xml +++ b/packages/SettingsLib/res/values-en-rAU/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disable absolute volume"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Enable in-band ringing"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP Version"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"These settings are intended for development use only. They can cause your device and the applications on it to break or misbehave."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verify apps over USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Check apps installed via ADB/ADT for harmful behaviour."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Allow ringtones on the phone to be played on Bluetooth headsets"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Local terminal"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> left"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> until fully charged"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"charging"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Not charging"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Plugged in, can\'t charge right now"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Full"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlled by admin"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Enabled by admin"</string> diff --git a/packages/SettingsLib/res/values-en-rCA/arrays.xml b/packages/SettingsLib/res/values-en-rCA/arrays.xml new file mode 100644 index 000000000000..55feafa87a95 --- /dev/null +++ b/packages/SettingsLib/res/values-en-rCA/arrays.xml @@ -0,0 +1,255 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** +** Copyright 2015 The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string-array name="wifi_status"> + <item msgid="1922181315419294640"></item> + <item msgid="8934131797783724664">"Scanning…"</item> + <item msgid="8513729475867537913">"Connecting…"</item> + <item msgid="515055375277271756">"Authenticating…"</item> + <item msgid="1943354004029184381">"Obtaining IP address…"</item> + <item msgid="4221763391123233270">"Connected"</item> + <item msgid="624838831631122137">"Suspended"</item> + <item msgid="7979680559596111948">"Disconnecting…"</item> + <item msgid="1634960474403853625">"Disconnected"</item> + <item msgid="746097431216080650">"Unsuccessful"</item> + <item msgid="6367044185730295334">"Blocked"</item> + <item msgid="503942654197908005">"Temporarily avoiding poor connection"</item> + </string-array> + <string-array name="wifi_status_with_ssid"> + <item msgid="7714855332363650812"></item> + <item msgid="8878186979715711006">"Scanning…"</item> + <item msgid="355508996603873860">"Connecting to <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item> + <item msgid="554971459996405634">"Authenticating with <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item> + <item msgid="7928343808033020343">"Obtaining IP address from <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item> + <item msgid="8937994881315223448">"Connected to <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</item> + <item msgid="1330262655415760617">"Suspended"</item> + <item msgid="7698638434317271902">"Disconnecting from <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item> + <item msgid="197508606402264311">"Disconnected"</item> + <item msgid="8578370891960825148">"Unsuccessful"</item> + <item msgid="5660739516542454527">"Blocked"</item> + <item msgid="1805837518286731242">"Temporarily avoiding poor connection"</item> + </string-array> + <string-array name="hdcp_checking_titles"> + <item msgid="441827799230089869">"Never check"</item> + <item msgid="6042769699089883931">"Check for DRM content only"</item> + <item msgid="9174900380056846820">"Always check"</item> + </string-array> + <string-array name="hdcp_checking_summaries"> + <item msgid="505558545611516707">"Never use HDCP checking"</item> + <item msgid="3878793616631049349">"Use HDCP checking for DRM content only"</item> + <item msgid="45075631231212732">"Always use HDCP checking"</item> + </string-array> + <string-array name="bluetooth_avrcp_versions"> + <item msgid="5347678900838034763">"AVRCP 1.4 (Default)"</item> + <item msgid="2089555299377409443">"AVRCP 1.5"</item> + <item msgid="2895327394279434278">"AVRCP 1.6"</item> + </string-array> + <string-array name="bluetooth_avrcp_version_values"> + <item msgid="2838624067805073303">"avrcp14"</item> + <item msgid="1913619118958233129">"avrcp15"</item> + <item msgid="7142710449249088270">"avrcp16"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_titles"> + <item msgid="7065842274271279580">"Use System Selection (Default)"</item> + <item msgid="7539690996561263909">"SBC"</item> + <item msgid="686685526567131661">"AAC"</item> + <item msgid="5254942598247222737">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> + <item msgid="2091430979086738145">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> + <item msgid="6751080638867012696">"LDAC"</item> + <item msgid="723675059572222462">"Enable Optional Codecs"</item> + <item msgid="3304843301758635896">"Disable Optional Codecs"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_summaries"> + <item msgid="5062108632402595000">"Use System Selection (Default)"</item> + <item msgid="6898329690939802290">"SBC"</item> + <item msgid="6839647709301342559">"AAC"</item> + <item msgid="7848030269621918608">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> + <item msgid="298198075927343893">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> + <item msgid="7950781694447359344">"LDAC"</item> + <item msgid="2209680154067241740">"Enable Optional Codecs"</item> + <item msgid="741805482892725657">"Disable Optional Codecs"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> + <item msgid="3093023430402746802">"Use System Selection (Default)"</item> + <item msgid="8895532488906185219">"44.1 kHz"</item> + <item msgid="2909915718994807056">"48.0 kHz"</item> + <item msgid="3347287377354164611">"88.2 kHz"</item> + <item msgid="1234212100239985373">"96.0 kHz"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_sample_rate_summaries"> + <item msgid="3214516120190965356">"Use System Selection (Default)"</item> + <item msgid="4482862757811638365">"44.1 kHz"</item> + <item msgid="354495328188724404">"48.0 kHz"</item> + <item msgid="7329816882213695083">"88.2 kHz"</item> + <item msgid="6967397666254430476">"96.0 kHz"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles"> + <item msgid="2684127272582591429">"Use System Selection (Default)"</item> + <item msgid="5618929009984956469">"16 bits/sample"</item> + <item msgid="3412640499234627248">"24 bits/sample"</item> + <item msgid="121583001492929387">"32 bits/sample"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries"> + <item msgid="1081159789834584363">"Use System Selection (Default)"</item> + <item msgid="4726688794884191540">"16 bits/sample"</item> + <item msgid="305344756485516870">"24 bits/sample"</item> + <item msgid="244568657919675099">"32 bits/sample"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_channel_mode_titles"> + <item msgid="5226878858503393706">"Use System Selection (Default)"</item> + <item msgid="4106832974775067314">"Mono"</item> + <item msgid="5571632958424639155">"Stereo"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_channel_mode_summaries"> + <item msgid="4118561796005528173">"Use System Selection (Default)"</item> + <item msgid="8900559293912978337">"Mono"</item> + <item msgid="8883739882299884241">"Stereo"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles"> + <item msgid="7158319962230727476">"Optimised for Audio Quality (990kbps/909kbps)"</item> + <item msgid="2921767058740704969">"Balanced Audio And Connection Quality (660 kbps/606 kbps)"</item> + <item msgid="8860982705384396512">"Optimised for Connection Quality (330kbps/303kbps)"</item> + <item msgid="4414060457677684127">"Best Effort (Adaptive Bit Rate)"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries"> + <item msgid="6398189564246596868">"Optimised for Audio Quality"</item> + <item msgid="4327143584633311908">"Balanced Audio and Connection Quality"</item> + <item msgid="4681409244565426925">"Optimised for Connection Quality"</item> + <item msgid="364670732877872677">"Best Effort (Adaptive Bit Rate)"</item> + </string-array> + <string-array name="select_logd_size_titles"> + <item msgid="8665206199209698501">"Off"</item> + <item msgid="1593289376502312923">"64 K"</item> + <item msgid="487545340236145324">"256 K"</item> + <item msgid="2423528675294333831">"1 M"</item> + <item msgid="180883774509476541">"4 M"</item> + <item msgid="2803199102589126938">"16 M"</item> + </string-array> + <string-array name="select_logd_size_lowram_titles"> + <item msgid="6089470720451068364">"Off"</item> + <item msgid="4622460333038586791">"64 K"</item> + <item msgid="2212125625169582330">"256 K"</item> + <item msgid="1704946766699242653">"1 M"</item> + </string-array> + <string-array name="select_logd_size_summaries"> + <item msgid="6921048829791179331">"Off"</item> + <item msgid="2969458029344750262">"64 K per log buffer"</item> + <item msgid="1342285115665698168">"256 K per log buffer"</item> + <item msgid="1314234299552254621">"1 M per log buffer"</item> + <item msgid="3606047780792894151">"4 M per log buffer"</item> + <item msgid="5431354956856655120">"16 M per log buffer"</item> + </string-array> + <string-array name="select_logpersist_titles"> + <item msgid="1744840221860799971">"Off"</item> + <item msgid="3054662377365844197">"All"</item> + <item msgid="688870735111627832">"All but radio"</item> + <item msgid="2850427388488887328">"kernel only"</item> + </string-array> + <string-array name="select_logpersist_summaries"> + <item msgid="2216470072500521830">"Off"</item> + <item msgid="172978079776521897">"All log buffers"</item> + <item msgid="3873873912383879240">"All but radio log buffers"</item> + <item msgid="8489661142527693381">"kernel log buffer only"</item> + </string-array> + <string-array name="window_animation_scale_entries"> + <item msgid="8134156599370824081">"Animation off"</item> + <item msgid="6624864048416710414">"Animation scale .5x"</item> + <item msgid="2219332261255416635">"Animation scale 1x"</item> + <item msgid="3544428804137048509">"Animation scale 1.5x"</item> + <item msgid="3110710404225974514">"Animation scale 2x"</item> + <item msgid="4402738611528318731">"Animation scale 5x"</item> + <item msgid="6189539267968330656">"Animation scale 10x"</item> + </string-array> + <string-array name="transition_animation_scale_entries"> + <item msgid="8464255836173039442">"Animation off"</item> + <item msgid="3375781541913316411">"Animation scale .5x"</item> + <item msgid="1991041427801869945">"Animation scale 1x"</item> + <item msgid="4012689927622382874">"Animation scale 1.5x"</item> + <item msgid="3289156759925947169">"Animation scale 2x"</item> + <item msgid="7705857441213621835">"Animation scale 5x"</item> + <item msgid="6660750935954853365">"Animation scale 10x"</item> + </string-array> + <string-array name="animator_duration_scale_entries"> + <item msgid="6039901060648228241">"Animation off"</item> + <item msgid="1138649021950863198">"Animation scale .5x"</item> + <item msgid="4394388961370833040">"Animation scale 1x"</item> + <item msgid="8125427921655194973">"Animation scale 1.5x"</item> + <item msgid="3334024790739189573">"Animation scale 2x"</item> + <item msgid="3170120558236848008">"Animation scale 5x"</item> + <item msgid="1069584980746680398">"Animation scale 10x"</item> + </string-array> + <string-array name="overlay_display_devices_entries"> + <item msgid="1606809880904982133">"None"</item> + <item msgid="9033194758688161545">"480 p"</item> + <item msgid="1025306206556583600">"480p (secure)"</item> + <item msgid="1853913333042744661">"720p"</item> + <item msgid="3414540279805870511">"720p (secure)"</item> + <item msgid="9039818062847141551">"1080p"</item> + <item msgid="4939496949750174834">"1080p (secure)"</item> + <item msgid="1833612718524903568">"4K"</item> + <item msgid="238303513127879234">"4K (secure)"</item> + <item msgid="3547211260846843098">"4K (upscaled)"</item> + <item msgid="5411365648951414254">"4K (upscaled, secure)"</item> + <item msgid="1311305077526792901">"720p, 1080p (dual screen)"</item> + </string-array> + <string-array name="enable_opengl_traces_entries"> + <item msgid="3191973083884253830">"None"</item> + <item msgid="9089630089455370183">"Logcat"</item> + <item msgid="5397807424362304288">"Systrace (Graphics)"</item> + <item msgid="1340692776955662664">"Call stack on glGetError"</item> + </string-array> + <string-array name="show_non_rect_clip_entries"> + <item msgid="993742912147090253">"Off"</item> + <item msgid="675719912558941285">"Draw non-rectangular clip region in blue"</item> + <item msgid="1064373276095698656">"Highlight tested drawing commands in green"</item> + </string-array> + <string-array name="track_frame_time_entries"> + <item msgid="2193584639058893150">"Off"</item> + <item msgid="2751513398307949636">"On screen as bars"</item> + <item msgid="2355151170975410323">"In <xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g>"</item> + </string-array> + <string-array name="debug_hw_overdraw_entries"> + <item msgid="8190572633763871652">"Off"</item> + <item msgid="7688197031296835369">"Show overdraw areas"</item> + <item msgid="2290859360633824369">"Show areas for Deuteranomaly"</item> + </string-array> + <string-array name="debug_hw_renderer_entries"> + <item msgid="2578620445459945681">"OpenGL (Default)"</item> + <item msgid="2839130076198120436">"OpenGL (Skia)"</item> + </string-array> + <string-array name="app_process_limit_entries"> + <item msgid="3401625457385943795">"Standard limit"</item> + <item msgid="4071574792028999443">"No background processes"</item> + <item msgid="4810006996171705398">"At most, 1 process"</item> + <item msgid="8586370216857360863">"At most, 2 processes"</item> + <item msgid="836593137872605381">"At most, 3 processes"</item> + <item msgid="7899496259191969307">"At most, 4 processes"</item> + </string-array> + <string-array name="usb_configuration_titles"> + <item msgid="488237561639712799">"Charging"</item> + <item msgid="5220695614993094977">"MTP (Media Transfer Protocol)"</item> + <item msgid="2086000968159047375">"PTP (Picture Transfer Protocol)"</item> + <item msgid="7398830860950841822">"RNDIS (USB Ethernet)"</item> + <item msgid="1718924214939774352">"Audio Source"</item> + <item msgid="8126315616613006284">"MIDI"</item> + </string-array> +</resources> diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml new file mode 100644 index 000000000000..db8cfa1fa436 --- /dev/null +++ b/packages/SettingsLib/res/values-en-rCA/strings.xml @@ -0,0 +1,395 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** +** Copyright 2015 The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Can\'t scan for networks"</string> + <string name="wifi_security_none" msgid="7985461072596594400">"None"</string> + <string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string> + <string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string> + <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string> + <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Not connected due to low quality network"</string> + <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi Connection Failure"</string> + <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Authentication problem"</string> + <string name="wifi_cant_connect" msgid="5410016875644565884">"Can\'t connect"</string> + <string name="wifi_cant_connect_to_ap" msgid="1222553274052685331">"Can\'t connect to \'<xliff:g id="AP_NAME">%1$s</xliff:g>\'"</string> + <string name="wifi_check_password_try_again" msgid="516958988102584767">"Check password and try again"</string> + <string name="wifi_not_in_range" msgid="1136191511238508967">"Not in range"</string> + <string name="wifi_no_internet_no_reconnect" msgid="5724903347310541706">"Won\'t automatically connect"</string> + <string name="wifi_no_internet" msgid="3880396223819116454">"No Internet access"</string> + <string name="saved_network" msgid="4352716707126620811">"Saved by <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatically connected via %1$s"</string> + <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatically connected via network rating provider"</string> + <string name="connected_via_passpoint" msgid="2826205693803088747">"Connected via %1$s"</string> + <string name="available_via_passpoint" msgid="1617440946846329613">"Available via %1$s"</string> + <string name="wifi_connected_no_internet" msgid="3149853966840874992">"Connected, no Internet"</string> + <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Access point temporarily full"</string> + <string name="connected_via_carrier" msgid="7583780074526041912">"Connected via %1$s"</string> + <string name="available_via_carrier" msgid="1469036129740799053">"Available via %1$s"</string> + <string name="speed_label_very_slow" msgid="1867055264243608530">"Very slow"</string> + <string name="speed_label_slow" msgid="813109590815810235">"Slow"</string> + <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> + <string name="speed_label_medium" msgid="3175763313268941953">"Medium"</string> + <string name="speed_label_fast" msgid="7715732164050975057">"Fast"</string> + <string name="speed_label_very_fast" msgid="2265363430784523409">"Very fast"</string> + <string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string> + <string name="bluetooth_disconnected" msgid="6557104142667339895">"Disconnected"</string> + <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Disconnecting…"</string> + <string name="bluetooth_connecting" msgid="8555009514614320497">"Connecting…"</string> + <string name="bluetooth_connected" msgid="6038755206916626419">"Connected"</string> + <string name="bluetooth_pairing" msgid="1426882272690346242">"Pairing…"</string> + <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Connected (no phone)"</string> + <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Connected (no media)"</string> + <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Connected (no message access)"</string> + <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Connected (no phone or media)"</string> + <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Connected, battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Connected (no phone), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Connected (no media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media audio"</string> + <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Phone calls"</string> + <string name="bluetooth_profile_opp" msgid="9168139293654233697">"File transfer"</string> + <string name="bluetooth_profile_hid" msgid="3680729023366986480">"Input device"</string> + <string name="bluetooth_profile_pan" msgid="3391606497945147673">"Internet access"</string> + <string name="bluetooth_profile_pbap" msgid="5372051906968576809">"Contact sharing"</string> + <string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"Use for contact sharing"</string> + <string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"Internet connection sharing"</string> + <string name="bluetooth_profile_map" msgid="1019763341565580450">"Text messages"</string> + <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Access"</string> + <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string> + <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string> + <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connected to media audio"</string> + <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connected to phone audio"</string> + <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connected to file-transfer server"</string> + <string name="bluetooth_map_profile_summary_connected" msgid="8191407438851351713">"Connected to map"</string> + <string name="bluetooth_sap_profile_summary_connected" msgid="8561765057453083838">"Connected to SAP"</string> + <string name="bluetooth_opp_profile_summary_not_connected" msgid="1267091356089086285">"Not connected to file-transfer server"</string> + <string name="bluetooth_hid_profile_summary_connected" msgid="3381760054215168689">"Connected to input device"</string> + <string name="bluetooth_pan_user_profile_summary_connected" msgid="4602294638909590612">"Connected to device for Internet access"</string> + <string name="bluetooth_pan_nap_profile_summary_connected" msgid="1561383706411975199">"Sharing local Internet connection with device"</string> + <string name="bluetooth_pan_profile_summary_use_for" msgid="5664884523822068653">"Use for Internet access"</string> + <string name="bluetooth_map_profile_summary_use_for" msgid="5154200119919927434">"Use for map"</string> + <string name="bluetooth_sap_profile_summary_use_for" msgid="7085362712786907993">"Use for SIM access"</string> + <string name="bluetooth_a2dp_profile_summary_use_for" msgid="4630849022250168427">"Use for media audio"</string> + <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Use for phone audio"</string> + <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Use for file transfer"</string> + <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Use for input"</string> + <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Pair"</string> + <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAIR"</string> + <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancel"</string> + <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Pairing grants access to your contacts and call history when connected."</string> + <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"Couldn\'t pair with <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> + <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"Couldn\'t pair with <xliff:g id="DEVICE_NAME">%1$s</xliff:g> because of an incorrect PIN or passkey."</string> + <string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"Can\'t communicate with <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> + <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"Pairing rejected by <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> + <string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi off."</string> + <string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi disconnected."</string> + <string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi one bar."</string> + <string name="accessibility_wifi_two_bars" msgid="3569851234710034416">"Wi-Fi two bars."</string> + <string name="accessibility_wifi_three_bars" msgid="8134185644861380311">"Wi-Fi three bars."</string> + <string name="accessibility_wifi_signal_full" msgid="7061045677694702">"Wi-Fi signal full."</string> + <string name="accessibility_wifi_security_type_none" msgid="1223747559986205423">"Open network"</string> + <string name="accessibility_wifi_security_type_secured" msgid="862921720418885331">"Secure network"</string> + <string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string> + <string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Removed apps"</string> + <string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Removed apps and users"</string> + <string name="tether_settings_title_usb" msgid="6688416425801386511">"USB tethering"</string> + <string name="tether_settings_title_wifi" msgid="3277144155960302049">"Portable hotspot"</string> + <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth tethering"</string> + <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"Tethering"</string> + <string name="tether_settings_title_all" msgid="8356136101061143841">"Tethering & portable hotspot"</string> + <string name="managed_user_title" msgid="8109605045406748842">"All work apps"</string> + <string name="user_guest" msgid="8475274842845401871">"Guest"</string> + <string name="unknown" msgid="1592123443519355854">"Unknown"</string> + <string name="running_process_item_user_label" msgid="3129887865552025943">"User: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string> + <string name="launch_defaults_some" msgid="313159469856372621">"Some defaults set"</string> + <string name="launch_defaults_none" msgid="4241129108140034876">"No defaults set"</string> + <string name="tts_settings" msgid="8186971894801348327">"Text-to-speech settings"</string> + <string name="tts_settings_title" msgid="1237820681016639683">"Text-to-speech output"</string> + <string name="tts_default_rate_title" msgid="6030550998379310088">"Speech rate"</string> + <string name="tts_default_rate_summary" msgid="4061815292287182801">"Speed at which the text is spoken"</string> + <string name="tts_default_pitch_title" msgid="6135942113172488671">"Pitch"</string> + <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Affects the tone of the synthesised speech"</string> + <string name="tts_default_lang_title" msgid="8018087612299820556">"Language"</string> + <string name="tts_lang_use_system" msgid="2679252467416513208">"Use system language"</string> + <string name="tts_lang_not_selected" msgid="7395787019276734765">"Language not selected"</string> + <string name="tts_default_lang_summary" msgid="5219362163902707785">"Sets the language-specific voice for the spoken text"</string> + <string name="tts_play_example_title" msgid="7094780383253097230">"Listen to an example"</string> + <string name="tts_play_example_summary" msgid="8029071615047894486">"Play a short demonstration of speech synthesis"</string> + <string name="tts_install_data_title" msgid="4264378440508149986">"Install voice data"</string> + <string name="tts_install_data_summary" msgid="5742135732511822589">"Install the voice data required for speech synthesis"</string> + <string name="tts_engine_security_warning" msgid="8786238102020223650">"This speech synthesis engine may be able to collect all the text that will be spoken, including personal data like passwords and credit card numbers. It comes from the <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> engine. Enable the use of this speech synthesis engine?"</string> + <string name="tts_engine_network_required" msgid="1190837151485314743">"This language requires a working network connection for text-to-speech output."</string> + <string name="tts_default_sample_string" msgid="4040835213373086322">"This is an example of speech synthesis"</string> + <string name="tts_status_title" msgid="7268566550242584413">"Default language status"</string> + <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> is fully supported"</string> + <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> requires network connection"</string> + <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> is not supported"</string> + <string name="tts_status_checking" msgid="5339150797940483592">"Checking…"</string> + <string name="tts_engine_settings_title" msgid="3499112142425680334">"Settings for <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string> + <string name="tts_engine_settings_button" msgid="1030512042040722285">"Launch engine settings"</string> + <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Preferred engine"</string> + <string name="tts_general_section_title" msgid="4402572014604490502">"General"</string> + <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Reset speech pitch"</string> + <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Reset the pitch at which the text is spoken to default."</string> + <string-array name="tts_rate_entries"> + <item msgid="6695494874362656215">"Very slow"</item> + <item msgid="4795095314303559268">"Slow"</item> + <item msgid="8903157781070679765">"Normal"</item> + <item msgid="164347302621392996">"Fast"</item> + <item msgid="5794028588101562009">"Faster"</item> + <item msgid="7163942783888652942">"Very fast"</item> + <item msgid="7831712693748700507">"Rapid"</item> + <item msgid="5194774745031751806">"Very rapid"</item> + <item msgid="9085102246155045744">"Fastest"</item> + </string-array> + <string name="choose_profile" msgid="6921016979430278661">"Choose profile"</string> + <string name="category_personal" msgid="1299663247844969448">"Personal"</string> + <string name="category_work" msgid="8699184680584175622">"Work"</string> + <string name="development_settings_title" msgid="215179176067683667">"Developer options"</string> + <string name="development_settings_enable" msgid="542530994778109538">"Enable developer options"</string> + <string name="development_settings_summary" msgid="1815795401632854041">"Set options for app development"</string> + <string name="development_settings_not_available" msgid="4308569041701535607">"Developer options are not available for this user"</string> + <string name="vpn_settings_not_available" msgid="956841430176985598">"VPN settings are not available for this user"</string> + <string name="tethering_settings_not_available" msgid="6765770438438291012">"Tethering settings are not available for this user"</string> + <string name="apn_settings_not_available" msgid="7873729032165324000">"Access Point Name settings are not available for this user"</string> + <string name="enable_adb" msgid="7982306934419797485">"USB debugging"</string> + <string name="enable_adb_summary" msgid="4881186971746056635">"Debug mode when USB is connected"</string> + <string name="clear_adb_keys" msgid="4038889221503122743">"Revoke USB debugging authorisations"</string> + <string name="bugreport_in_power" msgid="7923901846375587241">"Bug report shortcut"</string> + <string name="bugreport_in_power_summary" msgid="1778455732762984579">"Show a button in the power menu for taking a bug report"</string> + <string name="keep_screen_on" msgid="1146389631208760344">"Stay awake"</string> + <string name="keep_screen_on_summary" msgid="2173114350754293009">"Screen will never sleep while charging"</string> + <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Enable Bluetooth HCI snoop log"</string> + <string name="bt_hci_snoop_log_summary" msgid="730247028210113851">"Capture all Bluetooth HCI packets in a file"</string> + <string name="oem_unlock_enable" msgid="6040763321967327691">"OEM unlocking"</string> + <string name="oem_unlock_enable_summary" msgid="4720281828891618376">"Allow the bootloader to be unlocked"</string> + <string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"Allow OEM unlocking?"</string> + <string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"WARNING: Device protection features will not work on this device while this setting is turned on."</string> + <string name="mock_location_app" msgid="7966220972812881854">"Select mock location app"</string> + <string name="mock_location_app_not_set" msgid="809543285495344223">"No mock location app set"</string> + <string name="mock_location_app_set" msgid="8966420655295102685">"Mock location app: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string> + <string name="wifi_display_certification" msgid="8611569543791307533">"Wireless display certification"</string> + <string name="wifi_verbose_logging" msgid="4203729756047242344">"Enable Wi‑Fi verbose logging"</string> + <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressive Wi‑Fi to mobile handover"</string> + <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string> + <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string> + <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> + <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disable absolute volume"</string> + <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Enable in-band ringing"</string> + <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP Version"</string> + <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Select Bluetooth AVRCP Version"</string> + <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio Codec"</string> + <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Select Bluetooth Audio Codec"</string> + <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bluetooth Audio Sample Rate"</string> + <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Select Bluetooth Audio Codec:\nSample Rate"</string> + <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bluetooth Audio Bits Per Sample"</string> + <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Select Bluetooth Audio Codec:\nBits Per Sample"</string> + <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Bluetooth Audio Channel Mode"</string> + <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Select Bluetooth Audio Codec:\nChannel Mode"</string> + <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth Audio LDAC Codec: Playback Quality"</string> + <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Select Bluetooth Audio LDAC Codec:\nPlayback Quality"</string> + <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streaming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string> + <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string> + <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string> + <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"When enabled, Wi‑Fi will be more aggressive in handing over the data connection to mobile, when Wi‑Fi signal is low"</string> + <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface"</string> + <string name="select_logd_size_title" msgid="7433137108348553508">"Logger buffer sizes"</string> + <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Select Logger sizes per log buffer"</string> + <string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Clear logger persistent storage?"</string> + <string name="dev_logpersist_clear_warning_message" msgid="2256582531342994562">"When we are no longer monitoring with the persistent logger, we are required to erase the logger data resident on your device."</string> + <string name="select_logpersist_title" msgid="7530031344550073166">"Store logger data persistently on device"</string> + <string name="select_logpersist_dialog_title" msgid="4003400579973269060">"Select log buffers to store persistently on device"</string> + <string name="select_usb_configuration_title" msgid="2649938511506971843">"Select USB Configuration"</string> + <string name="select_usb_configuration_dialog_title" msgid="6385564442851599963">"Select USB Configuration"</string> + <string name="allow_mock_location" msgid="2787962564578664888">"Allow mock locations"</string> + <string name="allow_mock_location_summary" msgid="317615105156345626">"Allow mock locations"</string> + <string name="debug_view_attributes" msgid="6485448367803310384">"Enable view attribute inspection"</string> + <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Always keep mobile data active, even when Wi‑Fi is active (for fast network switching)."</string> + <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Use tethering hardware acceleration if available"</string> + <string name="adb_warning_title" msgid="6234463310896563253">"Allow USB debugging?"</string> + <string name="adb_warning_message" msgid="7316799925425402244">"USB debugging is intended for development purposes only. Use it to copy data between your computer and your device, install apps on your device without notification and read log data."</string> + <string name="adb_keys_warning_message" msgid="5659849457135841625">"Revoke access to USB debugging from all computers you\'ve previously authorised?"</string> + <string name="dev_settings_warning_title" msgid="7244607768088540165">"Allow development settings?"</string> + <string name="dev_settings_warning_message" msgid="2298337781139097964">"These settings are intended for development use only. They can cause your device and the applications on it to break or misbehave."</string> + <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verify apps over USB"</string> + <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Check apps installed via ADB/ADT for harmful behaviour."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> + <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string> + <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Allow ringtones on the phone to be played on Bluetooth headsets"</string> + <string name="enable_terminal_title" msgid="95572094356054120">"Local terminal"</string> + <string name="enable_terminal_summary" msgid="67667852659359206">"Enable terminal app that offers local shell access"</string> + <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP checking"</string> + <string name="hdcp_checking_dialog_title" msgid="5141305530923283">"Set HDCP checking behaviour"</string> + <string name="debug_debugging_category" msgid="6781250159513471316">"Debugging"</string> + <string name="debug_app" msgid="8349591734751384446">"Select debug app"</string> + <string name="debug_app_not_set" msgid="718752499586403499">"No debug application set"</string> + <string name="debug_app_set" msgid="2063077997870280017">"Debugging application: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="select_application" msgid="5156029161289091703">"Select application"</string> + <string name="no_application" msgid="2813387563129153880">"Nothing"</string> + <string name="wait_for_debugger" msgid="1202370874528893091">"Wait for debugger"</string> + <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Debugged application waits for debugger to attach before executing"</string> + <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string> + <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor will collect logs when it detects a problem with telephony/modem functionality and prompt notification to user to file a bug"</string> + <string name="debug_input_category" msgid="1811069939601180246">"Input"</string> + <string name="debug_drawing_category" msgid="6755716469267367852">"Drawing"</string> + <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Hardware accelerated rendering"</string> + <string name="media_category" msgid="4388305075496848353">"Media"</string> + <string name="debug_monitoring_category" msgid="7640508148375798343">"Monitoring"</string> + <string name="strict_mode" msgid="1938795874357830695">"Strict mode enabled"</string> + <string name="strict_mode_summary" msgid="142834318897332338">"Flash screen when apps do long operations on main thread"</string> + <string name="pointer_location" msgid="6084434787496938001">"Pointer location"</string> + <string name="pointer_location_summary" msgid="840819275172753713">"Screen overlay showing current touch data"</string> + <string name="show_touches" msgid="2642976305235070316">"Show taps"</string> + <string name="show_touches_summary" msgid="6101183132903926324">"Show visual feedback for taps"</string> + <string name="show_screen_updates" msgid="5470814345876056420">"Show surface updates"</string> + <string name="show_screen_updates_summary" msgid="2569622766672785529">"Flash entire window surfaces when they update"</string> + <string name="show_hw_screen_updates" msgid="5036904558145941590">"Show GPU view updates"</string> + <string name="show_hw_screen_updates_summary" msgid="1115593565980196197">"Flash views inside windows when drawn with the GPU"</string> + <string name="show_hw_layers_updates" msgid="5645728765605699821">"Show hardware layers updates"</string> + <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Flash hardware layers green when they update"</string> + <string name="debug_hw_overdraw" msgid="2968692419951565417">"Debug GPU overdraw"</string> + <string name="debug_hw_renderer" msgid="7568529019431785816">"Set GPU Renderer"</string> + <string name="disable_overlays" msgid="2074488440505934665">"Disable HW overlays"</string> + <string name="disable_overlays_summary" msgid="3578941133710758592">"Always use GPU for screen compositing"</string> + <string name="simulate_color_space" msgid="6745847141353345872">"Simulate colour space"</string> + <string name="enable_opengl_traces_title" msgid="6790444011053219871">"Enable OpenGL traces"</string> + <string name="usb_audio_disable_routing" msgid="8114498436003102671">"Disable USB audio routing"</string> + <string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"Disable automatic routing to USB audio peripherals"</string> + <string name="debug_layout" msgid="5981361776594526155">"Show layout bounds"</string> + <string name="debug_layout_summary" msgid="2001775315258637682">"Show clip bounds, margins, etc."</string> + <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Force RTL layout direction"</string> + <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Force screen layout direction to RTL for all locales"</string> + <string name="force_hw_ui" msgid="6426383462520888732">"Force GPU rendering"</string> + <string name="force_hw_ui_summary" msgid="5535991166074861515">"Force use of GPU for 2D drawing"</string> + <string name="force_msaa" msgid="7920323238677284387">"Force 4x MSAA"</string> + <string name="force_msaa_summary" msgid="9123553203895817537">"Enable 4x MSAA in OpenGL ES 2.0 apps"</string> + <string name="show_non_rect_clip" msgid="505954950474595172">"Debug non-rectangular clip operations"</string> + <string name="track_frame_time" msgid="6146354853663863443">"Profile GPU rendering"</string> + <string name="window_animation_scale_title" msgid="6162587588166114700">"Window animation scale"</string> + <string name="transition_animation_scale_title" msgid="387527540523595875">"Transition animation scale"</string> + <string name="animator_duration_scale_title" msgid="3406722410819934083">"Animator duration scale"</string> + <string name="overlay_display_devices_title" msgid="5364176287998398539">"Simulate secondary displays"</string> + <string name="debug_applications_category" msgid="4206913653849771549">"Apps"</string> + <string name="immediately_destroy_activities" msgid="1579659389568133959">"Don\'t keep activities"</string> + <string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"Destroy every activity as soon as the user leaves it"</string> + <string name="app_process_limit_title" msgid="4280600650253107163">"Background process limit"</string> + <string name="show_all_anrs" msgid="28462979638729082">"Show all ANRs"</string> + <string name="show_all_anrs_summary" msgid="641908614413544127">"Show App Not Responding dialogue for background apps"</string> + <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Show notification channel warnings"</string> + <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Displays on-screen warning when an app posts a notification without a valid channel"</string> + <string name="force_allow_on_external" msgid="3215759785081916381">"Force allow apps on external"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Makes any app eligible to be written to external storage, regardless of manifest values"</string> + <string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Make all activities resizable for multi-window, regardless of manifest values."</string> + <string name="enable_freeform_support" msgid="1461893351278940416">"Enable freeform windows"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Enable support for experimental freeform windows."</string> + <string name="local_backup_password_title" msgid="3860471654439418822">"Desktop backup password"</string> + <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Desktop full backups aren\'t currently protected"</string> + <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tap to change or remove the password for desktop full backups"</string> + <string name="local_backup_password_toast_success" msgid="582016086228434290">"New backup password set"</string> + <string name="local_backup_password_toast_confirmation_mismatch" msgid="7805892532752708288">"New password and confirmation don\'t match"</string> + <string name="local_backup_password_toast_validation_failure" msgid="5646377234895626531">"Failure setting backup password"</string> + <string-array name="color_mode_names"> + <item msgid="2425514299220523812">"Vibrant (default)"</item> + <item msgid="8446070607501413455">"Natural"</item> + <item msgid="6553408765810699025">"Standard"</item> + </string-array> + <string-array name="color_mode_descriptions"> + <item msgid="4979629397075120893">"Enhanced colours"</item> + <item msgid="8280754435979370728">"Natural colours as seen by the eye"</item> + <item msgid="5363960654009010371">"Colours optimised for digital content"</item> + </string-array> + <string name="inactive_apps_title" msgid="1317817863508274533">"Inactive apps"</string> + <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Inactive. Tap to toggle."</string> + <string name="inactive_app_active_summary" msgid="4174921824958516106">"Active. Tap to toggle."</string> + <string name="runningservices_settings_title" msgid="8097287939865165213">"Running services"</string> + <string name="runningservices_settings_summary" msgid="854608995821032748">"View and control currently running services"</string> + <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string> + <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Set WebView implementation"</string> + <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"This choice is no longer valid. Try again."</string> + <string name="convert_to_file_encryption" msgid="3060156730651061223">"Convert to file encryption"</string> + <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convert…"</string> + <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Already file encrypted"</string> + <string name="title_convert_fbe" msgid="1263622876196444453">"Converting to file-based encryption"</string> + <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Convert data partition to file-based encryption.\n !!Warning!! This will delete all your data.\n This feature is alpha, and may not work correctly.\n Press \'Wipe and convert…\' to continue."</string> + <string name="button_convert_fbe" msgid="5152671181309826405">"Wipe and convert…"</string> + <string name="picture_color_mode" msgid="4560755008730283695">"Picture colour mode"</string> + <string name="picture_color_mode_desc" msgid="1141891467675548590">"Use sRGB"</string> + <string name="daltonizer_mode_disabled" msgid="7482661936053801862">"Disabled"</string> + <string name="daltonizer_mode_monochromacy" msgid="8485709880666106721">"Monochromacy"</string> + <string name="daltonizer_mode_deuteranomaly" msgid="5475532989673586329">"Deuteranomaly (red-green)"</string> + <string name="daltonizer_mode_protanomaly" msgid="8424148009038666065">"Protanomaly (red-green)"</string> + <string name="daltonizer_mode_tritanomaly" msgid="481725854987912389">"Tritanomaly (blue-yellow)"</string> + <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Colour correction"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string> + <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string> + <string name="power_remaining_duration_only" msgid="845431008899029842">"About <xliff:g id="TIME">^1</xliff:g> left"</string> + <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"About <xliff:g id="TIME">^1</xliff:g> left based on your usage"</string> + <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> left until fully charged"</string> + <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> left"</string> + <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"<xliff:g id="TIME">^1</xliff:g> left based on your usage"</string> + <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> – about <xliff:g id="TIME">^2</xliff:g> left"</string> + <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> - about <xliff:g id="TIME">^2</xliff:g> left based on your usage"</string> + <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> left"</string> + <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> + <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> until fully charged"</string> + <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string> + <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string> + <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"charging"</string> + <string name="battery_info_status_discharging" msgid="310932812698268588">"Not charging"</string> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Plugged in, can\'t charge right now"</string> + <string name="battery_info_status_full" msgid="2824614753861462808">"Full"</string> + <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlled by admin"</string> + <string name="enabled_by_admin" msgid="5302986023578399263">"Enabled by admin"</string> + <string name="disabled_by_admin" msgid="8505398946020816620">"Disabled by admin"</string> + <string name="disabled" msgid="9206776641295849915">"Disabled"</string> + <string name="external_source_trusted" msgid="2707996266575928037">"Allowed"</string> + <string name="external_source_untrusted" msgid="2677442511837596726">"Not allowed"</string> + <string name="install_other_apps" msgid="6986686991775883017">"Install unknown apps"</string> + <string name="home" msgid="3256884684164448244">"Settings Home"</string> + <string-array name="battery_labels"> + <item msgid="8494684293649631252">"0%"</item> + <item msgid="8934126114226089439">"50%"</item> + <item msgid="1286113608943010849">"100%"</item> + </string-array> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ago"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> left"</string> + <string name="screen_zoom_summary_small" msgid="5867245310241621570">"Small"</string> + <string name="screen_zoom_summary_default" msgid="2247006805614056507">"Default"</string> + <string name="screen_zoom_summary_large" msgid="4835294730065424084">"Large"</string> + <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Larger"</string> + <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Largest"</string> + <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Custom (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string> + <string name="help_feedback_label" msgid="6815040660801785649">"Help & feedback"</string> + <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string> + <string name="retail_demo_reset_message" msgid="118771671364131297">"Enter password to perform factory reset in demo mode"</string> + <string name="retail_demo_reset_next" msgid="8356731459226304963">"Next"</string> + <string name="retail_demo_reset_title" msgid="696589204029930100">"Password required"</string> + <string name="active_input_method_subtypes" msgid="3596398805424733238">"Active input methods"</string> + <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Use system languages"</string> + <string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Failed to open settings for <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string> + <string name="ime_security_warning" msgid="4135828934735934248">"This input method may be able to collect all the text that you type, including personal data like passwords and credit card numbers. It comes from the app <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Use this input method?"</string> + <string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Note: After a reboot, this app can\'t start until you unlock your phone"</string> +</resources> diff --git a/packages/SettingsLib/res/values-en-rGB/arrays.xml b/packages/SettingsLib/res/values-en-rGB/arrays.xml index 77af30ecb6f8..55feafa87a95 100644 --- a/packages/SettingsLib/res/values-en-rGB/arrays.xml +++ b/packages/SettingsLib/res/values-en-rGB/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"Use System Selection (Default)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> + <item msgid="2091430979086738145">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"Enable Optional Codecs"</item> <item msgid="3304843301758635896">"Disable Optional Codecs"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"Use System Selection (Default)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> + <item msgid="298198075927343893">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"Enable Optional Codecs"</item> <item msgid="741805482892725657">"Disable Optional Codecs"</item> diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml index bbc114463582..db8cfa1fa436 100644 --- a/packages/SettingsLib/res/values-en-rGB/strings.xml +++ b/packages/SettingsLib/res/values-en-rGB/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disable absolute volume"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Enable in-band ringing"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP Version"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"These settings are intended for development use only. They can cause your device and the applications on it to break or misbehave."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verify apps over USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Check apps installed via ADB/ADT for harmful behaviour."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Allow ringtones on the phone to be played on Bluetooth headsets"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Local terminal"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> left"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> until fully charged"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"charging"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Not charging"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Plugged in, can\'t charge right now"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Full"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlled by admin"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Enabled by admin"</string> diff --git a/packages/SettingsLib/res/values-en-rIN/arrays.xml b/packages/SettingsLib/res/values-en-rIN/arrays.xml index 77af30ecb6f8..55feafa87a95 100644 --- a/packages/SettingsLib/res/values-en-rIN/arrays.xml +++ b/packages/SettingsLib/res/values-en-rIN/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"Use System Selection (Default)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> + <item msgid="2091430979086738145">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"Enable Optional Codecs"</item> <item msgid="3304843301758635896">"Disable Optional Codecs"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"Use System Selection (Default)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> + <item msgid="298198075927343893">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"Enable Optional Codecs"</item> <item msgid="741805482892725657">"Disable Optional Codecs"</item> diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml index bbc114463582..db8cfa1fa436 100644 --- a/packages/SettingsLib/res/values-en-rIN/strings.xml +++ b/packages/SettingsLib/res/values-en-rIN/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disable absolute volume"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Enable in-band ringing"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP Version"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"These settings are intended for development use only. They can cause your device and the applications on it to break or misbehave."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verify apps over USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Check apps installed via ADB/ADT for harmful behaviour."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Allow ringtones on the phone to be played on Bluetooth headsets"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Local terminal"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> left"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> until fully charged"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"charging"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Not charging"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Plugged in, can\'t charge right now"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Full"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlled by admin"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Enabled by admin"</string> diff --git a/packages/SettingsLib/res/values-en-rXC/arrays.xml b/packages/SettingsLib/res/values-en-rXC/arrays.xml new file mode 100644 index 000000000000..2e74ce1cf8dd --- /dev/null +++ b/packages/SettingsLib/res/values-en-rXC/arrays.xml @@ -0,0 +1,255 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** +** Copyright 2015 The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string-array name="wifi_status"> + <item msgid="1922181315419294640"></item> + <item msgid="8934131797783724664">"Scanning…"</item> + <item msgid="8513729475867537913">"Connecting…"</item> + <item msgid="515055375277271756">"Authenticating…"</item> + <item msgid="1943354004029184381">"Obtaining IP address…"</item> + <item msgid="4221763391123233270">"Connected"</item> + <item msgid="624838831631122137">"Suspended"</item> + <item msgid="7979680559596111948">"Disconnecting…"</item> + <item msgid="1634960474403853625">"Disconnected"</item> + <item msgid="746097431216080650">"Unsuccessful"</item> + <item msgid="6367044185730295334">"Blocked"</item> + <item msgid="503942654197908005">"Temporarily avoiding poor connection"</item> + </string-array> + <string-array name="wifi_status_with_ssid"> + <item msgid="7714855332363650812"></item> + <item msgid="8878186979715711006">"Scanning…"</item> + <item msgid="355508996603873860">"Connecting to <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item> + <item msgid="554971459996405634">"Authenticating with <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item> + <item msgid="7928343808033020343">"Obtaining IP address from <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item> + <item msgid="8937994881315223448">"Connected to <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</item> + <item msgid="1330262655415760617">"Suspended"</item> + <item msgid="7698638434317271902">"Disconnecting from <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item> + <item msgid="197508606402264311">"Disconnected"</item> + <item msgid="8578370891960825148">"Unsuccessful"</item> + <item msgid="5660739516542454527">"Blocked"</item> + <item msgid="1805837518286731242">"Temporarily avoiding poor connection"</item> + </string-array> + <string-array name="hdcp_checking_titles"> + <item msgid="441827799230089869">"Never check"</item> + <item msgid="6042769699089883931">"Check for DRM content only"</item> + <item msgid="9174900380056846820">"Always check"</item> + </string-array> + <string-array name="hdcp_checking_summaries"> + <item msgid="505558545611516707">"Never use HDCP checking"</item> + <item msgid="3878793616631049349">"Use HDCP checking for DRM content only"</item> + <item msgid="45075631231212732">"Always use HDCP checking"</item> + </string-array> + <string-array name="bluetooth_avrcp_versions"> + <item msgid="5347678900838034763">"AVRCP 1.4 (Default)"</item> + <item msgid="2089555299377409443">"AVRCP 1.5"</item> + <item msgid="2895327394279434278">"AVRCP 1.6"</item> + </string-array> + <string-array name="bluetooth_avrcp_version_values"> + <item msgid="2838624067805073303">"avrcp14"</item> + <item msgid="1913619118958233129">"avrcp15"</item> + <item msgid="7142710449249088270">"avrcp16"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_titles"> + <item msgid="7065842274271279580">"Use System Selection (Default)"</item> + <item msgid="7539690996561263909">"SBC"</item> + <item msgid="686685526567131661">"AAC"</item> + <item msgid="5254942598247222737">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> + <item msgid="2091430979086738145">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> + <item msgid="6751080638867012696">"LDAC"</item> + <item msgid="723675059572222462">"Enable Optional Codecs"</item> + <item msgid="3304843301758635896">"Disable Optional Codecs"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_summaries"> + <item msgid="5062108632402595000">"Use System Selection (Default)"</item> + <item msgid="6898329690939802290">"SBC"</item> + <item msgid="6839647709301342559">"AAC"</item> + <item msgid="7848030269621918608">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item> + <item msgid="298198075927343893">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item> + <item msgid="7950781694447359344">"LDAC"</item> + <item msgid="2209680154067241740">"Enable Optional Codecs"</item> + <item msgid="741805482892725657">"Disable Optional Codecs"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> + <item msgid="3093023430402746802">"Use System Selection (Default)"</item> + <item msgid="8895532488906185219">"44.1 kHz"</item> + <item msgid="2909915718994807056">"48.0 kHz"</item> + <item msgid="3347287377354164611">"88.2 kHz"</item> + <item msgid="1234212100239985373">"96.0 kHz"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_sample_rate_summaries"> + <item msgid="3214516120190965356">"Use System Selection (Default)"</item> + <item msgid="4482862757811638365">"44.1 kHz"</item> + <item msgid="354495328188724404">"48.0 kHz"</item> + <item msgid="7329816882213695083">"88.2 kHz"</item> + <item msgid="6967397666254430476">"96.0 kHz"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles"> + <item msgid="2684127272582591429">"Use System Selection (Default)"</item> + <item msgid="5618929009984956469">"16 bits/sample"</item> + <item msgid="3412640499234627248">"24 bits/sample"</item> + <item msgid="121583001492929387">"32 bits/sample"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries"> + <item msgid="1081159789834584363">"Use System Selection (Default)"</item> + <item msgid="4726688794884191540">"16 bits/sample"</item> + <item msgid="305344756485516870">"24 bits/sample"</item> + <item msgid="244568657919675099">"32 bits/sample"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_channel_mode_titles"> + <item msgid="5226878858503393706">"Use System Selection (Default)"</item> + <item msgid="4106832974775067314">"Mono"</item> + <item msgid="5571632958424639155">"Stereo"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_channel_mode_summaries"> + <item msgid="4118561796005528173">"Use System Selection (Default)"</item> + <item msgid="8900559293912978337">"Mono"</item> + <item msgid="8883739882299884241">"Stereo"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles"> + <item msgid="7158319962230727476">"Optimized for Audio Quality (990kbps/909kbps)"</item> + <item msgid="2921767058740704969">"Balanced Audio And Connection Quality (660kbps/606kbps)"</item> + <item msgid="8860982705384396512">"Optimized for Connection Quality (330kbps/303kbps)"</item> + <item msgid="4414060457677684127">"Best Effort (Adaptive Bit Rate)"</item> + </string-array> + <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries"> + <item msgid="6398189564246596868">"Optimized for Audio Quality"</item> + <item msgid="4327143584633311908">"Balanced Audio And Connection Quality"</item> + <item msgid="4681409244565426925">"Optimized for Connection Quality"</item> + <item msgid="364670732877872677">"Best Effort (Adaptive Bit Rate)"</item> + </string-array> + <string-array name="select_logd_size_titles"> + <item msgid="8665206199209698501">"Off"</item> + <item msgid="1593289376502312923">"64K"</item> + <item msgid="487545340236145324">"256K"</item> + <item msgid="2423528675294333831">"1M"</item> + <item msgid="180883774509476541">"4M"</item> + <item msgid="2803199102589126938">"16M"</item> + </string-array> + <string-array name="select_logd_size_lowram_titles"> + <item msgid="6089470720451068364">"Off"</item> + <item msgid="4622460333038586791">"64K"</item> + <item msgid="2212125625169582330">"256K"</item> + <item msgid="1704946766699242653">"1M"</item> + </string-array> + <string-array name="select_logd_size_summaries"> + <item msgid="6921048829791179331">"Off"</item> + <item msgid="2969458029344750262">"64K per log buffer"</item> + <item msgid="1342285115665698168">"256K per log buffer"</item> + <item msgid="1314234299552254621">"1M per log buffer"</item> + <item msgid="3606047780792894151">"4M per log buffer"</item> + <item msgid="5431354956856655120">"16M per log buffer"</item> + </string-array> + <string-array name="select_logpersist_titles"> + <item msgid="1744840221860799971">"Off"</item> + <item msgid="3054662377365844197">"All"</item> + <item msgid="688870735111627832">"All but radio"</item> + <item msgid="2850427388488887328">"kernel only"</item> + </string-array> + <string-array name="select_logpersist_summaries"> + <item msgid="2216470072500521830">"Off"</item> + <item msgid="172978079776521897">"All log buffers"</item> + <item msgid="3873873912383879240">"All but radio log buffers"</item> + <item msgid="8489661142527693381">"kernel log buffer only"</item> + </string-array> + <string-array name="window_animation_scale_entries"> + <item msgid="8134156599370824081">"Animation off"</item> + <item msgid="6624864048416710414">"Animation scale .5x"</item> + <item msgid="2219332261255416635">"Animation scale 1x"</item> + <item msgid="3544428804137048509">"Animation scale 1.5x"</item> + <item msgid="3110710404225974514">"Animation scale 2x"</item> + <item msgid="4402738611528318731">"Animation scale 5x"</item> + <item msgid="6189539267968330656">"Animation scale 10x"</item> + </string-array> + <string-array name="transition_animation_scale_entries"> + <item msgid="8464255836173039442">"Animation off"</item> + <item msgid="3375781541913316411">"Animation scale .5x"</item> + <item msgid="1991041427801869945">"Animation scale 1x"</item> + <item msgid="4012689927622382874">"Animation scale 1.5x"</item> + <item msgid="3289156759925947169">"Animation scale 2x"</item> + <item msgid="7705857441213621835">"Animation scale 5x"</item> + <item msgid="6660750935954853365">"Animation scale 10x"</item> + </string-array> + <string-array name="animator_duration_scale_entries"> + <item msgid="6039901060648228241">"Animation off"</item> + <item msgid="1138649021950863198">"Animation scale .5x"</item> + <item msgid="4394388961370833040">"Animation scale 1x"</item> + <item msgid="8125427921655194973">"Animation scale 1.5x"</item> + <item msgid="3334024790739189573">"Animation scale 2x"</item> + <item msgid="3170120558236848008">"Animation scale 5x"</item> + <item msgid="1069584980746680398">"Animation scale 10x"</item> + </string-array> + <string-array name="overlay_display_devices_entries"> + <item msgid="1606809880904982133">"None"</item> + <item msgid="9033194758688161545">"480p"</item> + <item msgid="1025306206556583600">"480p (secure)"</item> + <item msgid="1853913333042744661">"720p"</item> + <item msgid="3414540279805870511">"720p (secure)"</item> + <item msgid="9039818062847141551">"1080p"</item> + <item msgid="4939496949750174834">"1080p (secure)"</item> + <item msgid="1833612718524903568">"4K"</item> + <item msgid="238303513127879234">"4K (secure)"</item> + <item msgid="3547211260846843098">"4K (upscaled)"</item> + <item msgid="5411365648951414254">"4K (upscaled, secure)"</item> + <item msgid="1311305077526792901">"720p, 1080p (dual screen)"</item> + </string-array> + <string-array name="enable_opengl_traces_entries"> + <item msgid="3191973083884253830">"None"</item> + <item msgid="9089630089455370183">"Logcat"</item> + <item msgid="5397807424362304288">"Systrace (Graphics)"</item> + <item msgid="1340692776955662664">"Call stack on glGetError"</item> + </string-array> + <string-array name="show_non_rect_clip_entries"> + <item msgid="993742912147090253">"Off"</item> + <item msgid="675719912558941285">"Draw non-rectangular clip region in blue"</item> + <item msgid="1064373276095698656">"Highlight tested drawing commands in green"</item> + </string-array> + <string-array name="track_frame_time_entries"> + <item msgid="2193584639058893150">"Off"</item> + <item msgid="2751513398307949636">"On screen as bars"</item> + <item msgid="2355151170975410323">"In <xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g>"</item> + </string-array> + <string-array name="debug_hw_overdraw_entries"> + <item msgid="8190572633763871652">"Off"</item> + <item msgid="7688197031296835369">"Show overdraw areas"</item> + <item msgid="2290859360633824369">"Show areas for Deuteranomaly"</item> + </string-array> + <string-array name="debug_hw_renderer_entries"> + <item msgid="2578620445459945681">"OpenGL (Default)"</item> + <item msgid="2839130076198120436">"OpenGL (Skia)"</item> + </string-array> + <string-array name="app_process_limit_entries"> + <item msgid="3401625457385943795">"Standard limit"</item> + <item msgid="4071574792028999443">"No background processes"</item> + <item msgid="4810006996171705398">"At most 1 process"</item> + <item msgid="8586370216857360863">"At most 2 processes"</item> + <item msgid="836593137872605381">"At most 3 processes"</item> + <item msgid="7899496259191969307">"At most 4 processes"</item> + </string-array> + <string-array name="usb_configuration_titles"> + <item msgid="488237561639712799">"Charging"</item> + <item msgid="5220695614993094977">"MTP (Media Transfer Protocol)"</item> + <item msgid="2086000968159047375">"PTP (Picture Transfer Protocol)"</item> + <item msgid="7398830860950841822">"RNDIS (USB Ethernet)"</item> + <item msgid="1718924214939774352">"Audio Source"</item> + <item msgid="8126315616613006284">"MIDI"</item> + </string-array> +</resources> diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml new file mode 100644 index 000000000000..01809e766d5d --- /dev/null +++ b/packages/SettingsLib/res/values-en-rXC/strings.xml @@ -0,0 +1,395 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** +** Copyright 2015 The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Can\'t scan for networks"</string> + <string name="wifi_security_none" msgid="7985461072596594400">"None"</string> + <string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string> + <string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string> + <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string> + <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Not connected due to low quality network"</string> + <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"WiFi Connection Failure"</string> + <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Authentication problem"</string> + <string name="wifi_cant_connect" msgid="5410016875644565884">"Can\'t connect"</string> + <string name="wifi_cant_connect_to_ap" msgid="1222553274052685331">"Can\'t connect to \'<xliff:g id="AP_NAME">%1$s</xliff:g>\'"</string> + <string name="wifi_check_password_try_again" msgid="516958988102584767">"Check password and try again"</string> + <string name="wifi_not_in_range" msgid="1136191511238508967">"Not in range"</string> + <string name="wifi_no_internet_no_reconnect" msgid="5724903347310541706">"Won\'t automatically connect"</string> + <string name="wifi_no_internet" msgid="3880396223819116454">"No Internet access"</string> + <string name="saved_network" msgid="4352716707126620811">"Saved by <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatically connected via %1$s"</string> + <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatically connected via network rating provider"</string> + <string name="connected_via_passpoint" msgid="2826205693803088747">"Connected via %1$s"</string> + <string name="available_via_passpoint" msgid="1617440946846329613">"Available via %1$s"</string> + <string name="wifi_connected_no_internet" msgid="3149853966840874992">"Connected, no Internet"</string> + <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Access point temporarily full"</string> + <string name="connected_via_carrier" msgid="7583780074526041912">"Connected via %1$s"</string> + <string name="available_via_carrier" msgid="1469036129740799053">"Available via %1$s"</string> + <string name="speed_label_very_slow" msgid="1867055264243608530">"Very Slow"</string> + <string name="speed_label_slow" msgid="813109590815810235">"Slow"</string> + <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> + <string name="speed_label_medium" msgid="3175763313268941953">"Medium"</string> + <string name="speed_label_fast" msgid="7715732164050975057">"Fast"</string> + <string name="speed_label_very_fast" msgid="2265363430784523409">"Very Fast"</string> + <string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string> + <string name="bluetooth_disconnected" msgid="6557104142667339895">"Disconnected"</string> + <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Disconnecting…"</string> + <string name="bluetooth_connecting" msgid="8555009514614320497">"Connecting…"</string> + <string name="bluetooth_connected" msgid="6038755206916626419">"Connected"</string> + <string name="bluetooth_pairing" msgid="1426882272690346242">"Pairing…"</string> + <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Connected (no phone)"</string> + <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Connected (no media)"</string> + <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Connected (no message access)"</string> + <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Connected (no phone or media)"</string> + <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"Connected, battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"Connected (no phone), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"Connected (no media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> + <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media audio"</string> + <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Phone calls"</string> + <string name="bluetooth_profile_opp" msgid="9168139293654233697">"File transfer"</string> + <string name="bluetooth_profile_hid" msgid="3680729023366986480">"Input device"</string> + <string name="bluetooth_profile_pan" msgid="3391606497945147673">"Internet access"</string> + <string name="bluetooth_profile_pbap" msgid="5372051906968576809">"Contact sharing"</string> + <string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"Use for contact sharing"</string> + <string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"Internet connection sharing"</string> + <string name="bluetooth_profile_map" msgid="1019763341565580450">"Text Messages"</string> + <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Access"</string> + <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string> + <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string> + <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connected to media audio"</string> + <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connected to phone audio"</string> + <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connected to file transfer server"</string> + <string name="bluetooth_map_profile_summary_connected" msgid="8191407438851351713">"Connected to map"</string> + <string name="bluetooth_sap_profile_summary_connected" msgid="8561765057453083838">"Connected to SAP"</string> + <string name="bluetooth_opp_profile_summary_not_connected" msgid="1267091356089086285">"Not connected to file transfer server"</string> + <string name="bluetooth_hid_profile_summary_connected" msgid="3381760054215168689">"Connected to input device"</string> + <string name="bluetooth_pan_user_profile_summary_connected" msgid="4602294638909590612">"Connected to device for Internet access"</string> + <string name="bluetooth_pan_nap_profile_summary_connected" msgid="1561383706411975199">"Sharing local Internet connection with device"</string> + <string name="bluetooth_pan_profile_summary_use_for" msgid="5664884523822068653">"Use for Internet access"</string> + <string name="bluetooth_map_profile_summary_use_for" msgid="5154200119919927434">"Use for map"</string> + <string name="bluetooth_sap_profile_summary_use_for" msgid="7085362712786907993">"Use for SIM access"</string> + <string name="bluetooth_a2dp_profile_summary_use_for" msgid="4630849022250168427">"Use for media audio"</string> + <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Use for phone audio"</string> + <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Use for file transfer"</string> + <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Use for input"</string> + <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Pair"</string> + <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAIR"</string> + <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancel"</string> + <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Pairing grants access to your contacts and call history when connected."</string> + <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"Couldn\'t pair with <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> + <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"Couldn\'t pair with <xliff:g id="DEVICE_NAME">%1$s</xliff:g> because of an incorrect PIN or passkey."</string> + <string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"Can\'t communicate with <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> + <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"Pairing rejected by <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> + <string name="accessibility_wifi_off" msgid="1166761729660614716">"Wifi off."</string> + <string name="accessibility_no_wifi" msgid="8834610636137374508">"Wifi disconnected."</string> + <string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wifi one bar."</string> + <string name="accessibility_wifi_two_bars" msgid="3569851234710034416">"Wifi two bars."</string> + <string name="accessibility_wifi_three_bars" msgid="8134185644861380311">"Wifi three bars."</string> + <string name="accessibility_wifi_signal_full" msgid="7061045677694702">"Wifi signal full."</string> + <string name="accessibility_wifi_security_type_none" msgid="1223747559986205423">"Open network"</string> + <string name="accessibility_wifi_security_type_secured" msgid="862921720418885331">"Secure network"</string> + <string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string> + <string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Removed apps"</string> + <string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Removed apps and users"</string> + <string name="tether_settings_title_usb" msgid="6688416425801386511">"USB tethering"</string> + <string name="tether_settings_title_wifi" msgid="3277144155960302049">"Portable hotspot"</string> + <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth tethering"</string> + <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"Tethering"</string> + <string name="tether_settings_title_all" msgid="8356136101061143841">"Tethering & portable hotspot"</string> + <string name="managed_user_title" msgid="8109605045406748842">"All work apps"</string> + <string name="user_guest" msgid="8475274842845401871">"Guest"</string> + <string name="unknown" msgid="1592123443519355854">"Unknown"</string> + <string name="running_process_item_user_label" msgid="3129887865552025943">"User: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string> + <string name="launch_defaults_some" msgid="313159469856372621">"Some defaults set"</string> + <string name="launch_defaults_none" msgid="4241129108140034876">"No defaults set"</string> + <string name="tts_settings" msgid="8186971894801348327">"Text-to-speech settings"</string> + <string name="tts_settings_title" msgid="1237820681016639683">"Text-to-speech output"</string> + <string name="tts_default_rate_title" msgid="6030550998379310088">"Speech rate"</string> + <string name="tts_default_rate_summary" msgid="4061815292287182801">"Speed at which the text is spoken"</string> + <string name="tts_default_pitch_title" msgid="6135942113172488671">"Pitch"</string> + <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Affects the tone of the synthesized speech"</string> + <string name="tts_default_lang_title" msgid="8018087612299820556">"Language"</string> + <string name="tts_lang_use_system" msgid="2679252467416513208">"Use system language"</string> + <string name="tts_lang_not_selected" msgid="7395787019276734765">"Language not selected"</string> + <string name="tts_default_lang_summary" msgid="5219362163902707785">"Sets the language-specific voice for the spoken text"</string> + <string name="tts_play_example_title" msgid="7094780383253097230">"Listen to an example"</string> + <string name="tts_play_example_summary" msgid="8029071615047894486">"Play a short demonstration of speech synthesis"</string> + <string name="tts_install_data_title" msgid="4264378440508149986">"Install voice data"</string> + <string name="tts_install_data_summary" msgid="5742135732511822589">"Install the voice data required for speech synthesis"</string> + <string name="tts_engine_security_warning" msgid="8786238102020223650">"This speech synthesis engine may be able to collect all the text that will be spoken, including personal data like passwords and credit card numbers. It comes from the <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> engine. Enable the use of this speech synthesis engine?"</string> + <string name="tts_engine_network_required" msgid="1190837151485314743">"This language requires a working network connection for text-to-speech output."</string> + <string name="tts_default_sample_string" msgid="4040835213373086322">"This is an example of speech synthesis"</string> + <string name="tts_status_title" msgid="7268566550242584413">"Default language status"</string> + <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> is fully supported"</string> + <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> requires network connection"</string> + <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> is not supported"</string> + <string name="tts_status_checking" msgid="5339150797940483592">"Checking…"</string> + <string name="tts_engine_settings_title" msgid="3499112142425680334">"Settings for <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string> + <string name="tts_engine_settings_button" msgid="1030512042040722285">"Launch engine settings"</string> + <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Preferred engine"</string> + <string name="tts_general_section_title" msgid="4402572014604490502">"General"</string> + <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Reset speech pitch"</string> + <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Reset the pitch at which the text is spoken to default."</string> + <string-array name="tts_rate_entries"> + <item msgid="6695494874362656215">"Very slow"</item> + <item msgid="4795095314303559268">"Slow"</item> + <item msgid="8903157781070679765">"Normal"</item> + <item msgid="164347302621392996">"Fast"</item> + <item msgid="5794028588101562009">"Faster"</item> + <item msgid="7163942783888652942">"Very fast"</item> + <item msgid="7831712693748700507">"Rapid"</item> + <item msgid="5194774745031751806">"Very rapid"</item> + <item msgid="9085102246155045744">"Fastest"</item> + </string-array> + <string name="choose_profile" msgid="6921016979430278661">"Choose profile"</string> + <string name="category_personal" msgid="1299663247844969448">"Personal"</string> + <string name="category_work" msgid="8699184680584175622">"Work"</string> + <string name="development_settings_title" msgid="215179176067683667">"Developer options"</string> + <string name="development_settings_enable" msgid="542530994778109538">"Enable developer options"</string> + <string name="development_settings_summary" msgid="1815795401632854041">"Set options for app development"</string> + <string name="development_settings_not_available" msgid="4308569041701535607">"Developer options are not available for this user"</string> + <string name="vpn_settings_not_available" msgid="956841430176985598">"VPN settings are not available for this user"</string> + <string name="tethering_settings_not_available" msgid="6765770438438291012">"Tethering settings are not available for this user"</string> + <string name="apn_settings_not_available" msgid="7873729032165324000">"Access Point Name settings are not available for this user"</string> + <string name="enable_adb" msgid="7982306934419797485">"USB debugging"</string> + <string name="enable_adb_summary" msgid="4881186971746056635">"Debug mode when USB is connected"</string> + <string name="clear_adb_keys" msgid="4038889221503122743">"Revoke USB debugging authorizations"</string> + <string name="bugreport_in_power" msgid="7923901846375587241">"Bug report shortcut"</string> + <string name="bugreport_in_power_summary" msgid="1778455732762984579">"Show a button in the power menu for taking a bug report"</string> + <string name="keep_screen_on" msgid="1146389631208760344">"Stay awake"</string> + <string name="keep_screen_on_summary" msgid="2173114350754293009">"Screen will never sleep while charging"</string> + <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Enable Bluetooth HCI snoop log"</string> + <string name="bt_hci_snoop_log_summary" msgid="730247028210113851">"Capture all bluetooth HCI packets in a file"</string> + <string name="oem_unlock_enable" msgid="6040763321967327691">"OEM unlocking"</string> + <string name="oem_unlock_enable_summary" msgid="4720281828891618376">"Allow the bootloader to be unlocked"</string> + <string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"Allow OEM unlocking?"</string> + <string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"WARNING: Device protection features will not work on this device while this setting is turned on."</string> + <string name="mock_location_app" msgid="7966220972812881854">"Select mock location app"</string> + <string name="mock_location_app_not_set" msgid="809543285495344223">"No mock location app set"</string> + <string name="mock_location_app_set" msgid="8966420655295102685">"Mock location app: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string> + <string name="wifi_display_certification" msgid="8611569543791307533">"Wireless display certification"</string> + <string name="wifi_verbose_logging" msgid="4203729756047242344">"Enable Wi‑Fi Verbose Logging"</string> + <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressive Wi‑Fi to mobile handover"</string> + <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string> + <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string> + <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> + <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disable absolute volume"</string> + <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Enable in-band ringing"</string> + <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP Version"</string> + <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Select Bluetooth AVRCP Version"</string> + <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio Codec"</string> + <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Select Bluetooth Audio Codec"</string> + <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bluetooth Audio Sample Rate"</string> + <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Select Bluetooth Audio Codec:\nSample Rate"</string> + <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bluetooth Audio Bits Per Sample"</string> + <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Select Bluetooth Audio Codec:\nBits Per Sample"</string> + <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Bluetooth Audio Channel Mode"</string> + <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Select Bluetooth Audio Codec:\nChannel Mode"</string> + <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth Audio LDAC Codec: Playback Quality"</string> + <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Select Bluetooth Audio LDAC Codec:\nPlayback Quality"</string> + <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streaming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string> + <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string> + <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string> + <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"When enabled, Wi‑Fi will be more aggressive in handing over the data connection to mobile, when Wi‑Fi signal is low"</string> + <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface"</string> + <string name="select_logd_size_title" msgid="7433137108348553508">"Logger buffer sizes"</string> + <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Select Logger sizes per log buffer"</string> + <string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Clear logger persistent storage?"</string> + <string name="dev_logpersist_clear_warning_message" msgid="2256582531342994562">"When we no longer are monitoring with the persistent logger, we are required to erase the logger data resident on your device."</string> + <string name="select_logpersist_title" msgid="7530031344550073166">"Store logger data persistently on device"</string> + <string name="select_logpersist_dialog_title" msgid="4003400579973269060">"Select log buffers to store persistently on device"</string> + <string name="select_usb_configuration_title" msgid="2649938511506971843">"Select USB Configuration"</string> + <string name="select_usb_configuration_dialog_title" msgid="6385564442851599963">"Select USB Configuration"</string> + <string name="allow_mock_location" msgid="2787962564578664888">"Allow mock locations"</string> + <string name="allow_mock_location_summary" msgid="317615105156345626">"Allow mock locations"</string> + <string name="debug_view_attributes" msgid="6485448367803310384">"Enable view attribute inspection"</string> + <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Always keep mobile data active, even when Wi‑Fi is active (for fast network switching)."</string> + <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Use tethering hardware acceleration if available"</string> + <string name="adb_warning_title" msgid="6234463310896563253">"Allow USB debugging?"</string> + <string name="adb_warning_message" msgid="7316799925425402244">"USB debugging is intended for development purposes only. Use it to copy data between your computer and your device, install apps on your device without notification, and read log data."</string> + <string name="adb_keys_warning_message" msgid="5659849457135841625">"Revoke access to USB debugging from all computers you’ve previously authorized?"</string> + <string name="dev_settings_warning_title" msgid="7244607768088540165">"Allow development settings?"</string> + <string name="dev_settings_warning_message" msgid="2298337781139097964">"These settings are intended for development use only. They can cause your device and the applications on it to break or misbehave."</string> + <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verify apps over USB"</string> + <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Check apps installed via ADB/ADT for harmful behavior."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> + <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string> + <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Allow ringtones on the phone to be played on Bluetooth headsets"</string> + <string name="enable_terminal_title" msgid="95572094356054120">"Local terminal"</string> + <string name="enable_terminal_summary" msgid="67667852659359206">"Enable terminal app that offers local shell access"</string> + <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP checking"</string> + <string name="hdcp_checking_dialog_title" msgid="5141305530923283">"Set HDCP checking behavior"</string> + <string name="debug_debugging_category" msgid="6781250159513471316">"Debugging"</string> + <string name="debug_app" msgid="8349591734751384446">"Select debug app"</string> + <string name="debug_app_not_set" msgid="718752499586403499">"No debug application set"</string> + <string name="debug_app_set" msgid="2063077997870280017">"Debugging application: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="select_application" msgid="5156029161289091703">"Select application"</string> + <string name="no_application" msgid="2813387563129153880">"Nothing"</string> + <string name="wait_for_debugger" msgid="1202370874528893091">"Wait for debugger"</string> + <string name="wait_for_debugger_summary" msgid="1766918303462746804">"Debugged application waits for debugger to attach before executing"</string> + <string name="telephony_monitor_switch" msgid="1764958220062121194">"Telephony Monitor"</string> + <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"TelephonyMonitor will collect logs when it detects a problem with telephony/modem functionality and prompt notification to user to file a bug"</string> + <string name="debug_input_category" msgid="1811069939601180246">"Input"</string> + <string name="debug_drawing_category" msgid="6755716469267367852">"Drawing"</string> + <string name="debug_hw_drawing_category" msgid="6220174216912308658">"Hardware accelerated rendering"</string> + <string name="media_category" msgid="4388305075496848353">"Media"</string> + <string name="debug_monitoring_category" msgid="7640508148375798343">"Monitoring"</string> + <string name="strict_mode" msgid="1938795874357830695">"Strict mode enabled"</string> + <string name="strict_mode_summary" msgid="142834318897332338">"Flash screen when apps do long operations on main thread"</string> + <string name="pointer_location" msgid="6084434787496938001">"Pointer location"</string> + <string name="pointer_location_summary" msgid="840819275172753713">"Screen overlay showing current touch data"</string> + <string name="show_touches" msgid="2642976305235070316">"Show taps"</string> + <string name="show_touches_summary" msgid="6101183132903926324">"Show visual feedback for taps"</string> + <string name="show_screen_updates" msgid="5470814345876056420">"Show surface updates"</string> + <string name="show_screen_updates_summary" msgid="2569622766672785529">"Flash entire window surfaces when they update"</string> + <string name="show_hw_screen_updates" msgid="5036904558145941590">"Show GPU view updates"</string> + <string name="show_hw_screen_updates_summary" msgid="1115593565980196197">"Flash views inside windows when drawn with the GPU"</string> + <string name="show_hw_layers_updates" msgid="5645728765605699821">"Show hardware layers updates"</string> + <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"Flash hardware layers green when they update"</string> + <string name="debug_hw_overdraw" msgid="2968692419951565417">"Debug GPU overdraw"</string> + <string name="debug_hw_renderer" msgid="7568529019431785816">"Set GPU Renderer"</string> + <string name="disable_overlays" msgid="2074488440505934665">"Disable HW overlays"</string> + <string name="disable_overlays_summary" msgid="3578941133710758592">"Always use GPU for screen compositing"</string> + <string name="simulate_color_space" msgid="6745847141353345872">"Simulate color space"</string> + <string name="enable_opengl_traces_title" msgid="6790444011053219871">"Enable OpenGL traces"</string> + <string name="usb_audio_disable_routing" msgid="8114498436003102671">"Disable USB audio routing"</string> + <string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"Disable automatic routing to USB audio peripherals"</string> + <string name="debug_layout" msgid="5981361776594526155">"Show layout bounds"</string> + <string name="debug_layout_summary" msgid="2001775315258637682">"Show clip bounds, margins, etc."</string> + <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Force RTL layout direction"</string> + <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Force screen layout direction to RTL for all locales"</string> + <string name="force_hw_ui" msgid="6426383462520888732">"Force GPU rendering"</string> + <string name="force_hw_ui_summary" msgid="5535991166074861515">"Force use of GPU for 2d drawing"</string> + <string name="force_msaa" msgid="7920323238677284387">"Force 4x MSAA"</string> + <string name="force_msaa_summary" msgid="9123553203895817537">"Enable 4x MSAA in OpenGL ES 2.0 apps"</string> + <string name="show_non_rect_clip" msgid="505954950474595172">"Debug non-rectangular clip operations"</string> + <string name="track_frame_time" msgid="6146354853663863443">"Profile GPU rendering"</string> + <string name="window_animation_scale_title" msgid="6162587588166114700">"Window animation scale"</string> + <string name="transition_animation_scale_title" msgid="387527540523595875">"Transition animation scale"</string> + <string name="animator_duration_scale_title" msgid="3406722410819934083">"Animator duration scale"</string> + <string name="overlay_display_devices_title" msgid="5364176287998398539">"Simulate secondary displays"</string> + <string name="debug_applications_category" msgid="4206913653849771549">"Apps"</string> + <string name="immediately_destroy_activities" msgid="1579659389568133959">"Don’t keep activities"</string> + <string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"Destroy every activity as soon as the user leaves it"</string> + <string name="app_process_limit_title" msgid="4280600650253107163">"Background process limit"</string> + <string name="show_all_anrs" msgid="28462979638729082">"Show all ANRs"</string> + <string name="show_all_anrs_summary" msgid="641908614413544127">"Show App Not Responding dialog for background apps"</string> + <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Show notification channel warnings"</string> + <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Displays on-screen warning when an app posts a notification without a valid channel"</string> + <string name="force_allow_on_external" msgid="3215759785081916381">"Force allow apps on external"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Makes any app eligible to be written to external storage, regardless of manifest values"</string> + <string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be resizable"</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Make all activities resizable for multi-window, regardless of manifest values."</string> + <string name="enable_freeform_support" msgid="1461893351278940416">"Enable freeform windows"</string> + <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Enable support for experimental freeform windows."</string> + <string name="local_backup_password_title" msgid="3860471654439418822">"Desktop backup password"</string> + <string name="local_backup_password_summary_none" msgid="6951095485537767956">"Desktop full backups aren’t currently protected"</string> + <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Tap to change or remove the password for desktop full backups"</string> + <string name="local_backup_password_toast_success" msgid="582016086228434290">"New backup password set"</string> + <string name="local_backup_password_toast_confirmation_mismatch" msgid="7805892532752708288">"New password and confirmation don’t match"</string> + <string name="local_backup_password_toast_validation_failure" msgid="5646377234895626531">"Failure setting backup password"</string> + <string-array name="color_mode_names"> + <item msgid="2425514299220523812">"Vibrant (default)"</item> + <item msgid="8446070607501413455">"Natural"</item> + <item msgid="6553408765810699025">"Standard"</item> + </string-array> + <string-array name="color_mode_descriptions"> + <item msgid="4979629397075120893">"Enhanced colors"</item> + <item msgid="8280754435979370728">"Natural colors as seen by the eye"</item> + <item msgid="5363960654009010371">"Colors optimized for digital content"</item> + </string-array> + <string name="inactive_apps_title" msgid="1317817863508274533">"Inactive apps"</string> + <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Inactive. Tap to toggle."</string> + <string name="inactive_app_active_summary" msgid="4174921824958516106">"Active. Tap to toggle."</string> + <string name="runningservices_settings_title" msgid="8097287939865165213">"Running services"</string> + <string name="runningservices_settings_summary" msgid="854608995821032748">"View and control currently running services"</string> + <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string> + <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Set WebView implementation"</string> + <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"This choice is no longer valid. Try again."</string> + <string name="convert_to_file_encryption" msgid="3060156730651061223">"Convert to file encryption"</string> + <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convert…"</string> + <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Already file encrypted"</string> + <string name="title_convert_fbe" msgid="1263622876196444453">"Converting to file based encryption"</string> + <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Convert data partition to file based encryption.\n !!Warning!! This will erase all your data.\n This feature is alpha, and may not work correctly.\n Press \'Wipe and convert…\' to continue."</string> + <string name="button_convert_fbe" msgid="5152671181309826405">"Wipe and convert…"</string> + <string name="picture_color_mode" msgid="4560755008730283695">"Picture color mode"</string> + <string name="picture_color_mode_desc" msgid="1141891467675548590">"Use sRGB"</string> + <string name="daltonizer_mode_disabled" msgid="7482661936053801862">"Disabled"</string> + <string name="daltonizer_mode_monochromacy" msgid="8485709880666106721">"Monochromacy"</string> + <string name="daltonizer_mode_deuteranomaly" msgid="5475532989673586329">"Deuteranomaly (red-green)"</string> + <string name="daltonizer_mode_protanomaly" msgid="8424148009038666065">"Protanomaly (red-green)"</string> + <string name="daltonizer_mode_tritanomaly" msgid="481725854987912389">"Tritanomaly (blue-yellow)"</string> + <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Color correction"</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string> + <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string> + <string name="power_remaining_duration_only" msgid="845431008899029842">"About <xliff:g id="TIME">^1</xliff:g> left"</string> + <string name="power_remaining_duration_only_enhanced" msgid="5992456722677973678">"About <xliff:g id="TIME">^1</xliff:g> left based on your usage"</string> + <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">^1</xliff:g> left until fully charged"</string> + <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">^1</xliff:g> left"</string> + <string name="power_remaining_duration_only_short_enhanced" msgid="7450425624026394823">"<xliff:g id="TIME">^1</xliff:g> left based on your usage"</string> + <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">^1</xliff:g> - about <xliff:g id="TIME">^2</xliff:g> left"</string> + <string name="power_discharging_duration_enhanced" msgid="4401782117770255046">"<xliff:g id="LEVEL">^1</xliff:g> - about <xliff:g id="TIME">^2</xliff:g> left based on your usage"</string> + <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> left"</string> + <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> + <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> until fully charged"</string> + <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string> + <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string> + <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"charging"</string> + <string name="battery_info_status_discharging" msgid="310932812698268588">"Not charging"</string> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Plugged in, can\'t charge right now"</string> + <string name="battery_info_status_full" msgid="2824614753861462808">"Full"</string> + <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlled by admin"</string> + <string name="enabled_by_admin" msgid="5302986023578399263">"Enabled by admin"</string> + <string name="disabled_by_admin" msgid="8505398946020816620">"Disabled by admin"</string> + <string name="disabled" msgid="9206776641295849915">"Disabled"</string> + <string name="external_source_trusted" msgid="2707996266575928037">"Allowed"</string> + <string name="external_source_untrusted" msgid="2677442511837596726">"Not allowed"</string> + <string name="install_other_apps" msgid="6986686991775883017">"Install unknown apps"</string> + <string name="home" msgid="3256884684164448244">"Settings Home"</string> + <string-array name="battery_labels"> + <item msgid="8494684293649631252">"0%"</item> + <item msgid="8934126114226089439">"50%"</item> + <item msgid="1286113608943010849">"100%"</item> + </string-array> + <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> ago"</string> + <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> left"</string> + <string name="screen_zoom_summary_small" msgid="5867245310241621570">"Small"</string> + <string name="screen_zoom_summary_default" msgid="2247006805614056507">"Default"</string> + <string name="screen_zoom_summary_large" msgid="4835294730065424084">"Large"</string> + <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Larger"</string> + <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Largest"</string> + <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Custom (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string> + <string name="help_feedback_label" msgid="6815040660801785649">"Help & feedback"</string> + <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string> + <string name="retail_demo_reset_message" msgid="118771671364131297">"Enter password to perform factory reset in demo mode"</string> + <string name="retail_demo_reset_next" msgid="8356731459226304963">"Next"</string> + <string name="retail_demo_reset_title" msgid="696589204029930100">"Password required"</string> + <string name="active_input_method_subtypes" msgid="3596398805424733238">"Active input methods"</string> + <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Use system languages"</string> + <string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Failed to open settings for <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string> + <string name="ime_security_warning" msgid="4135828934735934248">"This input method may be able to collect all the text you type, including personal data like passwords and credit card numbers. It comes from the app <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Use this input method?"</string> + <string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Note: After a reboot, this app can\'t start until you unlock your phone"</string> +</resources> diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml index ef6911401627..466d433b49b8 100644 --- a/packages/SettingsLib/res/values-es-rUS/arrays.xml +++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"Usar selección del sistema (predeterminado)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="2091430979086738145">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"Habilitar códecs opcionales"</item> <item msgid="3304843301758635896">"Inhabilitar códecs opcionales"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"Usar selección del sistema (predeterminado)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="298198075927343893">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"Habilitar códecs opcionales"</item> <item msgid="741805482892725657">"Inhabilitar códecs opcionales"</item> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index 8eff989dc8ff..2290a7ec3915 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -119,7 +119,7 @@ <string name="user_guest" msgid="8475274842845401871">"Invitado"</string> <string name="unknown" msgid="1592123443519355854">"Desconocido"</string> <string name="running_process_item_user_label" msgid="3129887865552025943">"Usuario: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string> - <string name="launch_defaults_some" msgid="313159469856372621">"Hay algunas configuraciones predeterminadas establecidas."</string> + <string name="launch_defaults_some" msgid="313159469856372621">"Configuraciones predeterminadas establecidas"</string> <string name="launch_defaults_none" msgid="4241129108140034876">"No hay configuraciones predeterminadas establecidas."</string> <string name="tts_settings" msgid="8186971894801348327">"Configuración de texto a voz"</string> <string name="tts_settings_title" msgid="1237820681016639683">"Salida de texto a voz"</string> @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir siempre búsquedas de Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Datos móviles siempre activados"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración de hardware de conexión mediante dispositivo portátil"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Inhabilitar volumen absoluto"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Habilitar sonido dentro de banda"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versión de AVRCP del Bluetooth"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Estos parámetros de configuración están destinados únicamente a los programadores. Pueden hacer que el dispositivo o sus aplicaciones no funcionen correctamente."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificar aplicaciones por USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Comprobar que las aplicaciones instaladas mediante ADB/ADT no ocasionen daños"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Inhabilita la función de volumen absoluto de Bluetooth si se producen problemas de volumen con dispositivos remotos (por ejemplo, volumen demasiado alto o falta de control)."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Permite que los tonos del teléfono suenen en auriculares Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - Tiempo restante: <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> (<xliff:g id="TIME">^2</xliff:g> para completar la carga)"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconocido"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"cargando"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"No se está cargando."</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Conectado. No se puede cargar en este momento"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Cargado"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlada por el administrador"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"El administrador habilitó esta opción"</string> diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml index 53c547dacd85..b6d52183597b 100644 --- a/packages/SettingsLib/res/values-es/arrays.xml +++ b/packages/SettingsLib/res/values-es/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"Usar preferencia del sistema (predeter.)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="2091430979086738145">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"Habilitar códecs opcionales"</item> <item msgid="3304843301758635896">"Inhabilitar códecs opcionales"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"Usar preferencia del sistema (predeter.)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="298198075927343893">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"Habilitar códecs opcionales"</item> <item msgid="741805482892725657">"Inhabilitar códecs opcionales"</item> diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index 4ac4b27db638..2819d4104fb7 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir siempre búsquedas de Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Datos móviles siempre activos"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración por hardware para conexión compartida"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Inhabilitar volumen absoluto"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Habilitar tono de llamada por Bluetooth"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versión AVRCP del Bluetooth"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Estos ajustes están destinados únicamente a los desarrolladores. Pueden provocar que el dispositivo o las aplicaciones no funcionen correctamente."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificar aplicaciones por USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Comprueba las aplicaciones instaladas mediante ADB/ADT para detectar comportamientos dañinos"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Inhabilita la función de volumen absoluto de Bluetooth si se producen problemas de volumen con dispositivos remotos (por ejemplo, volumen demasiado alto o falta de control)."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Permite que los tonos de llamada del teléfono se reproduzcan en auriculares Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - Tiempo restante: <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> para completar la carga"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconocido"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"cargando"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"No se está cargando"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Se ha conectado, pero no se puede cargar en este momento"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Completa"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlada por el administrador"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Habilitada por el administrador"</string> diff --git a/packages/SettingsLib/res/values-et/arrays.xml b/packages/SettingsLib/res/values-et/arrays.xml index 77668900b27e..191517651718 100644 --- a/packages/SettingsLib/res/values-et/arrays.xml +++ b/packages/SettingsLib/res/values-et/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Süsteemi valiku kasutamine (vaikeseade)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Lubatakse valikulised kodekid"</item> - <item msgid="3304843301758635896">"Keelatakse valikulised kodekid"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Süsteemi valiku kasutamine (vaikeseade)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Lubatakse valikulised kodekid"</item> - <item msgid="741805482892725657">"Keelatakse valikulised kodekid"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Süsteemi valiku kasutamine (vaikeseade)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml index 28a2a596d627..a5299c2ca80f 100644 --- a/packages/SettingsLib/res/values-et/strings.xml +++ b/packages/SettingsLib/res/values-et/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Luba alati WiFi-rändluse skannimine"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiilne andmeside on alati aktiivne"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Jagamise riistvaraline kiirendus"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Keela absoluutne helitugevus"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Luba ribasisene helisemine"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetoothi AVRCP versioon"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Need seaded on mõeldud ainult arendajatele. Need võivad põhjustada seadme ja seadmes olevate rakenduste rikkeid või valesti toimimist."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Kinnita rakendus USB kaudu"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrolli, kas ADB/ADT-ga installitud rakendused on ohtlikud."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Keelatakse Bluetoothi absoluutse helitugevuse funktsioon, kui kaugseadmetega on helitugevuse probleeme (nt liiga vali heli või juhitavuse puudumine)."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Lubab telefonis olevaid helinaid esitada Bluetoothi peakomplektides"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Kohalik terminal"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> on jäänud"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> täislaadimiseni"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Tundmatu"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Laadimine"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"laadimine"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Ei lae"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Vooluvõrgus, praegu ei saa laadida"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Täis"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Juhib administraator"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Administraatori lubatud"</string> diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml index 444ffbc4de22..64d59863ca8c 100644 --- a/packages/SettingsLib/res/values-eu/arrays.xml +++ b/packages/SettingsLib/res/values-eu/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Erabili sistema-hautapena (lehenetsia)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Gaitu aukerako kodekak"</item> - <item msgid="3304843301758635896">"Desgaitu aukerako kodekak"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Erabili sistema-hautapena (lehenetsia)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Gaitu aukerako kodekak"</item> - <item msgid="741805482892725657">"Desgaitu aukerako kodekak"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Erabili sistema-hautapena (lehenetsia)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml index 4e19b9942b91..1629e41026fb 100644 --- a/packages/SettingsLib/res/values-eu/strings.xml +++ b/packages/SettingsLib/res/values-eu/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Onartu beti ibiltaritzan Wi-Fi sareak bilatzea"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Datu mugikorrak beti aktibo"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Konexioa partekatzeko hardwarearen azelerazioa"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desgaitu bolumen absolutua"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Gaitu tonuak audio-kanal berean erreproduzitzeko aukera"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP bertsioa"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Ezarpen hauek garapen-xedeetarako pentsatu dira soilik. Baliteke ezarpenen eraginez gailua matxuratzea edo funtzionamendu okerra izatea."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Egiaztatu USBko aplikazioak."</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Egiaztatu ADB/ADT bidez instalatutako aplikazioak portaera kaltegarriak antzemateko."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desgaitu egiten du Bluetooth bidezko bolumen absolutuaren eginbidea urruneko gailuetan arazoak hautematen badira; esaterako, bolumena ozenegia bada edo ezin bada kontrolatu."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Onartu telefonoko tonuak Bluetooth entzungailuetan erreproduzitzeko aukera"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Tokiko terminala"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> guztiz kargatu arte"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> guztiz kargatu arte"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Ezezaguna"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Kargatzen"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"kargatzen"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Ez da kargatzen ari"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Konektatuta dago. Ezin da kargatu une honetan."</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Beteta"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Administratzaileak kontrolatzen du"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Administratzaileak gaitu du"</string> diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml index b9fa5e40f603..d2297778fb00 100644 --- a/packages/SettingsLib/res/values-fa/arrays.xml +++ b/packages/SettingsLib/res/values-fa/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"استفاده از انتخاب سیستم (پیشفرض)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="2091430979086738145">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"فعال کردن کدکهای اختیاری"</item> <item msgid="3304843301758635896">"غیرفعال کردن کدکهای اختیاری"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"استفاده از انتخاب سیستم (پیشفرض)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="298198075927343893">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"فعال کردن کدکهای اختیاری"</item> <item msgid="741805482892725657">"غیرفعال کردن کدکهای اختیاری"</item> diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml index 15facd8bf190..5d806d0217b5 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"اسکنهای رومینگ Wi‑Fi همیشه مجاز است"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"داده تلفن همراه همیشه فعال باشد"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"شتاب سختافزاری اتصال به اینترنت با تلفن همراه"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"غیرفعال کردن میزان صدای مطلق"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"فعال کردن زنگ زدن درون باندی"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"نسخه AVRCP بلوتوث"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"این تنظیمات فقط برای برنامهنویسی در نظر گرفته شده است. ممکن است استفاده از این تنظیمات موجب خرابی یا عملکرد نادرست دستگاه یا برنامههای شما شود."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"تأیید برنامههای نصب شده از طریق USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"برنامههای نصب شده از طریق ADB/ADT را ازنظر رفتار مخاطرهآمیز بررسی کنید."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"در صورت وجود مشکل میزان صدا با دستگاههای راه دور مثل میزان صدای بلند ناخوشایند یا عدم کنترل صدا، قابلیت میزان صدای کامل بلوتوث را غیرفعال کنید."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"اجازه میدهد آهنگهای زنگ تلفن در هدستهای بلوتوث پخش شود"</string> <string name="enable_terminal_title" msgid="95572094356054120">"ترمینال محلی"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> باقی مانده"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> مانده تا شارژ کامل"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"ناشناس"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"در حال شارژ شدن"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"درحال شارژ شدن"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"شارژ نمیشود"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"به برق وصل شده است، درحالحاضر شارژ نمیشود"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"پر"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"توسط سرپرست سیستم کنترل میشود"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"فعالشده توسط سرپرست"</string> diff --git a/packages/SettingsLib/res/values-fi/arrays.xml b/packages/SettingsLib/res/values-fi/arrays.xml index 7a5f8604face..311d408a7ca0 100644 --- a/packages/SettingsLib/res/values-fi/arrays.xml +++ b/packages/SettingsLib/res/values-fi/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"Käytä järjestelmän valintaa (oletus)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ‑ääni"</item> + <item msgid="2091430979086738145">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ‑ääni"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"Ota valinnaiset koodekit käyttöön"</item> <item msgid="3304843301758635896">"Poista valinnaiset koodekit käytöstä"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"Käytä järjestelmän valintaa (oletus)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ‑ääni"</item> + <item msgid="298198075927343893">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ‑ääni"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"Ota valinnaiset koodekit käyttöön"</item> <item msgid="741805482892725657">"Poista valinnaiset koodekit käytöstä"</item> diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index 59ba1379d246..6b3953effba9 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -119,7 +119,7 @@ <string name="user_guest" msgid="8475274842845401871">"Vieras"</string> <string name="unknown" msgid="1592123443519355854">"Tuntematon"</string> <string name="running_process_item_user_label" msgid="3129887865552025943">"Käyttäjä: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string> - <string name="launch_defaults_some" msgid="313159469856372621">"Joitakin oletuksia on asetettu."</string> + <string name="launch_defaults_some" msgid="313159469856372621">"Joitakin oletuksia on asetettu"</string> <string name="launch_defaults_none" msgid="4241129108140034876">"Oletuksia ei asetettu."</string> <string name="tts_settings" msgid="8186971894801348327">"Tekstistä puheeksi -asetukset"</string> <string name="tts_settings_title" msgid="1237820681016639683">"Tekstistä puheeksi -toisto"</string> @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Salli Wi-Fi-verkkovierailuskannaus aina"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiilidata aina käytössä"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Laitteistokiihdytyksen yhteyden jakaminen"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Poista yleinen äänenvoimakkuuden säätö käytöstä"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Ota käyttöön kaistalla soitto"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetoothin AVRCP-versio"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Nämä asetukset on tarkoitettu vain kehityskäyttöön, ja ne voivat aiheuttaa haittaa laitteellesi tai sen sovelluksille."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Tarkista USB:n kautta asennetut"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Tarkista ADB:n/ADT:n kautta asennetut sovellukset haitallisen toiminnan varalta."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Bluetoothin yleinen äänenvoimakkuuden säätö poistetaan käytöstä ongelmien välttämiseksi esimerkiksi silloin, kun laitteen äänenvoimakkuus on liian kova tai sitä ei voi säätää."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Salli puhelimen soittoäänten toistaminen Bluetooth-kuulokemikrofoneissa"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Paikallinen pääte"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> jäljellä"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> täyteen lataukseen"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Tuntematon"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Ladataan"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ladataan"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Ei laturissa"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Kytketty virtalähteeseen, lataaminen ei onnistu"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Täynnä"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Järjestelmänvalvoja hallinnoi tätä asetusta."</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Järjestelmänvalvojan käyttöön ottama"</string> diff --git a/packages/SettingsLib/res/values-fr-rCA/arrays.xml b/packages/SettingsLib/res/values-fr-rCA/arrays.xml index 29348c921595..8253614dd75a 100644 --- a/packages/SettingsLib/res/values-fr-rCA/arrays.xml +++ b/packages/SettingsLib/res/values-fr-rCA/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Utiliser sélect. du système (par défaut)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Activer les codecs optionnels"</item> - <item msgid="3304843301758635896">"Désactiver les codecs optionnels"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Utiliser sélect. du système (par défaut)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Activer les codecs optionnels"</item> - <item msgid="741805482892725657">"Désactiver les codecs optionnels"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Utiliser sélect. du système (par défaut)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index 201984c3415e..28e41fd7ffea 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Toujours autoriser la détection de réseaux Wi-Fi en itinérance"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Données cellulaires toujours actives"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Accélération matérielle pour le partage de connexion"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Désactiver le volume absolu"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Activer la signalisation intra-bande"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Version du profil Bluetooth AVRCP"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Ces paramètres sont en cours de développement. Ils peuvent endommager votre appareil et les applications qui s\'y trouvent, ou provoquer leur dysfonctionnement."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Vérifier les applis via USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Vérifiez que les applications installées par ADB/ADT ne présentent pas de comportement dangereux."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Désactive la fonctionnalité de volume absolu par Bluetooth en cas de problème de volume sur les appareils à distance, par exemple si le volume est trop élevé ou s\'il ne peut pas être contrôlé."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Autoriser la lecture des sonneries du téléphone sur les écouteurs Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – Temps restant : <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> : <xliff:g id="TIME">^2</xliff:g> jusqu\'à la charge complète"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Inconnu"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Charge en cours…"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"en cours de charge"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"N\'est pas en charge"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"L\'appareil est branché, mais il ne peut pas être chargé pour le moment"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Pleine"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Contrôlé par l\'administrateur"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Activé par l\'administrateur"</string> diff --git a/packages/SettingsLib/res/values-fr/arrays.xml b/packages/SettingsLib/res/values-fr/arrays.xml index 1c3605e525b3..aaa0381b0e01 100644 --- a/packages/SettingsLib/res/values-fr/arrays.xml +++ b/packages/SettingsLib/res/values-fr/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"Utiliser sélection système (par défaut)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="2091430979086738145">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"Activer les codecs facultatifs"</item> <item msgid="3304843301758635896">"Désactiver les codecs facultatifs"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"Utiliser sélection système (par défaut)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="298198075927343893">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"Activer les codecs facultatifs"</item> <item msgid="741805482892725657">"Désactiver les codecs facultatifs"</item> diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index 281e9575371a..d7c792028101 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Toujours autoriser la détection de réseaux Wi-Fi en itinérance"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Données mobiles toujours actives"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Accélération matérielle pour le partage de connexion"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Désactiver le volume absolu"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Activer la signalisation intra-bande"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Version Bluetooth AVRCP"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Ces paramètres sont en cours de développement. Ils peuvent endommager votre appareil et les applications qui s\'y trouvent, ou provoquer leur dysfonctionnement."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Vérifier les applis via USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Vérifiez que les applications installées par ADB/ADT ne présentent pas de comportement dangereux."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Désactive la fonctionnalité de volume absolu du Bluetooth en cas de problème de volume sur les appareils à distance, par exemple si le volume est trop élevé ou s\'il ne peut pas être contrôlé."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Autoriser la lecture des sonneries du téléphone sur les casques Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – Temps restant : <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> jusqu\'à la charge complète"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Inconnu"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Batterie en charge"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"chargement…"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Pas en charge"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Appareil branché, mais impossible de le charger pour le moment"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"pleine"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Contrôlé par l\'administrateur"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Activé par l\'administrateur"</string> diff --git a/packages/SettingsLib/res/values-gl/arrays.xml b/packages/SettingsLib/res/values-gl/arrays.xml index 1bfbbdfe0870..4b70cb3f8b71 100644 --- a/packages/SettingsLib/res/values-gl/arrays.xml +++ b/packages/SettingsLib/res/values-gl/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Usar selección sistema (predeterminado)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Activar códecs opcionais"</item> - <item msgid="3304843301758635896">"Desactivar códecs opcionais"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Usa selección sistema (predeterminado)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Activa os códecs opcionais"</item> - <item msgid="741805482892725657">"Desactiva os códecs opcionais"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Usar selección sistema (predeterminado)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml index 3311a5fe3017..cc6a96cad79d 100644 --- a/packages/SettingsLib/res/values-gl/strings.xml +++ b/packages/SettingsLib/res/values-gl/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir sempre buscas de itinerancia da wifi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Datos móbiles sempre activados"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración de hardware para conexión compartida"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desactivar volume absoluto"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Activar a función de soar na mesma banda"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versión AVRCP de Bluetooth"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Esta configuración só está destinada á programación. Esta pode provocar que o dispositivo e as aplicacións fallen ou se comporten incorrectamente."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificar aplicacións por USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Comprobar as aplicacións instaladas a través de ADB/ADT para detectar comportamento perigoso."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desactiva a función do volume absoluto do Bluetooth en caso de que se produzan problemas de volume cos dispositivos remotos, como volume demasiado alto ou falta de control."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Permite que os tons de chamada do teléfono se reproduzan nos auriculares Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> (tempo restante: <xliff:g id="TIME">^2</xliff:g>)"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> ata completar a carga"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> (<xliff:g id="TIME">^2</xliff:g>)"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Descoñecido"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"cargando"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Non se está cargando"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Conectouse, pero non se pode cargar neste momento"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Completa"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Opción controlada polo administrador"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Activado polo administrador"</string> diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml index 1fc1d7c5a1da..cdb0eb3fccbf 100644 --- a/packages/SettingsLib/res/values-gu/arrays.xml +++ b/packages/SettingsLib/res/values-gu/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"વૈકલ્પિક કોડેક સક્ષમ કરો"</item> - <item msgid="3304843301758635896">"વૈકલ્પિક કોડેક અક્ષમ કરો"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"વૈકલ્પિક કોડેક સક્ષમ કરો"</item> - <item msgid="741805482892725657">"વૈકલ્પિક કોડેક અક્ષમ કરો"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> @@ -238,7 +222,7 @@ </string-array> <string-array name="app_process_limit_entries"> <item msgid="3401625457385943795">"માનક સીમા"</item> - <item msgid="4071574792028999443">"કોઈ પૃષ્ઠભૂમિ પ્રક્રિયાઓ નથી"</item> + <item msgid="4071574792028999443">"કોઈ બૅકગ્રાઉન્ડ પ્રક્રિયાઓ નથી"</item> <item msgid="4810006996171705398">"સૌથી વધુ 1 પ્રક્રિયા"</item> <item msgid="8586370216857360863">"સૌથી વધુ 2 પ્રક્રિયા"</item> <item msgid="836593137872605381">"વધુમાં વધુ 3 પ્રક્રિયાઓ"</item> diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml index b931fd11ed74..1de92cd2efa2 100644 --- a/packages/SettingsLib/res/values-gu/strings.xml +++ b/packages/SettingsLib/res/values-gu/strings.xml @@ -92,11 +92,11 @@ <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ફાઇલ સ્થાનાંતર માટે ઉપયોગ કરો"</string> <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ઇનપુટ માટે ઉપયોગ કરો"</string> <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"જોડી"</string> - <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"જોડી કરો"</string> + <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"જોડાણ બનાવો"</string> <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"રદ કરો"</string> - <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"જોડી કરવી એ કનેક્ટ કરેલ હોય ત્યારે તમારા સંપર્કો અને કૉલ ઇતિહાસની અૅક્સેસ આપે છે."</string> + <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"એ કનેક્ટ કરેલ હોય ત્યારે જોડાણ બનાવવાથી તમારા સંપર્કો અને કૉલ ઇતિહાસનો અૅક્સેસ મળે છે."</string> <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> સાથે જોડી કરી શક્યાં નહીં."</string> - <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"એક ખોટા PIN અથવા પાસકીને કારણે <xliff:g id="DEVICE_NAME">%1$s</xliff:g> સાથે જોડી બનાવી શકાઈ નથી."</string> + <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"એક ખોટા પિન અથવા પાસકીને કારણે <xliff:g id="DEVICE_NAME">%1$s</xliff:g> સાથે જોડી બનાવી શકાઈ નથી."</string> <string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> સાથે સંચાર કરી શકાતો નથી."</string> <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> દ્વારા જોડી કરવાનું નકાર્યું."</string> <string name="accessibility_wifi_off" msgid="1166761729660614716">"Wifi બંધ."</string> @@ -111,10 +111,10 @@ <string name="data_usage_uninstalled_apps" msgid="614263770923231598">"દૂર કરેલી ઍપ્લિકેશનો"</string> <string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"દૂર કરેલી ઍપ્લિકેશનો અને વપરાશકર્તાઓ"</string> <string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ટિથરિંગ"</string> - <string name="tether_settings_title_wifi" msgid="3277144155960302049">"પોર્ટેબલ હોટસ્પોટ"</string> - <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth ટિથરિંગ"</string> + <string name="tether_settings_title_wifi" msgid="3277144155960302049">"પોર્ટેબલ હૉટસ્પૉટ"</string> + <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"બ્લૂટૂથ ટિથરિંગ"</string> <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"ટિથરિંગ"</string> - <string name="tether_settings_title_all" msgid="8356136101061143841">"ટિથરિંગ અને પોર્ટેબલ હોટસ્પોટ"</string> + <string name="tether_settings_title_all" msgid="8356136101061143841">"ટિથરિંગ અને પોર્ટેબલ હૉટસ્પૉટ"</string> <string name="managed_user_title" msgid="8109605045406748842">"તમામ કાર્ય અૅપ્લિકેશનો"</string> <string name="user_guest" msgid="8475274842845401871">"અતિથિ"</string> <string name="unknown" msgid="1592123443519355854">"અજાણ્યું"</string> @@ -175,10 +175,10 @@ <string name="clear_adb_keys" msgid="4038889221503122743">"USB ડીબગિંગ પ્રમાણીકરણોને રદબાતલ કરો"</string> <string name="bugreport_in_power" msgid="7923901846375587241">"બગ રિપોર્ટ શોર્ટકટ"</string> <string name="bugreport_in_power_summary" msgid="1778455732762984579">"બગ રિપોર્ટ લેવા માટે પાવર મેનૂમાં એક બટન બતાવો"</string> - <string name="keep_screen_on" msgid="1146389631208760344">"જાગૃત રહો"</string> + <string name="keep_screen_on" msgid="1146389631208760344">"સક્રિય રાખો"</string> <string name="keep_screen_on_summary" msgid="2173114350754293009">"ચાર્જિંગ દરમિયાન સ્ક્રીન ક્યારેય નિષ્ક્રિય થશે નહીં"</string> - <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Bluetooth HCI સ્નૂપ લૉગ સક્ષમ કરો"</string> - <string name="bt_hci_snoop_log_summary" msgid="730247028210113851">"ફાઇલમાં તમામ Bluetooth HCI પૅકેટ્સ કેપ્ચર કરો"</string> + <string name="bt_hci_snoop_log" msgid="3340699311158865670">"બ્લૂટૂથ HCI સ્નૂપ લૉગ સક્ષમ કરો"</string> + <string name="bt_hci_snoop_log_summary" msgid="730247028210113851">"ફાઇલમાં તમામ બ્લૂટૂથ HCI પૅકેટ્સ કેપ્ચર કરો"</string> <string name="oem_unlock_enable" msgid="6040763321967327691">"OEM અનલૉકિંગ"</string> <string name="oem_unlock_enable_summary" msgid="4720281828891618376">"બુટલોડર અનલૉક કરવાની મંજૂરી આપો"</string> <string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"OEM ને અનલૉક કરવાની મંજૂરી આપીએ?"</string> @@ -187,31 +187,33 @@ <string name="mock_location_app_not_set" msgid="809543285495344223">"કોઈ મોક સ્થાન ઍપ્લિકેશન સેટ કરાયેલ નથી"</string> <string name="mock_location_app_set" msgid="8966420655295102685">"મોક સ્થાન ઍપ્લિકેશન: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="debug_networking_category" msgid="7044075693643009662">"નેટવર્કિંગ"</string> - <string name="wifi_display_certification" msgid="8611569543791307533">"બિનતારી પ્રદર્શન પ્રમાણન"</string> - <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi-Fi વર્બોઝ લૉગિંગ સક્ષમ કરો"</string> + <string name="wifi_display_certification" msgid="8611569543791307533">"વાયરલેસ ડિસ્પ્લે પ્રમાણન"</string> + <string name="wifi_verbose_logging" msgid="4203729756047242344">"વાઇ-ફાઇ વર્બોઝ લૉગિંગ સક્ષમ કરો"</string> <string name="wifi_aggressive_handover" msgid="5309131983693661320">"સશક્ત Wi‑Fiથી મોબાઇલ પર હૅન્ડઓવર"</string> - <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"હંમેશા Wi‑Fi રોમ સ્કૅન્સને મંજૂરી આપો"</string> + <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"હંમેશા વાઇ-ફાઇ રોમ સ્કૅન્સને મંજૂરી આપો"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"મોબાઇલ ડેટા હંમેશાં સક્રિય"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"ટિથરિંગ માટે હાર્ડવેર ગતિવૃદ્ધિ"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ચોક્કસ વૉલ્યૂમને અક્ષમ કરો"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"બેંડમાં રિંગ કરવાનું સક્ષમ કરો"</string> - <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP સંસ્કરણ"</string> - <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth AVRCP સંસ્કરણ પસંદ કરો"</string> - <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth ઑડિઓ કોડેક"</string> - <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Bluetooth ઑડિઓ LDAC કોડેક પસંદ કરો"</string> - <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bluetooth ઑડિઓ નમૂના દર"</string> - <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Bluetooth ઑડિઓ LDAC કોડેક પસંદ કરો:\nનમૂના દર"</string> - <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"નમૂના દીઠ Bluetooth ઑડિઓ બિટ"</string> - <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Bluetooth ઑડિઓ કોડેક પસંદ કરો:\nનમૂના દીઠ બિટ"</string> - <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Bluetooth ઑડિઓ ચેનલ મોડ"</string> - <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Bluetooth ઑડિઓ કોડેક પસંદ કરો:\nચૅનલ મોડ"</string> - <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth ઑડિઓ LDAC કોડેક: પ્લેબૅક ગુણવત્તા"</string> - <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Bluetooth ઑડિઓ LDAC કોડેક પસંદ કરો:\nપ્લેબૅક ગુણવત્તા"</string> + <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"બ્લૂટૂથ AVRCP સંસ્કરણ"</string> + <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"બ્લૂટૂથ AVRCP સંસ્કરણ પસંદ કરો"</string> + <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"બ્લૂટૂથ ઑડિઓ કોડેક"</string> + <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"બ્લૂટૂથ ઑડિઓ LDAC કોડેક પસંદ કરો"</string> + <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"બ્લૂટૂથ ઑડિઓ નમૂના દર"</string> + <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"બ્લૂટૂથ ઑડિઓ LDAC કોડેક પસંદ કરો:\nનમૂના દર"</string> + <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"નમૂના દીઠ બ્લૂટૂથ ઑડિઓ બિટ"</string> + <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"બ્લૂટૂથ ઑડિઓ કોડેક પસંદ કરો:\nનમૂના દીઠ બિટ"</string> + <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"બ્લૂટૂથ ઑડિઓ ચેનલ મોડ"</string> + <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"બ્લૂટૂથ ઑડિઓ કોડેક પસંદ કરો:\nચૅનલ મોડ"</string> + <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"બ્લૂટૂથ ઑડિઓ LDAC કોડેક: પ્લેબૅક ગુણવત્તા"</string> + <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"બ્લૂટૂથ ઑડિઓ LDAC કોડેક પસંદ કરો:\nપ્લેબૅક ગુણવત્તા"</string> <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"સ્ટ્રીમિંગ: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"વાયરલેસ ડિસ્પ્લે પ્રમાણપત્ર માટેના વિકલ્પો બતાવો"</string> - <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi લોગિંગ સ્તર વધારો, Wi‑Fi પીકરમાં SSID RSSI દીઠ બતાવો"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"જ્યારે સક્ષમ કરેલ હોય, ત્યારે Wi‑Fi સિગ્નલ નબળું હોવા પર, Wi-Fi વધુ ઝડપથી ડેટા કનેક્શનને મોબાઇલ પર મોકલશે"</string> - <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ઇન્ટરફેસ પર હાજર ડેટા ટ્રાફિકના પ્રમાણનાં આધારે Wi‑Fi રોમ સ્કૅન્સને મંજૂરી આપો/નામંજૂર કરો"</string> + <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"વાઇ-ફાઇ લોગિંગ સ્તર વધારો, વાઇ-ફાઇ પીકરમાં SSID RSSI દીઠ બતાવો"</string> + <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"જ્યારે સક્ષમ કરેલ હોય, ત્યારે વાઇ-ફાઇ સિગ્નલ નબળું હોવા પર, વાઇ-ફાઇ વધુ ઝડપથી ડેટા કનેક્શનને મોબાઇલ પર મોકલશે"</string> + <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ઇન્ટરફેસ પર હાજર ડેટા ટ્રાફિકના પ્રમાણનાં આધારે વાઇ-ફાઇ રોમ સ્કૅન્સને મંજૂરી આપો/નામંજૂર કરો"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"લોગર બફર કદ"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"લૉગ દીઠ લૉગર કદ બફર પસંદ કરો"</string> <string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"લૉગર નિરંતર સ્ટોરેજ સાફ કરીએ?"</string> @@ -223,7 +225,7 @@ <string name="allow_mock_location" msgid="2787962564578664888">"મોક સ્થાનોની મંજૂરી આપો"</string> <string name="allow_mock_location_summary" msgid="317615105156345626">"મોક સ્થાનોની મંજૂરી આપો"</string> <string name="debug_view_attributes" msgid="6485448367803310384">"લક્ષણ નિરીક્ષણ જોવાનું સક્ષમ કરો"</string> - <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Wi‑Fi સક્રિય હોય ત્યારે પણ, હંમેશા મોબાઇલ ડેટાને સક્રિય રાખો (ઝડપી નેટવર્ક સ્વિચિંગ માટે)."</string> + <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"વાઇ-ફાઇ સક્રિય હોય ત્યારે પણ, હંમેશા મોબાઇલ ડેટાને સક્રિય રાખો (ઝડપી નેટવર્ક સ્વિચિંગ માટે)."</string> <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"જો ટિથરિંગ માટે હાર્ડવેર ગતિવૃદ્ધિ ઉપલબ્ધ હોય તો તેનો ઉપયોગ કરો"</string> <string name="adb_warning_title" msgid="6234463310896563253">"USB ડિબગિંગને મંજૂરી આપીએ?"</string> <string name="adb_warning_message" msgid="7316799925425402244">"USB ડિબગીંગ ફક્ત વિકાસ હેતુઓ માટે જ બનાવાયેલ છે. તેનો ઉપયોગ તમારા કમ્પ્યુટર અને તમારા ઉપકરણ વચ્ચે ડેટાને કૉપિ કરવા, સૂચના વગર તમારા ઉપકરણ પર ઍપ્લિકેશનો ઇન્સ્ટોલ કરવા અને લૉગ ડેટા વાંચવા માટે કરો."</string> @@ -232,8 +234,10 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"આ સેટિંગ્સ ફક્ત વિકાસનાં ઉપયોગ માટે જ હેતુબદ્ધ છે. તે તમારા ઉપકરણ અને તેના પરની એપ્લિકેશન્સનાં ભંગ થવા અથવા ખરાબ વર્તનનું કારણ બની શકે છે."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB પર ઍપ્લિકેશનો ચકાસો"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"હાનિકારક વર્તણૂંક માટે ADB/ADT મારફતે ઇન્સ્ટોલ કરવામાં આવેલી ઍપ્લિકેશનો તપાસો."</string> - <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"રિમોટ ઉપકરણોમાં વધુ પડતું ઊંચું વૉલ્યૂમ અથવા નિયંત્રણની કમી જેવી વૉલ્યૂમની સમસ્યાઓની સ્થિતિમાં Bluetooth ચોક્કસ વૉલ્યૂમ સુવિધાને અક્ષમ કરે છે."</string> - <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ફોનનો રિંગટોન Bluetooth હેડસેટ પર વાગવાની મંજૂરી આપો"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> + <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"રિમોટ ઉપકરણોમાં વધુ પડતું ઊંચું વૉલ્યૂમ અથવા નિયંત્રણની કમી જેવી વૉલ્યૂમની સમસ્યાઓની સ્થિતિમાં બ્લૂટૂથ ચોક્કસ વૉલ્યૂમ સુવિધાને અક્ષમ કરે છે."</string> + <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ફોનની રિંગટોન બ્લૂટૂથ હૅડસેટ પર વાગવાની મંજૂરી આપો"</string> <string name="enable_terminal_title" msgid="95572094356054120">"સ્થાનિક ટર્મિનલ"</string> <string name="enable_terminal_summary" msgid="67667852659359206">"સ્થાનિક શેલ અૅક્સેસની ઑફર કરતી ટર્મિનલ એપ્લિકેશનને સક્ષમ કરો"</string> <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP તપાસણી"</string> @@ -290,9 +294,9 @@ <string name="debug_applications_category" msgid="4206913653849771549">"ઍપ્લિકેશનો"</string> <string name="immediately_destroy_activities" msgid="1579659389568133959">"પ્રવૃત્તિઓ રાખશો નહીં"</string> <string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"જેવો વપરાશકર્તા તેને છોડે, તરત જ દરેક પ્રવૃત્તિ નષ્ટ કરો"</string> - <string name="app_process_limit_title" msgid="4280600650253107163">"પૃષ્ઠભૂમિ પ્રક્રિયા સીમા"</string> + <string name="app_process_limit_title" msgid="4280600650253107163">"બૅકગ્રાઉન્ડ પ્રક્રિયા સીમા"</string> <string name="show_all_anrs" msgid="28462979638729082">"બધા ANR બતાવો"</string> - <string name="show_all_anrs_summary" msgid="641908614413544127">"પૃષ્ઠભૂમિ ઍપ્લિકેશનો માટે ઍપ્લિકેશન પ્રતિસાદ આપતી નથી સંવાદ બતાવો"</string> + <string name="show_all_anrs_summary" msgid="641908614413544127">"બૅકગ્રાઉન્ડ ઍપ્લિકેશનો માટે ઍપ્લિકેશન પ્રતિસાદ આપતી નથી સંવાદ બતાવો"</string> <string name="show_notification_channel_warnings" msgid="1399948193466922683">"સૂચના ચૅનલની ચેતવણી બતાવો"</string> <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"ઍપ્લિકેશન માન્ય ચૅનલ વિના સૂચના પોસ્ટ કરે તો સ્ક્રીન પર ચેતવણી દેખાય છે"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"બાહ્ય પર એપ્લિકેશનોને મંજૂરી આપવાની ફરજ પાડો"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> બાકી"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - સંપૂર્ણપણે ચાર્જ થવા માટે <xliff:g id="TIME">^2</xliff:g>"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"અજાણ્યું"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"ચાર્જ થઈ રહ્યું છે"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ચાર્જ થઈ રહ્યું છે"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"ચાર્જ થઈ રહ્યું નથી"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"પ્લગ ઇન કરેલ, હમણાં ચાર્જ કરી શકતા નથી"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"પૂર્ણ"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"વ્યવસ્થાપક દ્વારા નિયંત્રિત"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"વ્યવસ્થાપકે સક્ષમ કરેલ"</string> diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml index e304e908564f..a90e37834693 100644 --- a/packages/SettingsLib/res/values-hi/arrays.xml +++ b/packages/SettingsLib/res/values-hi/arrays.xml @@ -25,7 +25,7 @@ <item msgid="8934131797783724664">"स्कैन कर रहा है…"</item> <item msgid="8513729475867537913">"कनेक्ट हो रहा है..."</item> <item msgid="515055375277271756">"प्रमाणीकरण कर रहा है…"</item> - <item msgid="1943354004029184381">"IP पता प्राप्त कर रहा है…"</item> + <item msgid="1943354004029184381">"आईपी पता ले रहा है…"</item> <item msgid="4221763391123233270">"कनेक्ट किया गया"</item> <item msgid="624838831631122137">"निलंबित"</item> <item msgid="7979680559596111948">"डिस्कनेक्ट हो रहा है..."</item> @@ -39,7 +39,7 @@ <item msgid="8878186979715711006">"स्कैन कर रहा है…"</item> <item msgid="355508996603873860">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> से कनेक्ट कर रहा है…"</item> <item msgid="554971459996405634">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> के साथ प्रमाणीकरण कर रहा है…"</item> - <item msgid="7928343808033020343">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> से IP पता प्राप्त कर रहा है…"</item> + <item msgid="7928343808033020343">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> से आईपी पता ले रहा है..."</item> <item msgid="8937994881315223448">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> से कनेक्ट किया गया"</item> <item msgid="1330262655415760617">"निलंबित"</item> <item msgid="7698638434317271902">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> से डिस्कनेक्ट कर रहा है…"</item> @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"वैकल्पिक कोडेक सक्षम करें"</item> - <item msgid="3304843301758635896">"वैकल्पिक कोडेक अक्षम करें"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"वैकल्पिक कोडेक सक्षम करें"</item> - <item msgid="741805482892725657">"वैकल्पिक कोडेक अक्षम करें"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> @@ -128,13 +112,13 @@ <item msgid="7158319962230727476">"ऑडियो की गुणवत्ता के लिए अनुकूलित किया गया (990kbps/909kbps)"</item> <item msgid="2921767058740704969">"संतुलित ऑडियो और कनेक्शन गुणवत्ता (660kbps/606kbps)"</item> <item msgid="8860982705384396512">"कनेक्शन की गुणवत्ता के लिए अनुकूलित किया गया (330kbps/303kbps)"</item> - <item msgid="4414060457677684127">"सबसे अच्छी कोशिश (अनुकूल बिट दर)"</item> + <item msgid="4414060457677684127">"सबसे अच्छी क्वालिटी में चलाएं (अनुकूल बिट रेट)"</item> </string-array> <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries"> <item msgid="6398189564246596868">"ऑडियो की गुणवत्ता के लिए अनुकूलित किया गया"</item> <item msgid="4327143584633311908">"संतुलित ऑडियो और कनेक्शन गुणवत्ता"</item> <item msgid="4681409244565426925">"कनेक्शन की गुणवत्ता के लिए अनुकूलित किया गया"</item> - <item msgid="364670732877872677">"सबसे अच्छी कोशिश (अनुकूल बिट दर)"</item> + <item msgid="364670732877872677">"सबसे अच्छी क्वालिटी में चलाएं (अनुकूल बिट रेट)"</item> </string-array> <string-array name="select_logd_size_titles"> <item msgid="8665206199209698501">"बंद"</item> @@ -215,7 +199,7 @@ <item msgid="3191973083884253830">"कोई नहीं"</item> <item msgid="9089630089455370183">"Logcat"</item> <item msgid="5397807424362304288">"Systrace (ग्राफ़िक)"</item> - <item msgid="1340692776955662664">"glGetError पर स्टैक कॉल करें"</item> + <item msgid="1340692776955662664">"glGetError पर कॉल स्टैक"</item> </string-array> <string-array name="show_non_rect_clip_entries"> <item msgid="993742912147090253">"बंद"</item> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index b383b2ebdc33..252be3c13576 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -92,13 +92,13 @@ <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"फ़ाइल स्थानांतरण के लिए उपयोग करें"</string> <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"इनपुट के लिए उपयोग करें"</string> <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"युग्म बनाएं"</string> - <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"युग्मित करें"</string> - <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"अभी नहीं"</string> + <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"दूसरे डिवाइस से जोड़ें"</string> + <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"रद्द करें"</string> <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"कनेक्ट रहने पर, पेयरिंग आपको अपने संपर्कों और कॉल इतिहास की एक्सेस प्रदान करता है."</string> <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> के साथ युग्मित नहीं हो सका."</string> <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"गलत पिन या पासकी के कारण <xliff:g id="DEVICE_NAME">%1$s</xliff:g> के साथ युग्मित नहीं हो सका."</string> <string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> से संचार नहीं कर सकता."</string> - <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> द्वारा युग्मन अस्वीकृत किया गया."</string> + <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ने जोड़ने का अनुरोध नहीं माना."</string> <string name="accessibility_wifi_off" msgid="1166761729660614716">"वाई-फ़ाई बंद है."</string> <string name="accessibility_no_wifi" msgid="8834610636137374508">"वाई-फ़ाई डिसकनेक्ट है."</string> <string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"वाई-फ़ाई का एक बार है."</string> @@ -132,7 +132,7 @@ <string name="tts_lang_not_selected" msgid="7395787019276734765">"भाषा नहीं चुनी गई है"</string> <string name="tts_default_lang_summary" msgid="5219362163902707785">"बोले गए लेख के लिए भाषा-विशिष्ट ध्वनि सेट करता है"</string> <string name="tts_play_example_title" msgid="7094780383253097230">"एक उदाहरण सुनें"</string> - <string name="tts_play_example_summary" msgid="8029071615047894486">"बोली संश्लेषण का एक संक्षिप्त प्रदर्शन चलाएं"</string> + <string name="tts_play_example_summary" msgid="8029071615047894486">"लिखे हुए को बोली में बदलने की सुविधा की एक छोटी सी झलक चलाएं"</string> <string name="tts_install_data_title" msgid="4264378440508149986">"ध्वनि डेटा इंस्टॉल करें"</string> <string name="tts_install_data_summary" msgid="5742135732511822589">"बोली-संश्लेषण के लिए आवश्यक ध्वनि डेटा इंस्टॉल करें"</string> <string name="tts_engine_security_warning" msgid="8786238102020223650">"यह बोली संश्लेषण इंजन पासवर्ड और क्रेडिट कार्ड नंबर जैसे निजी डेटा समेत आपके द्वारा बोले जाने वाले सभी लेख को एकत्र कर सकता है. यह <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> इंजन से आता है. इस बोली संश्लेषण इंजन के उपयोग को सक्षम करें?"</string> @@ -163,20 +163,20 @@ <string name="choose_profile" msgid="6921016979430278661">"प्रोफ़ाइल चुनें"</string> <string name="category_personal" msgid="1299663247844969448">"व्यक्तिगत"</string> <string name="category_work" msgid="8699184680584175622">"कार्यालय"</string> - <string name="development_settings_title" msgid="215179176067683667">"डेवलपर विकल्प"</string> - <string name="development_settings_enable" msgid="542530994778109538">"डेवलपर विकल्प सक्षम करें"</string> + <string name="development_settings_title" msgid="215179176067683667">"डेवलपर के लिए सेटिंग और टूल"</string> + <string name="development_settings_enable" msgid="542530994778109538">"डेवलपर के लिए सेटिंग और टूल सक्षम करें"</string> <string name="development_settings_summary" msgid="1815795401632854041">"ऐप्स विकास के लिए विकल्प सेट करें"</string> - <string name="development_settings_not_available" msgid="4308569041701535607">"इस उपयोगकर्ता के लिए डेवलपर विकल्प उपलब्ध नहीं हैं"</string> + <string name="development_settings_not_available" msgid="4308569041701535607">"यह उपयोगकर्ता, डेवलपर के लिए सेटिंग और टूल का इस्तेमाल नहीं कर सकता"</string> <string name="vpn_settings_not_available" msgid="956841430176985598">"VPN सेटिंग इस उपयोगकर्ता के लिए उपलब्ध नहीं हैं"</string> <string name="tethering_settings_not_available" msgid="6765770438438291012">"टेदरिंग सेटिंग इस उपयोगकर्ता के लिए उपलब्ध नहीं हैं"</string> - <string name="apn_settings_not_available" msgid="7873729032165324000">"एक्सेस पॉइंट नाम सेटिंग इस उपयोगकर्ता के लिए उपलब्ध नहीं हैं"</string> + <string name="apn_settings_not_available" msgid="7873729032165324000">"एक्सेस पॉइंट नाम सेटिंग इस उपयोगकर्ता के लिए मौजूद नहीं हैं"</string> <string name="enable_adb" msgid="7982306934419797485">"USB डीबग करना"</string> <string name="enable_adb_summary" msgid="4881186971746056635">"डीबग मोड जब USB कनेक्ट किया गया हो"</string> - <string name="clear_adb_keys" msgid="4038889221503122743">"USB डीबगिंग प्राधिकरणों को निरस्त करें"</string> - <string name="bugreport_in_power" msgid="7923901846375587241">"बग रिपोर्ट शॉर्टकट"</string> - <string name="bugreport_in_power_summary" msgid="1778455732762984579">"बग रिपोर्ट लेने के लिए पावर मेनू में कोई बटन दिखाएं"</string> - <string name="keep_screen_on" msgid="1146389631208760344">"सचेत रहें"</string> - <string name="keep_screen_on_summary" msgid="2173114350754293009">"चार्ज होने के दौरान स्क्रीन कभी निष्क्रिय नहीं होगी"</string> + <string name="clear_adb_keys" msgid="4038889221503122743">"USB डीबग करने की मंज़ूरी रद्द करें"</string> + <string name="bugreport_in_power" msgid="7923901846375587241">"गड़बड़ी की रिपोर्ट का शॉर्टकट"</string> + <string name="bugreport_in_power_summary" msgid="1778455732762984579">"गड़बड़ी की रिपोर्ट लेने के लिए पावर मेन्यू में कोई बटन दिखाएं"</string> + <string name="keep_screen_on" msgid="1146389631208760344">"स्क्रीन को चालू रखें"</string> + <string name="keep_screen_on_summary" msgid="2173114350754293009">"चार्ज करते समय स्क्रीन कभी भी कम बैटरी मोड में नहीं जाएगी"</string> <string name="bt_hci_snoop_log" msgid="3340699311158865670">"ब्लूटूथ HCI स्नूप लॉग सक्षम करें"</string> <string name="bt_hci_snoop_log_summary" msgid="730247028210113851">"फ़ाइल के सभी ब्लूटूथ HCI पैकेट कैप्चर करें"</string> <string name="oem_unlock_enable" msgid="6040763321967327691">"OEM अनलॉक करना"</string> @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"हमेशा वाई-फ़ाई रोम स्कैन करने दें"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"मोबाइल डेटा हमेशा सक्रिय"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"हार्डवेयर त्वरण को टेदर करना"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"पूर्ण वॉल्यूम अक्षम करें"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"इन-बैंड रिंग करना सक्षम करें"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ब्लूटूथ AVRCP वर्शन"</string> @@ -226,14 +228,16 @@ <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"वाई-फ़ाई के सक्रिय रहने पर भी, हमेशा मोबाइल डेटा सक्रिय रखें (तेज़ी से नेटवर्क स्विच करने के लिए)."</string> <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"हार्डवेयर त्वरण को टेदर करना उपलब्ध होने पर उसका उपयोग करें"</string> <string name="adb_warning_title" msgid="6234463310896563253">"USB डीबग करने की अनुमति दें?"</string> - <string name="adb_warning_message" msgid="7316799925425402244">"USB डीबग करने का उद्देश्य केवल विकास है. इसका इस्तेमाल आपके कंप्यूटर और आपके डिवाइस के बीच डेटा को कॉपी करने, बिना नोटिफ़िकेशन के आपके डिवाइस पर ऐप इंस्टॉल करने और लॉग डेटा पढ़ने के लिए करें."</string> - <string name="adb_keys_warning_message" msgid="5659849457135841625">"आपके द्वारा पूर्व में प्राधिकृत सभी कंप्यूटर से USB डीबगिंग की पहुंच निरस्त करें?"</string> + <string name="adb_warning_message" msgid="7316799925425402244">"USB डीबग करने का मकसद केवल डेवेलप करना है. इसका इस्तेमाल आपके कंप्यूटर और आपके डिवाइस के बीच डेटा को कॉपी करने, बिना सूचना के आपके डिवाइस पर ऐप इंस्टॉल करने और लॉग डेटा पढ़ने के लिए करें."</string> + <string name="adb_keys_warning_message" msgid="5659849457135841625">"उन सभी कंप्यूटरों से USB डीबग करने की पहुंचर रद्द करें, जिन्हें आपने पहले इसकी मंज़ूरी दी थी?"</string> <string name="dev_settings_warning_title" msgid="7244607768088540165">"विकास सेटिंग की अनुमति दें?"</string> <string name="dev_settings_warning_message" msgid="2298337781139097964">"ये सेटिंग केवल विकास संबंधी उपयोग के प्रयोजन से हैं. वे आपके डिवाइस और उस पर स्थित ऐप्स को खराब कर सकती हैं या उनके दुर्व्यवहार का कारण हो सकती हैं."</string> - <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB पर ऐप्स सत्यापित करें"</string> + <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB पर ऐप की पुष्टि करें"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"नुकसानदेह व्यवहार के लिए ADB/ADT के द्वारा इंस्टॉल किए गए ऐप्स जांचें."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"दूरस्थ डिवाइस के साथ वॉल्यूम की समस्याओं जैसे अस्वीकार्य तेज़ वॉल्यूम या नियंत्रण की कमी की स्थिति में ब्लूटूथ पूर्ण वॉल्यूम सुविधा को अक्षम करता है."</string> - <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"फ़ोन की रिंगटोन को ब्लूटूथ हैडसेट पर बजने दें"</string> + <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"फ़ोन की रिंगटोन को ब्लूटूथ हेडसेट पर बजने दें"</string> <string name="enable_terminal_title" msgid="95572094356054120">"स्थानीय टर्मिनल"</string> <string name="enable_terminal_summary" msgid="67667852659359206">"स्थानीय शेल एक्सेस ऑफ़र करने वाला टर्मिनल ऐप्स सक्षम करें"</string> <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP जांच"</string> @@ -247,7 +251,7 @@ <string name="wait_for_debugger" msgid="1202370874528893091">"डीबगर की प्रतीक्षा करें"</string> <string name="wait_for_debugger_summary" msgid="1766918303462746804">"डीबग किया गया ऐप्स निष्पादन के पहले अनुलग्न करने के लिए डीबगर की प्रतीक्षा करता है"</string> <string name="telephony_monitor_switch" msgid="1764958220062121194">"टेलीफ़ोनी मॉनिटर"</string> - <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"टेलीफ़ोनी मॉनिटर को जब टेलीफ़ोनी/मॉडेम कार्यक्षमता में कोई समस्या मिलती है तो वह लॉग इकट्ठा करता है और उपयोगकर्ता को एक बग दर्ज करने के लिए नोटिफ़िकेशन देता है"</string> + <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"टेलीफ़ोनी मॉनिटर को जब टेलीफ़ोनी/मॉडेम के फंक्शन में कोई समस्या मिलती है, तो वह लॉग इकट्ठा करता है और उपयोगकर्ता को एक गड़बड़ी दर्ज करने के लिए सूचना देता है"</string> <string name="debug_input_category" msgid="1811069939601180246">"हिंदी में लिखें"</string> <string name="debug_drawing_category" msgid="6755716469267367852">"ड्रॉइंग"</string> <string name="debug_hw_drawing_category" msgid="6220174216912308658">"हार्डवेयर त्वरित रेंडरिंग"</string> @@ -256,18 +260,18 @@ <string name="strict_mode" msgid="1938795874357830695">"सख्त मोड सक्षम किया गया"</string> <string name="strict_mode_summary" msgid="142834318897332338">"जब ऐप्स मुख्य थ्रेड पर लंबी कार्यवाही करते हैं तो स्क्रीन फ़्लैश करें"</string> <string name="pointer_location" msgid="6084434787496938001">"सूचक स्थान"</string> - <string name="pointer_location_summary" msgid="840819275172753713">"वर्तमान स्पर्श डेटा दिखाने वाला स्क्रीन ओवरले"</string> + <string name="pointer_location_summary" msgid="840819275172753713">"मौजूदा स्पर्श डेटा दिखाने वाला स्क्रीन ओवरले"</string> <string name="show_touches" msgid="2642976305235070316">"टैप दिखाएं"</string> <string name="show_touches_summary" msgid="6101183132903926324">"टैप के लिए विज़ुअल फ़ीडबैक दिखाएं"</string> - <string name="show_screen_updates" msgid="5470814345876056420">"सतह के नई जानकारी दिखाएं"</string> - <string name="show_screen_updates_summary" msgid="2569622766672785529">"विंडो सतहें के नई जानकारी मिलने पर उन सभी को फ़्लैश करें"</string> - <string name="show_hw_screen_updates" msgid="5036904558145941590">"GPU दृश्य की नई जानकारी दिखाएं"</string> + <string name="show_screen_updates" msgid="5470814345876056420">"सर्फ़ेस अपडेट दिखाएं"</string> + <string name="show_screen_updates_summary" msgid="2569622766672785529">"अपडेट होने पर पूरे विंडो सर्फ़ेस को फ़्लैश करें"</string> + <string name="show_hw_screen_updates" msgid="5036904558145941590">"GPU व्यू अपडेट दिखाएं"</string> <string name="show_hw_screen_updates_summary" msgid="1115593565980196197">"GPU के साथ आरेखित करने पर विंडो में दृश्यों को फ़्लैश करें"</string> - <string name="show_hw_layers_updates" msgid="5645728765605699821">"हार्डवेयर लेयर की नई जानकारी"</string> - <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"हार्डवेयर लेयर की नई जानकारी मिलने पर हरा फ़्लैश होता है"</string> + <string name="show_hw_layers_updates" msgid="5645728765605699821">"हार्डवेयर लेयर अपडेट दिखाएं"</string> + <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"हार्डवेयर लेयर अपडेट होने पर उनमें हरी रोशनी डालें"</string> <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ओवरड्रॉ डीबग करें"</string> <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU दाता सेट करें"</string> - <string name="disable_overlays" msgid="2074488440505934665">"HW ओवरले अक्षम करें"</string> + <string name="disable_overlays" msgid="2074488440505934665">"HW ओवरले बंद करें"</string> <string name="disable_overlays_summary" msgid="3578941133710758592">"स्क्रीन संयोजन के लिए हमेशा GPU का उपयोग करें"</string> <string name="simulate_color_space" msgid="6745847141353345872">"रंग स्पेस सिम्युलेट करें"</string> <string name="enable_opengl_traces_title" msgid="6790444011053219871">"OpenGL चिह्न सक्षम करें"</string> @@ -289,16 +293,16 @@ <string name="overlay_display_devices_title" msgid="5364176287998398539">"द्वितीयक डिस्प्ले अनुरूपित करें"</string> <string name="debug_applications_category" msgid="4206913653849771549">"ऐप्स"</string> <string name="immediately_destroy_activities" msgid="1579659389568133959">"गतिविधियों को न रखें"</string> - <string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"उपयोगकर्ता के छोड़ते ही प्रत्येक गतिविधि समाप्त करें"</string> + <string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"उपयोगकर्ता के छोड़ते ही हर गतिविधि को खत्म करें"</string> <string name="app_process_limit_title" msgid="4280600650253107163">"पृष्ठभूमि प्रक्रिया सीमा"</string> <string name="show_all_anrs" msgid="28462979638729082">"सभी ANR दिखाएं"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"पृष्ठभूमि ऐप्स के लिए ऐप्स प्रतिसाद नहीं दे रहा डॉयलॉग दिखाएं"</string> - <string name="show_notification_channel_warnings" msgid="1399948193466922683">"नोटिफ़िकेशन चैनल चेतावनी दिखाएं"</string> - <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"ऐप्लिकेशन मान्य चैनल के बिना नोटिफ़िकेशन पोस्ट करे तो स्क्रीन पर चेतावनी दिखाएं"</string> + <string name="show_notification_channel_warnings" msgid="1399948193466922683">"सूचना चैनल चेतावनी दिखाएं"</string> + <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"ऐप सही चैनल के बिना सूचना पोस्ट करे तो स्क्रीन पर चेतावनी दिखाएं"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"ऐप्स को बाहरी मेमोरी पर बाध्य करें"</string> - <string name="force_allow_on_external_summary" msgid="3640752408258034689">"इससे कोई भी ऐप्लिकेशन, मेनिफेस्ट मानों को अनदेखा करके, बाहरी मेमोरी पर लिखने योग्य बन जाता है"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"इससे कोई भी ऐप बाहरी मेमोरी में रखने लायक बन जाता है चाहे उसकी मेनिफ़ेस्ट वैल्यू कुछ भी हो"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"आकार बदले जाने के लिए गतिविधियों को बाध्य करें"</string> - <string name="force_resizable_activities_summary" msgid="6667493494706124459">"सभी गतिविधियों को एकाधिक विंडो के लिए आकार बदलने योग्य बनाएं, चाहे मेनिफेस्ट मान कुछ भी हों."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"सभी गतिविधियों को मल्टी-विंडो (एक से ज़्यादा ऐप, एक साथ) के लिए आकार बदलने लायक बनाएं, चाहे उनकी मेनिफ़ेस्ट वैल्यू कुछ भी हो."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"फ़्रीफ़ॉर्म विंडो सक्षम करें"</string> <string name="enable_freeform_support_summary" msgid="8247310463288834487">"प्रयोगात्मक फ़्रीफ़ॉर्म विंडो का समर्थन सक्षम करें."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"डेस्कटॉप बैकअप पासवर्ड"</string> @@ -317,19 +321,19 @@ <item msgid="8280754435979370728">"आंखों को दिखाई देने वाले प्राकृतिक रंग"</item> <item msgid="5363960654009010371">"डिजिटल सामग्री के लिए ऑप्टिमाइज़़ किए गए रंग"</item> </string-array> - <string name="inactive_apps_title" msgid="1317817863508274533">"निष्क्रिय ऐप्स"</string> - <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"निष्क्रिय. टॉगल करने के लिए टैप करें."</string> + <string name="inactive_apps_title" msgid="1317817863508274533">"बंद एेप"</string> + <string name="inactive_app_inactive_summary" msgid="5091363706699855725">"बंद है. टॉगल करने के लिए टैप करें."</string> <string name="inactive_app_active_summary" msgid="4174921824958516106">"सक्रिय. टॉगल करने पर टैप करें."</string> <string name="runningservices_settings_title" msgid="8097287939865165213">"चल रही सेवाएं"</string> <string name="runningservices_settings_summary" msgid="854608995821032748">"वर्तमान में चल रही सेवाओं को देखें और नियंत्रित करें"</string> - <string name="select_webview_provider_title" msgid="4628592979751918907">"WebView कार्यान्वयन"</string> - <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView कार्यान्वयन सेट करें"</string> + <string name="select_webview_provider_title" msgid="4628592979751918907">"वेबव्यू लागू करें"</string> + <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"वेबव्यू सेट करें"</string> <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"यह चयन अब मान्य नहीं है. पुनः प्रयास करें."</string> - <string name="convert_to_file_encryption" msgid="3060156730651061223">"फ़ाइल एन्क्रिप्शन में रूपांतरित करें"</string> + <string name="convert_to_file_encryption" msgid="3060156730651061223">"फ़ाइल आधारित सुरक्षित करने के तरीके में बदलें"</string> <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"रूपांतरित करें..."</string> <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"फ़ाइल पहले से एन्क्रिप्ट की हुई है"</string> - <string name="title_convert_fbe" msgid="1263622876196444453">"फ़ाइल आधारित एन्क्रिप्शन में रूपांतरित कर रहा है"</string> - <string name="convert_to_fbe_warning" msgid="6139067817148865527">"डेटा विभाजन को फ़ाइल आधारित एन्क्रिप्शन में रूपांतरित करें.\n !!चेतावनी!! इससे आपका सभी डेटा मिट जाएगा.\n यह सुविधा अल्फ़ा स्थिति में है और ठीक से कार्य नहीं कर सकती.\n जारी रखने के लिए \'वाइप करें और रूपांतरित करें…\' दबाएं."</string> + <string name="title_convert_fbe" msgid="1263622876196444453">"फ़ाइल के आधार पर सुरक्षित करने के तरीके में बदल कर रहा है"</string> + <string name="convert_to_fbe_warning" msgid="6139067817148865527">"डेटा विभाजन (डेटा को अलग-अलग हिस्सों में बांटना) को फ़ाइल आधारित सुरक्षित करने के तरीके में बदलें.\n !!चेतावनी!! इससे आपका सभी डेटा मिट जाएगा.\n यह सुविधा अल्फ़ा स्थिति में है और हो सकता है ये ठीक से काम ना करे.\n जारी रखने के लिए \'वाइप करें और बदलें…\' दबाएं."</string> <string name="button_convert_fbe" msgid="5152671181309826405">"वाइप करें और रूपांतरित करें…"</string> <string name="picture_color_mode" msgid="4560755008730283695">"चित्र रंग मोड"</string> <string name="picture_color_mode_desc" msgid="1141891467675548590">"sRGB का उपयोग करें"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> शेष"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> पूरी तरह से चार्ज होने तक"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज हो रही है"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"चार्ज किया जा रहा है"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"चार्ज नहीं हो रही है"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"प्लग इन है, अभी चार्ज नहीं हो सकती"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"पूरी"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"व्यवस्थापक द्वारा नियंत्रित"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"व्यवस्थापक ने सक्षम किया है"</string> @@ -381,7 +383,7 @@ <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"सबसे बड़ा"</string> <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"कस्टम (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string> <string name="help_feedback_label" msgid="6815040660801785649">"सहायता और फ़ीडबैक"</string> - <string name="content_description_menu_button" msgid="8182594799812351266">"मेनू"</string> + <string name="content_description_menu_button" msgid="8182594799812351266">"मेन्यू"</string> <string name="retail_demo_reset_message" msgid="118771671364131297">"डेमो मोड में फ़ैक्टरी रीसेट के लिए पासवर्ड डालें"</string> <string name="retail_demo_reset_next" msgid="8356731459226304963">"आगे"</string> <string name="retail_demo_reset_title" msgid="696589204029930100">"पासवर्ड आवश्यक"</string> diff --git a/packages/SettingsLib/res/values-hr/arrays.xml b/packages/SettingsLib/res/values-hr/arrays.xml index 5deba6f32c84..fb1f546ecd06 100644 --- a/packages/SettingsLib/res/values-hr/arrays.xml +++ b/packages/SettingsLib/res/values-hr/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Upotreba odabira sustava (zadano)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Omogućivanje izbornih kodeka"</item> - <item msgid="3304843301758635896">"Onemogućivanje izbornih kodeka"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Upotreba odabira sustava (zadano)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Omogućivanje izbornih kodeka"</item> - <item msgid="741805482892725657">"Onemogućivanje izbornih kodeka"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Upotreba odabira sustava (zadano)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml index 0b8661578db7..3795dde12f15 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvijek dopusti slobodno traženje Wi-Fi mreže"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilni podaci uvijek aktivni"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzanje za modemsko povezivanje"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogući apsolutnu glasnoću"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Omogući zvuk zvona unutar pojasne širine"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Verzija AVRCP-a za Bluetooth"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Ove su postavke namijenjene samo razvojnim programerima. One mogu uzrokovati kvar ili neželjeno ponašanje vašeg uređaja i aplikacija na njemu."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Potvrdi aplikacije putem USB-a"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Provjerite uzrokuju li aplikacije instalirane putem ADB-a/ADT-a poteškoće."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Onemogućuje Bluetoothovu značajku apsolutne glasnoće ako udaljeni uređaji imaju poteškoća sa zvukom, kao što su, primjerice, neprihvatljiva glasnoća ili nepostojanje kontrole."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Omogući reprodukciju melodija zvona telefona putem Bluetooth slušalica"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Lokalni terminal"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – još <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> do potpune napunjenosti"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Punjenje"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"punjenje"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Ne puni se"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Uključen, trenutačno se ne može puniti"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Puna"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontrolira administrator"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Omogućio administrator"</string> @@ -365,7 +367,7 @@ <string name="disabled" msgid="9206776641295849915">"Onemogućeno"</string> <string name="external_source_trusted" msgid="2707996266575928037">"Dopušteno"</string> <string name="external_source_untrusted" msgid="2677442511837596726">"Nije dopušteno"</string> - <string name="install_other_apps" msgid="6986686991775883017">"Instalacija nepoznatih aplikacija"</string> + <string name="install_other_apps" msgid="6986686991775883017">"Instalacija nepoznatih apl."</string> <string name="home" msgid="3256884684164448244">"Početni zaslon postavki"</string> <string-array name="battery_labels"> <item msgid="8494684293649631252">"0%"</item> diff --git a/packages/SettingsLib/res/values-hu/arrays.xml b/packages/SettingsLib/res/values-hu/arrays.xml index 81d69d030144..b9a42fc6256c 100644 --- a/packages/SettingsLib/res/values-hu/arrays.xml +++ b/packages/SettingsLib/res/values-hu/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Rendszerérték (alapértelmezett)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Nem kötelező kodekek engedélyezése"</item> - <item msgid="3304843301758635896">"Nem kötelező kodekek letiltása"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Rendszerérték (alapértelmezett)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Engedélyezi a nem kötelező kodekeket"</item> - <item msgid="741805482892725657">"Letiltja a nem kötelező kodekeket"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Rendszerérték (alapértelmezett)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml index b6e55eca0c4d..e22b3ce375fd 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi-roaming ellenőrzésének engedélyezése mindig"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"A mobilhálózati kapcsolat mindig aktív"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Internetmegosztás hardveres gyorsítása"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Abszolút hangerő funkció letiltása"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Sávon belüli csörgetés engedélyezése"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"A Bluetooth AVRCP-verziója"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Ezek a beállítások csak fejlesztői használatra szolgálnak. Használatuk esetén eszköze vagy alkalmazásai meghibásodhatnak, illetve nem várt módon viselkedhetnek."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB-n keresztül telepített alkalmazások ellenőrzése"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Az ADB/ADT útján telepített alkalmazások ellenőrzése kártékony viselkedésre."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Letiltja a Bluetooth abszolút hangerő funkcióját a távoli eszközökkel kapcsolatos hangerőproblémák – például elfogadhatatlanul magas vagy nem vezérelhető hangerő – esetén."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"A telefonon lévő csengőhangok Bluetooth-headseteken való lejátszásának engedélyezése"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Helyi végpont"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> van hátra"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> a teljes feltöltésig"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Ismeretlen"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Töltés"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"töltés"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Nem tölt"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Csatlakoztatva, jelenleg nem tölt"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Feltöltve"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Rendszergazda által irányítva"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"A rendszergazda bekapcsolta"</string> @@ -365,7 +367,7 @@ <string name="disabled" msgid="9206776641295849915">"Letiltva"</string> <string name="external_source_trusted" msgid="2707996266575928037">"Engedélyezett"</string> <string name="external_source_untrusted" msgid="2677442511837596726">"Nem engedélyezett"</string> - <string name="install_other_apps" msgid="6986686991775883017">"Ismeretlen alkalmazások telepítése"</string> + <string name="install_other_apps" msgid="6986686991775883017">"Új alkalmazások telepítése"</string> <string name="home" msgid="3256884684164448244">"Beállítások kezdőlapja"</string> <string-array name="battery_labels"> <item msgid="8494684293649631252">"0%"</item> diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml index 22de9389e9ad..27ea288ea7db 100644 --- a/packages/SettingsLib/res/values-hy/arrays.xml +++ b/packages/SettingsLib/res/values-hy/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> աուդիո"</item> + <item msgid="2091430979086738145">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> աուդիո"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"Միացնել լրացուցիչ կոդեկները"</item> <item msgid="3304843301758635896">"Անջատել լրացուցիչ կոդեկները"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> աուդիո"</item> + <item msgid="298198075927343893">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> աուդիո"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"Միացնել լրացուցիչ կոդեկները"</item> <item msgid="741805482892725657">"Անջատել լրացուցիչ կոդեկները"</item> diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml index e44e38707842..6c844b90533c 100644 --- a/packages/SettingsLib/res/values-hy/strings.xml +++ b/packages/SettingsLib/res/values-hy/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Միշտ թույլատրել Wi‑Fi ռոումինգի որոնումը"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Բջջային ինտերնետը միշտ ակտիվ է"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Սարքակազմի արագացման միացում"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Անջատել ձայնի բացարձակ ուժգնությունը"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Միացնել ներխմբային զանգը"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP տարբերակը"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Այս կարգավորումները միայն ծրագրավորման նպատակների համար են նախատեսված: Դրանք կարող են խանգարել ձեր սարքի կամ ծրագրի աշխատանքին:"</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Ստուգել հավելվածները USB-ի նկատմամբ"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Ստուգեք տեղադրված հավելվածը ADB/ADT-ի միջոցով կասկածելի աշխատանքի պատճառով:"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Կասեցնում է Bluetooth-ի ձայնի բացարձակ ուժգնության գործառույթը՝ հեռավոր սարքերի հետ ձայնի ուժգնությանը վերաբերող խնդիրներ ունենալու դեպքում (օրինակ՝ երբ ձայնի ուժգնությունն անընդունելի է կամ դրա կառավարումը հնարավոր չէ):"</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Ընձեռել հեռախոսի բոլոր զանգերանգների Bluetooth ականջակալներով նվագարկումը"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Տեղային տերմինալ"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - մնացել է <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> մինչև լրիվ լիցքավորումը"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Անհայտ"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Լիցքավորում"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"լիցքավորում"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Չի լիցքավորվում"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Միացված է հոսանքի աղբյուրին, սակայն այս պահին չի կարող լիցքավորվել"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Լիցքավորված"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Վերահսկվում է ադմինիստրատորի կողմից"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Միացված է ադմինիստրատորի կողմից"</string> diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml index 7f02a6a29fa1..56c14b99578c 100644 --- a/packages/SettingsLib/res/values-in/arrays.xml +++ b/packages/SettingsLib/res/values-in/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Gunakan Pilihan Sistem (Default)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Aktifkan Codec Opsional"</item> - <item msgid="3304843301758635896">"Nonaktifkan Codec Opsional"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Gunakan Pilihan Sistem (Default)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Aktifkan Codec Opsional"</item> - <item msgid="741805482892725657">"Nonaktifkan Codec Opsional"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Gunakan Pilihan Sistem (Default)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index 89da94bdbb8f..2838be4ae116 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Selalu izinkan Pemindaian Roaming Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Data seluler selalu aktif"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Akselerasi hardware tethering"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Nonaktifkan volume absolut"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Aktifkan dering in-band"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versi AVRCP Bluetooth"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Setelan ini hanya dimaksudkan untuk penggunaan pengembangan. Setelan dapat menyebabkan perangkat dan aplikasi yang menerapkannya rusak atau tidak berfungsi semestinya."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verifikasi aplikasi melalui USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Periksa perilaku membahayakan dalam aplikasi yang terpasang melalui ADB/ADT."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Menonaktifkan fitur volume absolut Bluetooth jika ada masalah volume dengan perangkat jarak jauh, misalnya volume terlalu keras atau kurangnya kontrol."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Izinkan nada dering di ponsel diputar di headset Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Terminal lokal"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> tersisa"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> lagi terisi penuh"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Tidak diketahui"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Mengisi daya"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"mengisi daya baterai"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Tidak mengisi daya"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Tercolok, tidak dapat mengisi baterai sekarang"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Penuh"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Dikontrol oleh admin"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Diaktifkan oleh admin"</string> diff --git a/packages/SettingsLib/res/values-is/arrays.xml b/packages/SettingsLib/res/values-is/arrays.xml index 7f6141d160e5..c4edfd57d26a 100644 --- a/packages/SettingsLib/res/values-is/arrays.xml +++ b/packages/SettingsLib/res/values-is/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Nota val kerfisins (sjálfgefið)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Gera valfrjálsa kóðara virka"</item> - <item msgid="3304843301758635896">"Gera valfrjálsa kóðara óvirka"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Nota val kerfisins (sjálfgefið)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Gera valfrjálsa kóðara virka"</item> - <item msgid="741805482892725657">"Gera valfrjálsa kóðara óvirka"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Nota val kerfisins (sjálfgefið)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml index c5bca1c05167..5db0a3a31791 100644 --- a/packages/SettingsLib/res/values-is/strings.xml +++ b/packages/SettingsLib/res/values-is/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Leyfa alltaf reikileit með Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Alltaf kveikt á farsímagögnum"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Vélbúnaðarhröðun fyrir tjóðrun"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Slökkva á samstillingu hljóðstyrks"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Leyfa símtöl á sömu rás"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP-útgáfa"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Þessar stillingar eru einungis ætlaðar í þróunarskyni. Þær geta valdið því að tækið og forrit þess bili eða starfi á rangan hátt."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Staðfesta forrit gegnum USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kanna skaðlega hegðun forrita sem sett eru upp frá ADB/ADT."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Slekkur á samstillingu Bluetooth-hljóðstyrks ef vandamál koma upp með hljóðstyrk hjá fjartengdum tækjum, svo sem of hár hljóðstyrkur eða erfiðleikar við stjórnun."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Leyfa að hringitónar í símanum spilist í Bluetooth-höfuðtólum"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Staðbundin skipanalína"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> eftir"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> þar til fullri hleðslu er náð"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Óþekkt"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Í hleðslu"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"í hleðslu"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Ekki í hleðslu"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Í sambandi, ekki hægt að hlaða eins og er"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Fullhlaðin"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Stjórnað af kerfisstjóra"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Gert virkt af kerfisstjóra"</string> diff --git a/packages/SettingsLib/res/values-it/arrays.xml b/packages/SettingsLib/res/values-it/arrays.xml index cb6d5f7eaea6..40b28f0dbce4 100644 --- a/packages/SettingsLib/res/values-it/arrays.xml +++ b/packages/SettingsLib/res/values-it/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Usa selezione di sistema (predefinita)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Attiva codec facoltativi"</item> - <item msgid="3304843301758635896">"Disattiva codec facoltativi"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Usa selezione di sistema (predefinita)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Attiva codec facoltativi"</item> - <item msgid="741805482892725657">"Disattiva codec facoltativi"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Usa selezione di sistema (predefinita)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml index cd6b785e32be..b82dce8252fe 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Consenti sempre scansioni roaming Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Dati mobili sempre attivi"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering accelerazione hardware"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disattiva volume assoluto"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Attiva suoneria in banda"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versione Bluetooth AVRCP"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Queste impostazioni sono utilizzabili solo a scopo di sviluppo. Possono causare l\'arresto o il comportamento anomalo del dispositivo e delle applicazioni su di esso."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verifica app tramite USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Controlla che le app installate tramite ADB/ADT non abbiano un comportamento dannoso."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Consente di disattivare la funzione del volume assoluto Bluetooth in caso di problemi con il volume dei dispositivi remoti, ad esempio un volume troppo alto o la mancanza di controllo."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Consenti la riproduzione delle suonerie del telefono tramite gli auricolari Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Terminale locale"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - Tempo rimanente: <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> alla carica completa"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Sconosciuta"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"In carica"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"in carica"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Non in carica"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Collegato alla corrente. Impossibile caricare al momento"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Carica"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Gestita dall\'amministratore"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Attivata dall\'amministratore"</string> diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml index 917f7108b851..f069595e654a 100644 --- a/packages/SettingsLib/res/values-iw/arrays.xml +++ b/packages/SettingsLib/res/values-iw/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"שימוש בבחירת המערכת (ברירת המחדל)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"הפעלה של Codecs אופציונליים"</item> - <item msgid="3304843301758635896">"השבתה של Codecs אופציונליים"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"השתמש בבחירת המערכת (ברירת המחדל)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"הפעלה של Codecs אופציונליים"</item> - <item msgid="741805482892725657">"השבתה של Codecs אופציונליים"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"שימוש בבחירת המערכת (ברירת המחדל)"</item> <item msgid="8895532488906185219">"44.1 קילו-הרץ"</item> diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index 3c0bf6bef275..d73f4207884a 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -147,8 +147,8 @@ <string name="tts_engine_settings_button" msgid="1030512042040722285">"השק הגדרות מנוע"</string> <string name="tts_engine_preference_section_title" msgid="448294500990971413">"מנוע מועדף"</string> <string name="tts_general_section_title" msgid="4402572014604490502">"כללי"</string> - <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"אפס את גובה צליל הדיבור"</string> - <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"אפס את גובה הצליל שבו מושמע הטקסט לברירת המחדל."</string> + <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"איפוס של גובה צליל הדיבור"</string> + <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"איפוס גובה הצליל שבו מושמע הטקסט לברירת המחדל."</string> <string-array name="tts_rate_entries"> <item msgid="6695494874362656215">"איטי מאוד"</item> <item msgid="4795095314303559268">"איטי"</item> @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"התר תמיד סריקות נדידה של Wi‑Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"חבילת הגלישה פעילה תמיד"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"שיפור מהירות באמצעות חומרה לצורך שיתוף אינטרנט בין ניידים"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"השבת עוצמת קול מוחלטת"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"הפעל צלצולים בערוץ ה-Bluetooth (in-band ringing)"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth גרסה AVRCP"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"הגדרות אלה מיועדות לשימוש בפיתוח בלבד. הן עלולות לגרום למכשיר או לאפליקציות המותקנות בו לקרוס או לפעול באופן לא תקין."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"אמת אפליקציות באמצעות USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"בדוק אפליקציות שהותקנו באמצעות ADB/ADT לאיתור התנהגות מזיקה."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"משבית את תכונת עוצמת הקול המוחלטת ב-Bluetooth במקרה של בעיות בעוצמת הקול במכשירים מרוחקים, כגון עוצמת קול רמה מדי או חוסר שליטה ברמת העוצמה."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"הפעלת רינגטונים באוזניות Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"מסוף מקומי"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - נותרו <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> עד לטעינה מלאה"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"לא ידוע"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"טוען"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"בטעינה"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"לא בטעינה"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"המכשיר מחובר, אבל לא ניתן לטעון עכשיו"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"מלא"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"נמצא בשליטת מנהל מערכת"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"מופעל על ידי מנהל המכשיר"</string> @@ -365,7 +367,7 @@ <string name="disabled" msgid="9206776641295849915">"מושבת"</string> <string name="external_source_trusted" msgid="2707996266575928037">"מורשה"</string> <string name="external_source_untrusted" msgid="2677442511837596726">"לא מורשה"</string> - <string name="install_other_apps" msgid="6986686991775883017">"להתקין גם אם לא מוכר?"</string> + <string name="install_other_apps" msgid="6986686991775883017">"להתקין גם אם לא מוכר לך?"</string> <string name="home" msgid="3256884684164448244">"דף הבית של ההגדרות"</string> <string-array name="battery_labels"> <item msgid="8494684293649631252">"0%"</item> diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml index 779e2b11dbe8..1c7d2e96cbb5 100644 --- a/packages/SettingsLib/res/values-ja/arrays.xml +++ b/packages/SettingsLib/res/values-ja/arrays.xml @@ -23,7 +23,7 @@ <string-array name="wifi_status"> <item msgid="1922181315419294640"></item> <item msgid="8934131797783724664">"スキャン中..."</item> - <item msgid="8513729475867537913">"接続中..."</item> + <item msgid="8513729475867537913">"接続処理中..."</item> <item msgid="515055375277271756">"認証中..."</item> <item msgid="1943354004029184381">"IPアドレスを取得中..."</item> <item msgid="4221763391123233270">"接続済み"</item> @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"システムの選択(デフォルト)を使用"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> オーディオ"</item> + <item msgid="2091430979086738145">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> オーディオ"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"オプションのコーデックの有効化"</item> <item msgid="3304843301758635896">"オプションのコーデックの無効化"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"システムの選択(デフォルト)を使用"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> オーディオ"</item> + <item msgid="298198075927343893">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> オーディオ"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"オプションのコーデックを有効にします"</item> <item msgid="741805482892725657">"オプションのコーデックを無効にします"</item> diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index 713f796a6a3a..4a574952ed9f 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -52,7 +52,7 @@ <string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string> <string name="bluetooth_disconnected" msgid="6557104142667339895">"切断"</string> <string name="bluetooth_disconnecting" msgid="8913264760027764974">"切断中..."</string> - <string name="bluetooth_connecting" msgid="8555009514614320497">"接続中..."</string> + <string name="bluetooth_connecting" msgid="8555009514614320497">"接続処理中..."</string> <string name="bluetooth_connected" msgid="6038755206916626419">"接続"</string> <string name="bluetooth_pairing" msgid="1426882272690346242">"ペアとして設定中..."</string> <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"接続済み(電話を除く)"</string> @@ -119,7 +119,7 @@ <string name="user_guest" msgid="8475274842845401871">"ゲスト"</string> <string name="unknown" msgid="1592123443519355854">"不明"</string> <string name="running_process_item_user_label" msgid="3129887865552025943">"ユーザー: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string> - <string name="launch_defaults_some" msgid="313159469856372621">"一部デフォルトを設定"</string> + <string name="launch_defaults_some" msgid="313159469856372621">"一部デフォルトで設定"</string> <string name="launch_defaults_none" msgid="4241129108140034876">"デフォルトの設定なし"</string> <string name="tts_settings" msgid="8186971894801348327">"テキスト読み上げの設定"</string> <string name="tts_settings_title" msgid="1237820681016639683">"テキスト読み上げの出力"</string> @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fiローミングスキャンを常に許可する"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"モバイルデータを常に ON にする"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"テザリング時のハードウェア アクセラレーション"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"絶対音量を無効にする"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"インバンド リンギングを有効にする"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP バージョン"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"これらの設定は開発専用に設計されています。そのため端末や端末上のアプリが故障したり正常に動作しなくなったりするおそれがあります。"</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB経由のアプリを確認"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT経由でインストールされたアプリに不正な動作がないかを確認する"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"リモート端末で音量に関する問題(音量が大きすぎる、制御できないなど)が発生した場合に、Bluetooth の絶対音量の機能を無効にする。"</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"スマートフォンの着信音が Bluetooth ヘッドセットで再生されることを許可する"</string> <string name="enable_terminal_title" msgid="95572094356054120">"ローカルターミナル"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>(残り時間)"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - フル充電まで <xliff:g id="TIME">^2</xliff:g>"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"不明"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"充電しています"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"充電していません"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"接続されていますが、現在、充電できません"</string> <!-- String.format failed for translation --> <!-- no translation found for battery_info_status_full (2824614753861462808) --> <skip /> diff --git a/packages/SettingsLib/res/values-ka/arrays.xml b/packages/SettingsLib/res/values-ka/arrays.xml index cf2113b60336..69ebd3301351 100644 --- a/packages/SettingsLib/res/values-ka/arrays.xml +++ b/packages/SettingsLib/res/values-ka/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"არასავალდებულო კოდეკების ჩართვა"</item> - <item msgid="3304843301758635896">"არასავალდებულო კოდეკების გათიშვა"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"არასავალდებულო კოდეკების ჩართვა"</item> - <item msgid="741805482892725657">"არასავალდებულო კოდეკების გათიშვა"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item> <item msgid="8895532488906185219">"44,1 კჰც"</item> diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml index ff275236e84f..cbacb28c58d5 100644 --- a/packages/SettingsLib/res/values-ka/strings.xml +++ b/packages/SettingsLib/res/values-ka/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi Roam სკანირების მუდამ დაშვება"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"მობილური ინტერნეტის ყოველთვის გააქტიურება"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"ტეტერინგის აპარატურული აჩქარება"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ხმის აბსოლუტური სიძლიერის გათიშვა"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"ზოლსშიდა დარეკვის ჩართვა"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth-ის AVRCP-ის ვერსია"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"ამ პარამეტრების გამოყენება დასაშვებია მხოლოდ დეველოპერული მიზნებით. მათმა გამოყენებამ შეიძლება გამოიწვიოს თქვენი მოწყობილობის და მისი აპლიკაციების დაზიანება ან გაუმართავი მუშაობა."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"აპლიკაციების USB-ს საშუალებით შემოწმება"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"შეამოწმეთ, რამდენად უსაფრთხოა ADB/ADT-ის საშუალებით ინსტალირებული აპლიკაციები."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"გათიშავს Bluetooth-ის ხმის აბსოლუტური სიძლიერის ფუნქციას დისტანციურ მოწყობილობებზე ხმასთან დაკავშირებული ისეთი პრობლემების არსებობის შემთხვევაში, როგორიცაა ხმის დაუშვებლად მაღალი სიძლიერე ან კონტროლის შეუძლებლობა."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ტელეფონის ზარების Bluetooth-ყურსაცვამებზე დაკვრის დაშვება"</string> <string name="enable_terminal_title" msgid="95572094356054120">"ადგილობრივი ტერმინალი"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> — დარჩენილია <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> — სრულ დატენვამდე დარჩა <xliff:g id="TIME">^2</xliff:g>"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> — <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"უცნობი"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"იტენება"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"იტენება"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"არ იტენება"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"მიერთებულია, დატენვა ამჟამად ვერ ხერხდება"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"ბატარეა დატენილია"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"იმართება ადმინისტრატორის მიერ"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"ჩართულია ადმინისტრატორის მიერ"</string> diff --git a/packages/SettingsLib/res/values-kk/arrays.xml b/packages/SettingsLib/res/values-kk/arrays.xml index e3481084ab43..2fb35e0a38a8 100644 --- a/packages/SettingsLib/res/values-kk/arrays.xml +++ b/packages/SettingsLib/res/values-kk/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Жүйені таңдау (әдепкі)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Қосымша кодектерді қосу"</item> - <item msgid="3304843301758635896">"Қосымша кодектерді өшіру"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Жүйені таңдау (әдепкі)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Қосымша кодектерді қосу"</item> - <item msgid="741805482892725657">"Қосымша кодектерді өшіру"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Жүйені таңдау (әдепкі)"</item> <item msgid="8895532488906185219">"44,1 кГц"</item> diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml index 5c0713914864..354e0b5ddb9b 100644 --- a/packages/SettingsLib/res/values-kk/strings.xml +++ b/packages/SettingsLib/res/values-kk/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi роумингін іздеулерге әрқашан рұқсат ету"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Мобильдік деректер әрқашан қосулы"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Тетерингтің аппараттық жеделдетуі"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Абсолютті дыбыс деңгейін өшіру"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Ішкі жолақтағы шылдырлауды қосу"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP нұсқасы"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Бұл параметрлер жетілдіру мақсатында ғана қолданылады. Олар құрылғыңыз бен қолданбаларыңыздың бұзылуына немесе әдеттен тыс әрекеттерге себеп болуы мүмкін."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB арқылы орнатылған қолданбаларды растау"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT арқылы орнатылған қолданбалардың залалды болмауын тексеру."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Қолайсыз қатты дыбыс деңгейі немесе басқарудың болмауы сияқты қашықтағы құрылғыларда дыбыс деңгейімен мәселелер жағдайында Bluetooth абсолютті дыбыс деңгейі функциясын өшіреді."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Телефондағы қоңырау әуендерінің Bluetooth құлақаспабында ойнатылуына мүмкіндік беру"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Жергілікті терминал"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> қалды"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – толық зарядталғанға дейін <xliff:g id="TIME">^2</xliff:g>"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Белгісіз"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Зарядталуда"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"зарядталуда"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Зарядталу орындалып жатқан жоқ"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Қосылған, зарядталмайды"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Толық"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Әкімші басқарады"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Әкімші қосқан"</string> diff --git a/packages/SettingsLib/res/values-km/arrays.xml b/packages/SettingsLib/res/values-km/arrays.xml index 27e0e5917f26..43406c0cbd2e 100644 --- a/packages/SettingsLib/res/values-km/arrays.xml +++ b/packages/SettingsLib/res/values-km/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"ប្រើការជ្រើសរើសប្រព័ន្ធ (លំនាំដើម)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"បើកកូឌិកប្រភេទស្រេចចិត្ត"</item> - <item msgid="3304843301758635896">"បិទកូឌិកប្រភេទស្រេចចិត្ត"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"ប្រើការជ្រើសរើសប្រព័ន្ធ (លំនាំដើម)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"បើកកូឌិកប្រភេទស្រេចចិត្ត"</item> - <item msgid="741805482892725657">"បិទកូឌិកប្រភេទស្រេចចិត្ត"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"ប្រើការជ្រើសរើសប្រព័ន្ធ (លំនាំដើម)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml index 45687bfe30aa..f9800669cf63 100644 --- a/packages/SettingsLib/res/values-km/strings.xml +++ b/packages/SettingsLib/res/values-km/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"តែងតែអនុញ្ញាតការវិភាគរ៉ូមវ៉ាយហ្វាយ"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"ទិន្នន័យទូរសព្ទចល័តដំណើរការជានិច្ច"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"ការបង្កើនល្បឿនផ្នែករឹងសម្រាប់ការភ្ជាប់"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"បិទកម្រិតសំឡេងលឺខ្លាំង"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"បើកការរោទ៍ក្នុងបណ្តាញ"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"កំណែប្ល៊ូធូស AVRCP"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"ការកំណត់ទាំងនេះសម្រាប់តែការប្រើក្នុងការអភិវឌ្ឍប៉ុណ្ណោះ។ ពួកវាអាចធ្វើឲ្យឧបករណ៍ និងកម្មវិធីរបស់អ្នកខូច ឬដំណើរមិនត្រឹមត្រូវ។"</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"ផ្ទៀងផ្ទាត់កម្មវិធីតាមយូអេសប៊ី"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ពិនិត្យកម្មវិធីបានដំឡើងតាមរយៈ ADB/ADT សម្រាប់ឥរិយាបថដែលគ្រោះថ្នាក់។"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"បិទលក្ខណៈពិសេសកម្រិតសំឡេងលឺខ្លាំងពេលភ្ជាប់ប៊្លូធូសក្នុងករណីមានបញ្ហាជាមួយឧបករណ៍បញ្ជាពីចម្ងាយ ដូចជាកម្រិតសំឡេងលឺខ្លាំងដែលមិនអាចទទួលយកបាន ឬខ្វះការគ្រប់គ្រង។"</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"អនុញ្ញាតឲ្យសំឡេងរោទ៍នៅលើទូរសព្ទបញ្ចេញសំឡេងតាមរយៈកាសប្ល៊ូធូស"</string> <string name="enable_terminal_title" msgid="95572094356054120">"ស្ថានីយមូលដ្ឋាន"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - នៅសល់ <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> រហូតដល់សាកពេញ"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"មិនស្គាល់"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"កំពុងបញ្ចូលថ្ម"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"កំពុងសាកថ្ម"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"មិនកំពុងបញ្ចូលថ្ម"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"ដោតសាកថ្មរួចហើយ ប៉ុន្តែសាកថ្មមិនចូលទេឥឡូវនេះ"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"ពេញ"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"គ្រប់គ្រងដោយអ្នកគ្រប់គ្រង"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"បើកដោយអ្នកគ្រប់គ្រង"</string> diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml index 810aefedb04d..54eebda034bd 100644 --- a/packages/SettingsLib/res/values-kn/arrays.xml +++ b/packages/SettingsLib/res/values-kn/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"ಐಚ್ಛಿಕ ಕೋಡೆಕ್ಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</item> - <item msgid="3304843301758635896">"ಐಚ್ಛಿಕ ಕೋಡೆಕ್ಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"ಐಚ್ಛಿಕ ಕೋಡೆಕ್ಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</item> - <item msgid="741805482892725657">"ಐಚ್ಛಿಕ ಕೋಡೆಕ್ಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml index 0b39e26cf7df..40dea01a0e6f 100644 --- a/packages/SettingsLib/res/values-kn/strings.xml +++ b/packages/SettingsLib/res/values-kn/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ವೈ-ಫೈ ರೋಮ್ ಸ್ಕ್ಯಾನ್ಗಳನ್ನು ಯಾವಾಗಲೂ ಅನುಮತಿಸಿ"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"ಮೊಬೈಲ್ ಡೇಟಾ ಯಾವಾಗಲೂ ಸಕ್ರಿಯ"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"ಹಾರ್ಡ್ವೇರ್ನ ವೇಗವರ್ಧನೆಯನ್ನು ಟೆಥರಿಂಗ್ ಮಾಡಿ"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ಸಂಪೂರ್ಣ ವಾಲ್ಯೂಮ್ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"ಇನ್ ಬ್ಯಾಂಡ್ ರಿಂಗಿಂಗ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ಬ್ಲೂಟೂತ್ AVRCP ಆವೃತ್ತಿ"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"ಈ ಸೆಟ್ಟಿಂಗ್ಗಳು ಅಭಿವೃದ್ಧಿಯ ಬಳಕೆಗೆ ಮಾತ್ರ. ಅವುಗಳು ನಿಮ್ಮ ಸಾಧನ ಮತ್ತು ಅಪ್ಲಿಕೇಶನ್ಗಳಿಗೆ ಧಕ್ಕೆ ಮಾಡಬಹುದು ಅಥವಾ ಅವು ಸರಿಯಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸದಿರುವಂತೆ ಮಾಡಬಹುದು."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB ಮೂಲಕ ಆಪ್ ಪರಿಶೀಲಿಸಿ"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ಹಾನಿಮಾಡುವಂತಹ ವರ್ತನೆಗಾಗಿ ADB/ADT ಮೂಲಕ ಸ್ಥಾಪಿಸಲಾದ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ರಿಮೋಟ್ ಸಾಧನಗಳೊಂದಿಗೆ ಒಪ್ಪಲಾಗದ ಜೋರಾದ ವಾಲ್ಯೂಮ್ ಅಥವಾ ನಿಯಂತ್ರಣದ ಕೊರತೆಯಂತಹ ವಾಲ್ಯೂಮ್ ಸಮಸ್ಯೆಗಳಂತಹ ಸಂದರ್ಭದಲ್ಲಿ ಬ್ಲೂಟೂತ್ ಸಂಪೂರ್ಣ ವಾಲ್ಯೂಮ್ ವೈಶಿಷ್ಟ್ಯವನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಬಹುದು."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ಫೋನ್ನ ರಿಂಗ್ಟೋನ್ಗಳನ್ನು ಬ್ಲೂಟೂತ್ ಹೆಡ್ಸೆಟ್ಗಳಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲು ಅನುಮತಿ ನೀಡಿ"</string> <string name="enable_terminal_title" msgid="95572094356054120">"ಸ್ಥಳೀಯ ಟರ್ಮಿನಲ್"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> ಉಳಿದಿದೆ"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - ಸಂಪೂರ್ಣ ಚಾರ್ಜ್ ಆಗಲು <xliff:g id="TIME">^2</xliff:g>"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"ಅಪರಿಚಿತ"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"ಚಾರ್ಜ್ ಆಗುತ್ತಿಲ್ಲ"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"ಪ್ಲಗ್ ಇನ್ ಮಾಡಲಾಗಿದೆ, ಇದೀಗ ಚಾರ್ಜ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"ಭರ್ತಿ"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"ನಿರ್ವಾಹಕರ ಮೂಲಕ ನಿಯಂತ್ರಿಸಲಾಗಿದೆ"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"ನಿರ್ವಾಹಕರು ಸಕ್ರಿಯಗೊಳಿಸಿದ್ದಾರೆ"</string> diff --git a/packages/SettingsLib/res/values-ko/arrays.xml b/packages/SettingsLib/res/values-ko/arrays.xml index dbbe89dbeed9..57b691125640 100644 --- a/packages/SettingsLib/res/values-ko/arrays.xml +++ b/packages/SettingsLib/res/values-ko/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"시스템 설정 사용(기본)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"선택사항 코덱 사용 설정"</item> - <item msgid="3304843301758635896">"선택사항 코덱 사용 중지"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"시스템 설정 사용(기본)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"선택사항 코덱 사용 설정"</item> - <item msgid="741805482892725657">"선택사항 코덱 사용 중지"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"시스템 설정 사용(기본)"</item> <item msgid="8895532488906185219">"44.1kHz"</item> diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index 9bd711130759..5c89d8b7a5f5 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi 로밍 스캔 항상 허용"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"항상 모바일 데이터 활성화"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"테더링 하드웨어 가속"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"절대 볼륨 사용 안함"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"대역 내 벨소리 사용 설정"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"블루투스 AVRCP 버전"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"이 설정은 개발자용으로만 설계되었습니다. 이 설정을 사용하면 기기 및 애플리케이션에 예기치 않은 중단이나 오류가 발생할 수 있습니다."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB를 통해 설치된 앱 확인"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT을 통해 설치된 앱에 유해한 동작이 있는지 확인"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"참기 어려울 정도로 볼륨이 크거나 제어가 되지 않는 등 원격 기기에서 볼륨 문제가 발생할 경우 블루투스 절대 볼륨 기능을 사용 중지합니다."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"휴대전화의 벨소리가 블루투스 헤드셋에서 재생되도록 허용"</string> <string name="enable_terminal_title" msgid="95572094356054120">"로컬 터미널"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> 남음"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - 충전 완료까지 <xliff:g id="TIME">^2</xliff:g> 남음"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"알 수 없음"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"충전 중"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"충전 중"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"충전 안함"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"전원이 연결되었지만 현재 충전할 수 없음"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"충전 완료"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"관리자가 제어"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"관리자가 사용 설정함"</string> diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml index 9c8e28a1e42d..bb4da499017a 100644 --- a/packages/SettingsLib/res/values-ky/arrays.xml +++ b/packages/SettingsLib/res/values-ky/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Тутум тандаганды колдонуу (демейки)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Кошумча кодекстер иштетилсин"</item> - <item msgid="3304843301758635896">"Кошумча кодекстер өчүрүлсүн"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Тутум тандаганды колдонуу (демейки)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Кошумча кодекстер иштетилсин"</item> - <item msgid="741805482892725657">"Кошумча кодекстер өчүрүлсүн"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Тутум тандаганды колдонуу (демейки)"</item> <item msgid="8895532488906185219">"44,1 кГц"</item> diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml index f26ed8c6b6c5..6680d07b1db0 100644 --- a/packages/SettingsLib/res/values-ky/strings.xml +++ b/packages/SettingsLib/res/values-ky/strings.xml @@ -119,7 +119,7 @@ <string name="user_guest" msgid="8475274842845401871">"Конок"</string> <string name="unknown" msgid="1592123443519355854">"Белгисиз"</string> <string name="running_process_item_user_label" msgid="3129887865552025943">"Колдонуучу: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string> - <string name="launch_defaults_some" msgid="313159469856372621">"Айрым демейкилер коюлду"</string> + <string name="launch_defaults_some" msgid="313159469856372621">"Айрым демейки параметрлер туураланды"</string> <string name="launch_defaults_none" msgid="4241129108140034876">"Демейкилер коюлган жок"</string> <string name="tts_settings" msgid="8186971894801348327">"Кеп синтезаторунун жөндөөлөрү"</string> <string name="tts_settings_title" msgid="1237820681016639683">"Текстти-оозекилөө"</string> @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi Роуминг Скандоо мүмкүнчүлүгүнө ар дайым уруксат берилсин"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Мобилдик Интернет иштей берсин"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Тетерингдин иштешин тездетүү"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Үндүн абсолюттук деңгээли өчүрүлсүн"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Канал аралык чалууну иштетүү"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP версиясы"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Бул орнотуулар өндүрүүчүлөр үчүн гана берилген. Булар түзмөгүңүздүн колдонмолорун бузулушуна же туура эмес иштешине алып келиши мүмкүн."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB аркылуу келген колдонмолорду ырастоо"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT аркылуу орнотулган колдонмолорду зыянкечтикке текшерүү."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Алыскы түзмөктөр өтө катуу добуш чыгарып же көзөмөлдөнбөй жатса Bluetooth \"Үндүн абсолюттук деңгээли\" функциясын өчүрөт."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Телефондогу рингтондор Bluetooth гарнитурасында ойнотулсун"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Жергиликтүү терминал"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> калды"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> кийин толук кубатталат"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Белгисиз"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Кубатталууда"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"кубатталууда"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Кубат алган жок"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Сайылып турат, учурда кубаттоо мүмкүн эмес"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Толук"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Администратор тарабынан көзөмөлдөнөт"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Администратор иштетип койгон"</string> diff --git a/packages/SettingsLib/res/values-lo/arrays.xml b/packages/SettingsLib/res/values-lo/arrays.xml index 63889e03fc9e..5b546ff241c9 100644 --- a/packages/SettingsLib/res/values-lo/arrays.xml +++ b/packages/SettingsLib/res/values-lo/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"Use System Selection (Default)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="2091430979086738145">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"ເປີດໃຊ້ Codecs ແບບເສີມ"</item> <item msgid="3304843301758635896">"ປິດການໃຊ້ Codecs ແບບເສີມ"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"Use System Selection (Default)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="298198075927343893">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"ເປີດໃຊ້ Codecs ແບບເສີມ"</item> <item msgid="741805482892725657">"ປິດການໃຊ້ Codecs ແບບເສີມ"</item> diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml index 350066471dce..25809e14bbd1 100644 --- a/packages/SettingsLib/res/values-lo/strings.xml +++ b/packages/SettingsLib/res/values-lo/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ອະນຸຍາດການສະແກນການໂຣມ Wi‑Fi ສະເໝີ"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"ເປີດໃຊ້ອິນເຕີເນັດມືຖືຕະຫຼອດເວລາ"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"ເປີດໃຊ້ການເລັ່ງຄວາມໄວດ້ວຍຮາດແວ"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ປິດໃຊ້ລະດັບສຽງສົມບູນ"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"ເປີດສຽງເຕືອນແບບອິນແບນ"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ເວີຊັນ Bluetooth AVRCP"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"ການຕັ້ງຄ່າເຫຼົ່ານີ້ແມ່ນມີຈຸດປະສົງເພື່ອການພັດທະນາເທົ່ານັ້ນ. ພວກມັນສາມາດເຮັດໃຫ້ອຸປະກອນ ແລະແອັບພລິເຄຊັນຂອງທ່ານຢຸດເຮັດວຽກ ຫຼືເຮັດວຽກຜິດປົກກະຕິໄດ້."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"ຢືນຢັນແອັບຯຜ່ານທາງ USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ກວດສອບແອັບຯທີ່ຕິດຕັ້ງແລ້ວຜ່ານທາງ ADB/ADT ເພື່ອກວດຫາພຶດຕິກຳທີ່ເປັນອັນຕະລາຍ."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ປິດໃຊ້ຄຸນສົມບັດລະດັບສຽງສົມບູນຂອງ Bluetooth ໃນກໍລະນີເກີດບັນຫາລະດັບສຽງສົມບູນກັບອຸປະກອນທາງໄກ ເຊັ່ນວ່າ ລະດັບສຽງດັງເກີນຍອມຮັບໄດ້ ຫຼື ຄວບຄຸມບໍ່ໄດ້."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ເປີດໃຫ້ສຽງຣິງໂທນຢູ່ໂທລະສັບດັງໃນຫູຟັງ Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Terminal ໃນໂຕເຄື່ອງ"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - ຍັງເຫຼືອ <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> ຈົນກວ່າຈະສາກເຕັມ"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"ບໍ່ຮູ້ຈັກ"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"ກຳລັງສາກໄຟ"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ກຳລັງສາກໄຟ"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"ບໍ່ໄດ້ສາກໄຟ"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"ສຽບສາຍແລ້ວ, ບໍ່ສາມາດສາກໄດ້ໃນຕອນນີ້"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"ເຕັມ"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"ຄວບຄຸມໂດຍຜູ້ເບິ່ງແຍງ"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"ຜູ້ເບິ່ງແຍງລະບົບເປີດໃຫ້ໃຊ້ແລ້ວ"</string> diff --git a/packages/SettingsLib/res/values-lt/arrays.xml b/packages/SettingsLib/res/values-lt/arrays.xml index 3c325c17320a..1276e2bd810c 100644 --- a/packages/SettingsLib/res/values-lt/arrays.xml +++ b/packages/SettingsLib/res/values-lt/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Naudoti sistemos pasirink. (numatytasis)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Įgalinti nebūtinus kodekus"</item> - <item msgid="3304843301758635896">"Išjungti nebūtinus kodekus"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Naudoti sistemos pasirink. (numatytasis)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Įgalinti nebūtinus kodekus"</item> - <item msgid="741805482892725657">"Išjungti nebūtinus kodekus"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Naudoti sistemos pasirink. (numatytasis)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml index 889f312c8edf..5c8c5db5f26e 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Visada leisti „Wi-Fi“ tarptiklinio ryšio nuskaitymą"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiliojo ryšio duomenys visada suaktyvinti"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Įrenginio kaip modemo naudojimo aparatinės įrangos spartinimas"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Išjungti didžiausią garsą"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Įgalinti diapazono skambėjimą"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"„Bluetooth“ AVRCP versija"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Šie nustatymai skirti tik kūrėjams. Nustačius juos įrenginys ir jame naudojamos programos gali nustoti veikti arba veikti netinkamai."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Patvirtinti progr. naudojant USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Patikrinkite, ar programų, įdiegtų naudojant ADB / ADT, veikimas nėra žalingas."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Išjungiama „Bluetooth“ didžiausio garso funkcija, jei naudojant nuotolinio valdymo įrenginius kyla problemų dėl garso, pvz., garsas yra per didelis arba jo negalima tinkamai valdyti."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Leisti telefono skambėjimo tonus per „Bluetooth“ ausines"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Vietinis terminalas"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – liko <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> iki visiško įkrovimo"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Nežinomas"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Kraunasi..."</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"įkraunama"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Nekraunama"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Įjungta į maitinimo lizdą, bet šiuo metu įkrauti neįmanoma"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Visiškai įkrautas"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Valdo administratorius"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Įgalino administratorius"</string> diff --git a/packages/SettingsLib/res/values-lv/arrays.xml b/packages/SettingsLib/res/values-lv/arrays.xml index 2c69c7e61f56..9cc2702e7ddb 100644 --- a/packages/SettingsLib/res/values-lv/arrays.xml +++ b/packages/SettingsLib/res/values-lv/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Sistēmas atlases izmantošana (nokl.)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Iespējot neobligātos kodekus"</item> - <item msgid="3304843301758635896">"Atspējot neobligātos kodekus"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Sistēmas atlases izmantošana (nokl.)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Iespējot neobligātos kodekus"</item> - <item msgid="741805482892725657">"Atspējot neobligātos kodekus"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Sistēmas atlases izmantošana (nokl.)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml index 512ebaaba0ef..089862479d4e 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vienmēr atļaut Wi‑Fi meklēšanu"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Vienmēr aktīvs mobilo datu savienojums"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Paātrināta aparatūras darbība piesaistei"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Atspējot absolūto skaļumu"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Iespējot iekšjoslas zvanīšanu"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP versija"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Šie iestatījumi ir paredzēti tikai izstrādei. To dēļ var tikt pārtraukta vai traucēta ierīces un lietojumprogrammu darbība."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificēt, ja instalētas no USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Pārbaudīt, vai lietotņu, kuru instalēšanai izmantots ADB/ADT, darbība nav kaitīga."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Atspējo Bluetooth absolūtā skaļuma funkciju skaļuma problēmu gadījumiem attālajās ierīcēs, piemēram, ja ir nepieņemami liels skaļums vai nav iespējas kontrolēt skaļumu."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Atļaut tālrunī esošo zvana signālu atskaņošanu Bluetooth austiņās"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Vietējā beigu lietotne"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> — atlicis: <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>, kamēr pilnībā uzlādēts"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> — <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Nezināms"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Uzlāde"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"notiek uzlāde"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Nenotiek uzlāde"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Pievienots, taču pašlaik nevar veikt uzlādi"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Pilns"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontrolē administrators"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Iespējoja administrators"</string> diff --git a/packages/SettingsLib/res/values-mk/arrays.xml b/packages/SettingsLib/res/values-mk/arrays.xml index 2da43f0925b8..a204da6b222a 100644 --- a/packages/SettingsLib/res/values-mk/arrays.xml +++ b/packages/SettingsLib/res/values-mk/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Користи избор на системот (стандардно)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Овозможување на „Кодеци по избор“"</item> - <item msgid="3304843301758635896">"Оневозможување на „Кодеци по избор“"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Користи избор на системот (стандардно)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Овозможи ја „Кодеци по избор“"</item> - <item msgid="741805482892725657">"Оневозможи ја „Кодеци по избор“"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Користи избор на системот (стандардно)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml index 0dbaae2fea0d..8377fd57e700 100644 --- a/packages/SettingsLib/res/values-mk/strings.xml +++ b/packages/SettingsLib/res/values-mk/strings.xml @@ -144,7 +144,7 @@ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> не е поддржано"</string> <string name="tts_status_checking" msgid="5339150797940483592">"Се проверува..."</string> <string name="tts_engine_settings_title" msgid="3499112142425680334">"Поставки на <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string> - <string name="tts_engine_settings_button" msgid="1030512042040722285">"Стартувај подесувања на софтвер"</string> + <string name="tts_engine_settings_button" msgid="1030512042040722285">"Стартувај поставки на софтвер"</string> <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Претпочитан софтвер"</string> <string name="tts_general_section_title" msgid="4402572014604490502">"Општо"</string> <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Ресетирајте ја висината на изговорот"</string> @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Секогаш дозволувај Wi‑Fi скенирање во роаминг"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Мобилниот интернет е секогаш активен"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Хардверско забрзување за врзување"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Оневозможете апсолутна јачина на звук"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Овозможете ѕвонење во појас"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Верзија Bluetooth AVRCP"</string> @@ -228,10 +230,12 @@ <string name="adb_warning_title" msgid="6234463310896563253">"Овозможи отстранување грешки на USB?"</string> <string name="adb_warning_message" msgid="7316799925425402244">"Отстранувањето грешки на USB е наменето само за целите на развој. Користете го за копирање податоци меѓу вашиот компјутер и вашиот уред, за инсталирање апликации на вашиот уред без известување и за читање евиденција на податоци."</string> <string name="adb_keys_warning_message" msgid="5659849457135841625">"Отповикај пристап кон отстранување грешка од USB од сите претходно овластени компјутери?"</string> - <string name="dev_settings_warning_title" msgid="7244607768088540165">"Дозволи подесувања за развој?"</string> - <string name="dev_settings_warning_message" msgid="2298337781139097964">"Овие подесувања се наменети само за употреба за развој. Тие може да предизвикаат уредот и апликациите во него да се расипат или да се однесуваат необично."</string> + <string name="dev_settings_warning_title" msgid="7244607768088540165">"Дозволи поставки за развој?"</string> + <string name="dev_settings_warning_message" msgid="2298337781139097964">"Овие поставки се наменети само за употреба за развој. Тие може да предизвикаат уредот и апликациите во него да се расипат или да се однесуваат необично."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Потврди апликации преку USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Провери апликации инсталирани преку ADB/ADT за штетно однесување."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Ја оневозможува карактеристиката за апсолутна јачина на звук преку Bluetooth во случај кога ќе настанат проблеми со далечинските уреди, како на пр., неприфатливо силен звук или недоволна контрола."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Дозволи мелодиите на телефонот да се пуштаат на Bluetooth слушалките"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Локален терминал"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - уште <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> дури се наполни целосно"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Непознато"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Се полни"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"се полни"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Не се полни"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Приклучен е, но батеријата не може да се полни во моментов"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Полна"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Контролирано од администраторот"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Овозможено од администраторот"</string> diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml index 57382f1a0c00..bf5860878620 100644 --- a/packages/SettingsLib/res/values-ml/arrays.xml +++ b/packages/SettingsLib/res/values-ml/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ (ഡിഫോൾട്ട്)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"ഓപ്ഷണൽ കോഡെകുകൾ പ്രവർത്തനക്ഷമമാക്കുക"</item> - <item msgid="3304843301758635896">"ഓപ്ഷണൽ കോഡെകുകൾ പ്രവർത്തനരഹിതമാക്കുക"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ (ഡിഫോൾട്ട്)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"ഓപ്ഷണൽ കോഡെകുകൾ പ്രവർത്തനക്ഷമമാക്കുക"</item> - <item msgid="741805482892725657">"ഓപ്ഷണൽ കോഡെകുകൾ പ്രവർത്തനരഹിതമാക്കുക"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ (ഡിഫോൾട്ട്)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml index 84c1279dbdcb..63704f47bfa0 100644 --- a/packages/SettingsLib/res/values-ml/strings.xml +++ b/packages/SettingsLib/res/values-ml/strings.xml @@ -119,12 +119,12 @@ <string name="user_guest" msgid="8475274842845401871">"അതിഥി"</string> <string name="unknown" msgid="1592123443519355854">"അജ്ഞാതം"</string> <string name="running_process_item_user_label" msgid="3129887865552025943">"ഉപയോക്താവ്: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string> - <string name="launch_defaults_some" msgid="313159469856372621">"സ്ഥിരമായ ചിലവ സജ്ജീകരിച്ചു"</string> + <string name="launch_defaults_some" msgid="313159469856372621">"സ്ഥിരമായ ചിലത് സജ്ജീകരിച്ചു"</string> <string name="launch_defaults_none" msgid="4241129108140034876">"സ്ഥിരമായൊന്നും സജ്ജീകരിച്ചിട്ടില്ല"</string> <string name="tts_settings" msgid="8186971894801348327">"ടെക്സ്റ്റ്-ടു-സ്പീച്ച് ക്രമീകരണങ്ങൾ"</string> <string name="tts_settings_title" msgid="1237820681016639683">"ടെക്സ്റ്റ്-ടു-സ്പീച്ച് ഔട്ട്പുട്ട്"</string> <string name="tts_default_rate_title" msgid="6030550998379310088">"വായന നിരക്ക്"</string> - <string name="tts_default_rate_summary" msgid="4061815292287182801">"വാചകം പറയുന്ന വേഗത"</string> + <string name="tts_default_rate_summary" msgid="4061815292287182801">"ടെക്സ്റ്റ് ചെയ്യൽ പറയുമ്പോഴുടെക്കുന്ന വേഗത"</string> <string name="tts_default_pitch_title" msgid="6135942113172488671">"പിച്ച്"</string> <string name="tts_default_pitch_summary" msgid="1944885882882650009">"സിന്തസൈസ് ചെയ്ത സംസാരത്തിന്റെ സ്വരഭേദത്തെ ബാധിക്കുന്നു"</string> <string name="tts_default_lang_title" msgid="8018087612299820556">"ഭാഷ"</string> @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"എപ്പോഴും വൈഫൈ റോം സ്കാൻ അനുവദിക്കൂ"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"മൊബൈൽ ഡാറ്റ എല്ലായ്പ്പോഴും സജീവം"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"ടെതറിംഗ് ഹാർഡ്വെയർ ത്വരിതപ്പെടുത്തൽ"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"അബ്സൊല്യൂട്ട് വോളിയം പ്രവർത്തനരഹിതമാക്കുക"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"ഇൻ-ബാൻഡ് റിംഗുചെയ്യൽ പ്രവർത്തനക്ഷമമാക്കുക"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP പതിപ്പ്"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"ഈ ക്രമീകരണങ്ങൾ വികസന ഉപയോഗത്തിന് മാത്രമായുള്ളതാണ്. അവ നിങ്ങളുടെ ഉപകരണവും അതിലെ അപ്ലിക്കേഷനുകളും തകരാറിലാക്കുന്നതിനോ തെറ്റായി പ്രവർത്തിക്കുന്നതിനോ ഇടയാക്കാം."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB വഴി ആപ്സ് പരിശോധിച്ചുറപ്പിക്കൂ"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"കേടാക്കുന്ന പ്രവർത്തനരീതിയുള്ള ADB/ADT വഴി ഇൻസ്റ്റാളുചെയ്ത അപ്ലിക്കേഷനുകൾ പരിശോധിക്കുക."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"അസ്വീകാര്യമായ തരത്തിൽ ഉയർന്ന വോളിയമോ ശബ്ദ നിയന്ത്രണത്തിന്റെ അഭാവമോ പോലെ, വിദൂര ഉപകരണങ്ങളുമായി ബന്ധപ്പെട്ട വോളിയം പ്രശ്നങ്ങൾ ഉണ്ടാകുന്ന സാഹചര്യത്തിൽ, Bluetooth അബ്സൊല്യൂട്ട് വോളിയം ഫീച്ചർ പ്രവർത്തനരഹിതമാക്കുന്നു."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ഫോണിലെ റിംഗ്ടോണുകൾ Bluetooth ഹെഡ്സെറ്റുകളിൽ പ്ലേ ചെയ്യാനായി അനുവദിക്കുക"</string> <string name="enable_terminal_title" msgid="95572094356054120">"പ്രാദേശിക ടെർമിനൽ"</string> @@ -261,7 +265,7 @@ <string name="show_touches_summary" msgid="6101183132903926324">"ടാപ്പുകൾക്ക് ദൃശ്യ ഫീഡ്ബാക്ക് കാണിക്കുക"</string> <string name="show_screen_updates" msgid="5470814345876056420">"സർഫേസ് അപ്ഡേറ്റ് കാണിക്കൂ"</string> <string name="show_screen_updates_summary" msgid="2569622766672785529">"മുഴുവൻ വിൻഡോ സർഫേസുകളും അപ്ഡേറ്റുചെയ്തുകഴിയുമ്പോൾ അവ ഫ്ലാഷുചെയ്യുക"</string> - <string name="show_hw_screen_updates" msgid="5036904558145941590">"GPU കാഴ്ച അപ്ഡേറ്റ് കാണിക്കൂ"</string> + <string name="show_hw_screen_updates" msgid="5036904558145941590">"GPU കാഴ്ചയുടെ അപ്ഡേറ്റുകൾ കാണിക്കൂ"</string> <string name="show_hw_screen_updates_summary" msgid="1115593565980196197">"GPU ഉപയോഗിച്ച് വലിക്കുമ്പോൾ വിൻഡോകൾക്കുള്ളിൽ കാഴ്ചകൾ ഫ്ലാഷുചെയ്യുക"</string> <string name="show_hw_layers_updates" msgid="5645728765605699821">"ഹാർഡ്വെയർ ലേയർ അപ്ഡേറ്റ് കാണിക്കൂ"</string> <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ഹാർഡ്വെയർ ലേയറുകളുടെ അപ്ഡേറ്റുകൾ പൂർത്തിയാകുമ്പോൾ അവ പച്ച നിറത്തിൽ പ്രകാശിപ്പിക്കുക"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> ശേഷിക്കുന്നു"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - ഫുൾ ചാർജാകാൻ <xliff:g id="TIME">^2</xliff:g>"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"അജ്ഞാതം"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"ചാർജ്ജുചെയ്യുന്നു"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ചാർജ് ചെയ്യുന്നു"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"ചാർജ്ജുചെയ്യുന്നില്ല"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"പ്ലഗ് ഇൻ ചെയ്തു, ഇപ്പോൾ ചാർജ് ചെയ്യാനാവില്ല"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"നിറഞ്ഞു"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"അഡ്മിൻ നിയന്ത്രിക്കുന്നത്"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"അഡ്മിൻ പ്രവർത്തനക്ഷമമാക്കി"</string> diff --git a/packages/SettingsLib/res/values-mn/arrays.xml b/packages/SettingsLib/res/values-mn/arrays.xml index d6a0772d36db..01c36bfd1842 100644 --- a/packages/SettingsLib/res/values-mn/arrays.xml +++ b/packages/SettingsLib/res/values-mn/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Нэмэлт кодлогчийг идэвхжүүлэх"</item> - <item msgid="3304843301758635896">"Нэмэлт кодлогчийг идэвхгүй болгох"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Нэмэлт кодлогчийг идэвхжүүлэх"</item> - <item msgid="741805482892725657">"Нэмэлт кодлогчийг идэвхгүй болгох"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item> <item msgid="8895532488906185219">"44.1 кГц"</item> diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml index 8f4b695bf83d..4da11e564f3b 100644 --- a/packages/SettingsLib/res/values-mn/strings.xml +++ b/packages/SettingsLib/res/values-mn/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi Роум сканыг байнга зөвшөөрөх"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Мобайл дата байнга идэвхтэй"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Модем болгох хардвер хурдасгуур"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Үнэмлэхүй дууны түвшинг идэвхгүй болгох"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Сүлжээний хонхны аяыг идэвхжүүлэх"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP хувилбар"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Эдгээр тохиргоо нь зөвхөн хөгжүүлэлтэд ашиглах зорилготой. Эдгээр нь таны төхөөрөмж буюу түүн дээрх аппликейшнүүдийг эвдрэх, буруу ажиллах шалтгаан нь болж болно."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Апп-г USB-р тулгах"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT-р суулгасан апп-уудыг хорлонтой авиртай эсэхийг шалгах."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Хэт чанга дуугаралт эсвэл муу тохиргоо зэрэг алсын зайн төхөөрөмжийн дуугаралттай холбоотой асуудлын үед Bluetooth-ийн үнэмлэхүй дууны түвшинг идэвхгүй болго."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Утасны хонхны аяыг Bluetooth чихэвчээр тоглуулахыг зөвшөөрөх"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Локал терминал"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> үлдсэн"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"бүрэн цэнэглэх хүртэл <xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Тодорхойгүй"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Цэнэглэж байна"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"цэнэглэж байна"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Цэнэглэхгүй байна"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Залгаастай тул одоо цэнэглэх боломжгүй"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Дүүрэн"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Админ удирдсан"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Админ идэвхжүүлсэн"</string> diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml index 5c7b15fa61fa..c983cfd2ef3e 100644 --- a/packages/SettingsLib/res/values-mr/arrays.xml +++ b/packages/SettingsLib/res/values-mr/arrays.xml @@ -25,7 +25,7 @@ <item msgid="8934131797783724664">"स्कॅन करत आहे…"</item> <item msgid="8513729475867537913">"कनेक्ट करत आहे..."</item> <item msgid="515055375277271756">"प्रमाणीकरण करत आहे…"</item> - <item msgid="1943354004029184381">"IP पत्ता प्राप्त करत आहे…"</item> + <item msgid="1943354004029184381">"IP पत्ता मिळवत आहे…"</item> <item msgid="4221763391123233270">"कनेक्ट केले"</item> <item msgid="624838831631122137">"निलंबित"</item> <item msgid="7979680559596111948">"डिस्कनेक्ट करत आहे..."</item> @@ -39,7 +39,7 @@ <item msgid="8878186979715711006">"स्कॅन करत आहे…"</item> <item msgid="355508996603873860">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> वर कनेक्ट करत आहे…"</item> <item msgid="554971459996405634">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> सह प्रमाणीकरण करत आहे…"</item> - <item msgid="7928343808033020343">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> वरून IP पत्ता प्राप्त करत आहे…"</item> + <item msgid="7928343808033020343">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> वरून IP पत्ता मिळवत आहे…"</item> <item msgid="8937994881315223448">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> वर कनेक्ट केले आहे"</item> <item msgid="1330262655415760617">"निलंबित"</item> <item msgid="7698638434317271902">"<xliff:g id="NETWORK_NAME">%1$s</xliff:g> वरून डिस्कनेक्ट करत आहे…"</item> @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"प्रणाली निवड वापरा (डीफॉल्ट)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"पर्यायी कोडेक सक्षम करा"</item> - <item msgid="3304843301758635896">"पर्यायी कोडेक अक्षम करा"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"प्रणाली निवड वापरा (डीफॉल्ट)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"पर्यायी कोडेक सक्षम करा"</item> - <item msgid="741805482892725657">"पर्यायी कोडेक अक्षम करा"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"प्रणाली निवड वापरा (डीफॉल्ट)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> @@ -104,15 +88,15 @@ </string-array> <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles"> <item msgid="2684127272582591429">"प्रणाली निवड वापरा (डीफॉल्ट)"</item> - <item msgid="5618929009984956469">"16 बिट/नमुना"</item> - <item msgid="3412640499234627248">"24 बिट/नमुना"</item> - <item msgid="121583001492929387">"32 बिट/नमुना"</item> + <item msgid="5618929009984956469">"16 बिट/पॅटर्न"</item> + <item msgid="3412640499234627248">"24 बिट/पॅटर्न"</item> + <item msgid="121583001492929387">"32 बिट/पॅटर्न"</item> </string-array> <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries"> <item msgid="1081159789834584363">"प्रणाली निवड वापरा (डीफॉल्ट)"</item> - <item msgid="4726688794884191540">"16 बिट/नमुना"</item> - <item msgid="305344756485516870">"24 बिट/नमुना"</item> - <item msgid="244568657919675099">"32 बिट/नमुना"</item> + <item msgid="4726688794884191540">"16 बिट/पॅटर्न"</item> + <item msgid="305344756485516870">"24 बिट/पॅटर्न"</item> + <item msgid="244568657919675099">"32 बिट/पॅटर्न"</item> </string-array> <string-array name="bluetooth_a2dp_codec_channel_mode_titles"> <item msgid="5226878858503393706">"प्रणाली निवड वापरा (डीफॉल्ट)"</item> @@ -128,13 +112,13 @@ <item msgid="7158319962230727476">"ऑडिओ गुणवत्ता (990kbps/909kbps) साठी ऑप्टिमाइझ केली"</item> <item msgid="2921767058740704969">"संतुलित ऑडिओ आणि कनेक्शन गुणवत्ता (660kbps/606kbps)"</item> <item msgid="8860982705384396512">"कनेक्शन गुणवत्ता (330kbps/303kbps) साठी ऑप्टिमाइझ केली"</item> - <item msgid="4414060457677684127">"सर्वोत्तम प्रयत्न (अनुकूल बिट दर)"</item> + <item msgid="4414060457677684127">"सर्वोत्तम प्रयत्न (अनुकूल बिट रेट)"</item> </string-array> <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries"> <item msgid="6398189564246596868">"ऑडिओ गुणवत्तेसाठी ऑप्टिमाइझ केले"</item> <item msgid="4327143584633311908">"संतुलित ऑडिओ आणि कनेक्शन गुणवत्ता"</item> <item msgid="4681409244565426925">"कनेक्शन गुणवत्तेसाठी ऑप्टिमाइझ केले"</item> - <item msgid="364670732877872677">"सर्वोत्तम प्रयत्न (अनुकूल बिट दर)"</item> + <item msgid="364670732877872677">"सर्वोत्तम प्रयत्न (अनुकूल बिट रेट)"</item> </string-array> <string-array name="select_logd_size_titles"> <item msgid="8665206199209698501">"बंद"</item> @@ -220,7 +204,7 @@ <string-array name="show_non_rect_clip_entries"> <item msgid="993742912147090253">"बंद"</item> <item msgid="675719912558941285">"निळ्या रंगात आयताकार नसलेला क्लिप प्रांत रेखांकित करा"</item> - <item msgid="1064373276095698656">"चाचणी केलेले रेखांकित आदेश हिरव्या रंगामध्ये हायलाइट करा"</item> + <item msgid="1064373276095698656">"चाचणी केलेल्या रेखांकित कमांड हिरव्या रंगामध्ये हायलाइट करा"</item> </string-array> <string-array name="track_frame_time_entries"> <item msgid="2193584639058893150">"बंद"</item> diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml index 4f7cff752c6b..7cb750983612 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -33,7 +33,7 @@ <string name="wifi_check_password_try_again" msgid="516958988102584767">"पासवर्ड तपासा आणि पुन्हा प्रयत्न करा"</string> <string name="wifi_not_in_range" msgid="1136191511238508967">"परिक्षेत्रामध्ये नाही"</string> <string name="wifi_no_internet_no_reconnect" msgid="5724903347310541706">"स्वयंचलितपणे कनेक्ट करणार नाही"</string> - <string name="wifi_no_internet" msgid="3880396223819116454">"इंटरनेट प्रवेश नाही"</string> + <string name="wifi_no_internet" msgid="3880396223819116454">"इंटरनेट अॅक्सेस नाही"</string> <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> द्वारे जतन केले"</string> <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s द्वारे स्वयंचलितपणे कनेक्ट केले"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"नेटवर्क रेटिंग प्रदात्याद्वारे स्वयंचलितपणे कनेक्ट केले"</string> @@ -66,11 +66,11 @@ <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"मीडिया ऑडिओ"</string> <string name="bluetooth_profile_headset" msgid="7815495680863246034">"फोन कॉल"</string> <string name="bluetooth_profile_opp" msgid="9168139293654233697">"फाइल स्थानांतरण"</string> - <string name="bluetooth_profile_hid" msgid="3680729023366986480">"इनपुट डिव्हाइस"</string> - <string name="bluetooth_profile_pan" msgid="3391606497945147673">"इंटरनेट प्रवेश"</string> + <string name="bluetooth_profile_hid" msgid="3680729023366986480">"इनपुट डीव्हाइस"</string> + <string name="bluetooth_profile_pan" msgid="3391606497945147673">"इंटरनेट अॅक्सेस"</string> <string name="bluetooth_profile_pbap" msgid="5372051906968576809">"संपर्क सामायिकरण"</string> <string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"संपर्क सामायिकरणासाठी वापरा"</string> - <string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"इंटरनेट कनेक्शन सामायिकरण"</string> + <string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"इंटरनेट कनेक्शन शेअररण"</string> <string name="bluetooth_profile_map" msgid="1019763341565580450">"मजकूर संदेश"</string> <string name="bluetooth_profile_sap" msgid="5764222021851283125">"सिम प्रवेश"</string> <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ऑडिओ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string> @@ -82,23 +82,23 @@ <string name="bluetooth_sap_profile_summary_connected" msgid="8561765057453083838">"SAP शी कनेक्ट केले"</string> <string name="bluetooth_opp_profile_summary_not_connected" msgid="1267091356089086285">"फाइल स्थानांतर सर्व्हरशी कनेक्ट केले नाही"</string> <string name="bluetooth_hid_profile_summary_connected" msgid="3381760054215168689">"इनपुट डिव्हाइसवर कनेक्ट केले"</string> - <string name="bluetooth_pan_user_profile_summary_connected" msgid="4602294638909590612">"इंटरनेट प्रवेशासाठी डिव्हाइसवर कनेक्ट केले"</string> - <string name="bluetooth_pan_nap_profile_summary_connected" msgid="1561383706411975199">"डिव्हाइससह स्थानिक इंटरनेट कनेक्शन सामायिक करत आहे"</string> - <string name="bluetooth_pan_profile_summary_use_for" msgid="5664884523822068653">"इंटरनेट प्रवेशासाठी वापरा"</string> + <string name="bluetooth_pan_user_profile_summary_connected" msgid="4602294638909590612">"इंटरनेट अॅक्सेससाठी डीव्हाइसवर कनेक्ट केले"</string> + <string name="bluetooth_pan_nap_profile_summary_connected" msgid="1561383706411975199">"डीव्हाइससह स्थानिक इंटरनेट कनेक्शन शेअर करत आहे"</string> + <string name="bluetooth_pan_profile_summary_use_for" msgid="5664884523822068653">"इंटरनेट अॅक्सेससाठी वापरा"</string> <string name="bluetooth_map_profile_summary_use_for" msgid="5154200119919927434">"नकाशासाठी वापरा"</string> <string name="bluetooth_sap_profile_summary_use_for" msgid="7085362712786907993">"SIM प्रवेशासाठी वापरा"</string> <string name="bluetooth_a2dp_profile_summary_use_for" msgid="4630849022250168427">"मीडिया ऑडिओसाठी वापरा"</string> <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"फोन ऑडिओसाठी वापरा"</string> <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"फाईल स्थानांतरणासाठी वापरा"</string> <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"इनपुट साठी वापरा"</string> - <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"जोडा"</string> - <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"जोडा"</string> + <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"पेअर करा"</string> + <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"पेअर करा"</string> <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"रद्द करा"</string> - <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"कनेक्ट केल्यावर जोडणी आपले संपर्क आणि कॉल इतिहास यावरील प्रवेशास मंजूरी देते."</string> + <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"कनेक्ट केल्यावर पेअरींग तुमचे संपर्क आणि कॉल इतिहास यामध्ये अॅक्सेस देते."</string> <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> शी जोडू शकलो नाही."</string> <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"अयोग्य पिन किंवा पासकीमुळे <xliff:g id="DEVICE_NAME">%1$s</xliff:g> सह जोडू शकलो नाही."</string> <string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> शी संप्रेषण करू शकत नाही."</string> - <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> द्वारे जोडणी नाकारली."</string> + <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> द्वारे पेअरींग नाकारले."</string> <string name="accessibility_wifi_off" msgid="1166761729660614716">"वाय फाय बंद."</string> <string name="accessibility_no_wifi" msgid="8834610636137374508">"वाय फाय डिस्कनेक्ट झाले."</string> <string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"वाय फाय एक बार."</string> @@ -112,8 +112,8 @@ <string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"काढलेले अॅप्स आणि वापरकर्ते"</string> <string name="tether_settings_title_usb" msgid="6688416425801386511">"USB टेदरिंग"</string> <string name="tether_settings_title_wifi" msgid="3277144155960302049">"पोर्टेबल हॉटस्पॉट"</string> - <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ब्लूटुथ टेदरिंग"</string> - <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"टिथरिंग"</string> + <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ब्लूटूथ टेदरिंग"</string> + <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"टेदरिंग"</string> <string name="tether_settings_title_all" msgid="8356136101061143841">"टेदरिंग आणि पोर्टेबल हॉटस्पॉट"</string> <string name="managed_user_title" msgid="8109605045406748842">"सर्व कार्य अॅप्स"</string> <string name="user_guest" msgid="8475274842845401871">"अतिथी"</string> @@ -133,8 +133,8 @@ <string name="tts_default_lang_summary" msgid="5219362163902707785">"बोललेल्या मजकुरासाठी भाषा-विशिष्ट आवाज सेट करते"</string> <string name="tts_play_example_title" msgid="7094780383253097230">"उदाहरण ऐका"</string> <string name="tts_play_example_summary" msgid="8029071615047894486">"उच्चार संश्लेषणाचे एक छोटेसे प्रात्यक्षिक प्ले करा"</string> - <string name="tts_install_data_title" msgid="4264378440508149986">"व्हॉइस डेटा स्थापित करा"</string> - <string name="tts_install_data_summary" msgid="5742135732511822589">"उच्चार संश्लेषणासाठी आवश्यक आवाज डेटा स्थापित करा"</string> + <string name="tts_install_data_title" msgid="4264378440508149986">"व्हॉइस डेटा इंस्टॉल करा"</string> + <string name="tts_install_data_summary" msgid="5742135732511822589">"उच्चार संश्लेषणासाठी आवश्यक आवाज डेटा इंस्टॉल करा"</string> <string name="tts_engine_security_warning" msgid="8786238102020223650">"हे उच्चार संश्लेषण इंजिन संकेतशब्द आणि क्रेडिट कार्ड नंबर यासारख्या वैयक्तिक मजकुरासह, बोलला जाणारा सर्व मजकूर संकलित करण्यात सक्षम होऊ शकते. हे <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> इंजिनवरून येते. या उच्चार संश्लेषण इंजिनचा वापर सक्षम करायचा?"</string> <string name="tts_engine_network_required" msgid="1190837151485314743">"या भाषेस टेक्स्ट टू स्पीचसाठी एका नेटवर्क कनेक्शनची आवश्यकता आहे."</string> <string name="tts_default_sample_string" msgid="4040835213373086322">"हे उच्चार संश्लेषणाचे एक उदाहरण आहे"</string> @@ -163,54 +163,56 @@ <string name="choose_profile" msgid="6921016979430278661">"प्रोफाइल निवडा"</string> <string name="category_personal" msgid="1299663247844969448">"वैयक्तिक"</string> <string name="category_work" msgid="8699184680584175622">"कार्य"</string> - <string name="development_settings_title" msgid="215179176067683667">"विकासक पर्याय"</string> - <string name="development_settings_enable" msgid="542530994778109538">"विकासक पर्याय सक्षम करा"</string> + <string name="development_settings_title" msgid="215179176067683667">"डेव्हलपर पर्याय"</string> + <string name="development_settings_enable" msgid="542530994778109538">"डेव्हलपर पर्याय सुरू करा"</string> <string name="development_settings_summary" msgid="1815795401632854041">"अॅप विकासासाठी पर्याय सेट करा"</string> - <string name="development_settings_not_available" msgid="4308569041701535607">"या वापरकर्त्यासाठी विकासक पर्याय उपलब्ध नाहीत"</string> + <string name="development_settings_not_available" msgid="4308569041701535607">"या वापरकर्त्यासाठी डेव्हलपर पर्याय उपलब्ध नाहीत"</string> <string name="vpn_settings_not_available" msgid="956841430176985598">"या वापरकर्त्यासाठी VPN सेटिंग्ज उपलब्ध नाहीत"</string> - <string name="tethering_settings_not_available" msgid="6765770438438291012">"या वापरकर्त्यासाठी टिथरिंग सेटिंग्ज उपलब्ध नाहीत"</string> - <string name="apn_settings_not_available" msgid="7873729032165324000">"या वापरकर्त्यासाठी प्रवेश बिंदू नाव सेटिंग्ज उपलब्ध नाहीत"</string> + <string name="tethering_settings_not_available" msgid="6765770438438291012">"या वापरकर्त्यासाठी टेदरिंग सेटिंग्ज उपलब्ध नाहीत"</string> + <string name="apn_settings_not_available" msgid="7873729032165324000">"या वापरकर्त्यासाठी अॅक्सेस बिंदू नाव सेटिंग्ज उपलब्ध नाहीत"</string> <string name="enable_adb" msgid="7982306934419797485">"USB डीबग करणे"</string> <string name="enable_adb_summary" msgid="4881186971746056635">"USB कनेक्ट केलेले असताना डीबग मोड"</string> - <string name="clear_adb_keys" msgid="4038889221503122743">"USB डीबग करणारी प्रमाणिकरणे पुनर्प्राप्त करा"</string> - <string name="bugreport_in_power" msgid="7923901846375587241">"दोष अहवाल शॉर्टकट"</string> - <string name="bugreport_in_power_summary" msgid="1778455732762984579">"दोष अहवाल घेण्यासाठी पॉवर मेनूमध्ये एक बटण दर्शवा"</string> + <string name="clear_adb_keys" msgid="4038889221503122743">"USB डीबग करणारी प्रमाणीकरणे रीव्होक करा"</string> + <string name="bugreport_in_power" msgid="7923901846375587241">"बग रीपोर्ट शॉर्टकट"</string> + <string name="bugreport_in_power_summary" msgid="1778455732762984579">"बग रीपोर्ट घेण्यासाठी पॉवर मेनूमध्ये एक बटण दर्शवा"</string> <string name="keep_screen_on" msgid="1146389631208760344">"सक्रिय रहा"</string> <string name="keep_screen_on_summary" msgid="2173114350754293009">"चार्ज होत असताना स्क्रीन कधीही निष्क्रिय होणार नाही"</string> - <string name="bt_hci_snoop_log" msgid="3340699311158865670">"ब्लूटुथ HCI स्नूप लॉग सक्षम करा"</string> - <string name="bt_hci_snoop_log_summary" msgid="730247028210113851">"सर्व ब्लूटुथ HCI पॅकेट एका फाईलमध्ये कॅप्चर करा"</string> + <string name="bt_hci_snoop_log" msgid="3340699311158865670">"ब्लूटूथ HCI स्नूप लॉग सक्षम करा"</string> + <string name="bt_hci_snoop_log_summary" msgid="730247028210113851">"सर्व ब्लूटूथ HCI पॅकेट एका फाईलमध्ये कॅप्चर करा"</string> <string name="oem_unlock_enable" msgid="6040763321967327691">"OEM अनलॉक करणे"</string> <string name="oem_unlock_enable_summary" msgid="4720281828891618376">"बूटलोडर अनलॉक करण्यासाठी अनुमती द्या"</string> <string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"OEM अनलॉक करण्यास अनुमती द्यायची?"</string> - <string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"चेतावणी: ही सेटिंग चालू असताना या डिव्हाइसवर डिव्हाइस संरक्षण वैशिष्ट्ये कार्य करणार नाहीत."</string> + <string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"चेतावणी: हे सेटिंग चालू असताना या डीव्हाइस वर डीव्हाइस संरक्षण वैशिष्ट्ये काम करणार नाहीत."</string> <string name="mock_location_app" msgid="7966220972812881854">"बनावट स्थान अॅप निवडा"</string> <string name="mock_location_app_not_set" msgid="809543285495344223">"कोणताही बनावट स्थान अॅप सेट केला नाही"</string> <string name="mock_location_app_set" msgid="8966420655295102685">"बनावट स्थान अॅप: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="debug_networking_category" msgid="7044075693643009662">"नेटवर्किंग"</string> - <string name="wifi_display_certification" msgid="8611569543791307533">"वायरलेस प्रदर्शन प्रमाणीकरण"</string> - <string name="wifi_verbose_logging" msgid="4203729756047242344">"वाय-फाय शब्दपाल्हाळ लॉगिंग सक्षम करा"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"मोबाइलकडे सोपवण्यासाठी आक्रमक वाय-फाय"</string> + <string name="wifi_display_certification" msgid="8611569543791307533">"वायरलेस डिस्प्ले प्रमाणीकरण"</string> + <string name="wifi_verbose_logging" msgid="4203729756047242344">"वाय-फाय व्हर्बोझ लॉगिंग सक्षम करा"</string> + <string name="wifi_aggressive_handover" msgid="5309131983693661320">"मोबाइलकडे सोपवण्यासाठी अॅग्रेसिव्ह वाय-फाय"</string> <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"वाय-फाय रोम स्कॅनला नेहमी अनुमती द्या"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"मोबाइल डेटा नेहमी सक्रिय"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"टेदरिंग हार्डवेअर प्रवेग"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"संपूर्ण आवाज अक्षम करा"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"इन-बँड रिंगिंग सक्षम करा"</string> - <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ब्लूटुथ AVRCP आवृत्ती"</string> - <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ब्लूटुथ AVRCP आवृत्ती निवडा"</string> + <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ब्लूटूथ AVRCP आवृत्ती"</string> + <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ब्लूटूथ AVRCP आवृत्ती निवडा"</string> <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ब्लूटूथ ऑडिओ कोडेक"</string> - <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"ब्लूटुथ ऑडिओ कोडेक निवडा"</string> - <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"ब्लूटूथ ऑडिओ नमुना दर"</string> - <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"ब्लूटुथ ऑडिओ कोडेक निवडा:\nनमुना दर"</string> - <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"प्रति नमुना ब्लूटुथ ऑडिओ बिट"</string> - <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"ब्लूटुथ ऑडिओ कोडेक निवडा:\nबिट प्रति नमुना"</string> + <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"ब्लूटूथ ऑडिओ कोडेक निवडा"</string> + <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"ब्लूटूथ ऑडिओ पॅटर्न दर"</string> + <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"ब्लूटूध ऑडिओ कोडेक निवडा:\nपॅटर्न दर"</string> + <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"प्रति पॅटर्न ब्लूटूध ऑडिओ बिट"</string> + <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"ब्लूटूध ऑडिओ कोडेक निवडा:\nबिट प्रति पॅटर्न"</string> <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"ब्लूटूथ ऑडिओ चॅनेल मोड"</string> - <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"ब्लूटुथ ऑडिओ कोडेक निवडा:\nचॅनेल मोड"</string> - <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"ब्लूटुथ ऑडिओ LDAC कोडेक: प्लेबॅक गुणवत्ता"</string> - <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"ब्लूटुथ ऑडिओ LDAC कोडेक निवडा:\nप्लेबॅक गुणवत्ता"</string> - <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"धारावाहिक: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string> - <string name="wifi_display_certification_summary" msgid="1155182309166746973">"वायरलेस प्रदर्शन प्रमाणिकरणासाठी पर्याय दर्शवा"</string> - <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"वाय-फाय लॉगिंग स्तर वाढवा, वाय-फाय निवडकामध्ये प्रति SSID RSSI दर्शवा"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"सक्षम केले असताना, वाय-फाय सिग्नल कमी असताना, मोबाइलकडे डेटा कनेक्शन सोपवण्यासाठी वाय-फाय अधिक आक्रमक असेल."</string> + <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"ब्लूटूथ ऑडिओ कोडेक निवडा:\nचॅनेल मोड"</string> + <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"ब्लूटूथ ऑडिओ LDAC कोडेक: प्लेबॅक गुणवत्ता"</string> + <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"ब्लूटूथ ऑडिओ LDAC कोडेक निवडा:\nप्लेबॅक गुणवत्ता"</string> + <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"स्ट्रीमिंग: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string> + <string name="wifi_display_certification_summary" msgid="1155182309166746973">"वायरलेस डिस्प्ले प्रमाणिकरणाचे पर्याय दाखवा"</string> + <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"वाय-फाय लॉगिंग स्तर वाढवा, वाय-फाय सिलेक्टरमध्ये प्रति SSID RSSI दर्शवा"</string> + <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"सक्षम केले असताना, वाय-फाय सिग्नल कमी असताना, मोबाइलकडे डेटा कनेक्शन सोपवण्यासाठी वाय-फाय अधिक अॅग्रेसिव्ह असेल."</string> <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"वाय-फाय रोम स्कॅनला इंटरफेसवर उपस्थित असलेल्या रहदारी डेटाच्या प्रमाणावर आधारित अनुमती द्या/अनुमती देऊ नका"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"लॉगर बफर आकार"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"प्रति लॉग बफर लॉगर आकार निवडा"</string> @@ -223,29 +225,31 @@ <string name="allow_mock_location" msgid="2787962564578664888">"बनावट स्थानांना अनुमती द्या"</string> <string name="allow_mock_location_summary" msgid="317615105156345626">"बनावट स्थानांना अनुमती द्या"</string> <string name="debug_view_attributes" msgid="6485448367803310384">"दृश्य विशेषता तपासणी सक्षम करा"</string> - <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"जरी वाय-फाय सक्रिय असले तरीही, नेहमी मोबाईल डेटा सक्रिय ठेवा (जलद नेटवर्क स्विच करण्यासाठी)."</string> + <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"जरी वाय-फाय चालू असले तरीही, मोबाईल डेटा नेहमी चालू ठेवा (नेटवर्क जलदरीत्या स्विच करण्यासाठी)."</string> <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"उपलब्ध असल्यास टेदरिंग हार्डवेअर प्रवेग वापरा"</string> <string name="adb_warning_title" msgid="6234463310896563253">"USB डीबग करण्यास अनुमती द्यायची?"</string> - <string name="adb_warning_message" msgid="7316799925425402244">"USB डीबग करण्याचा हेतू फक्त विकासाच्या उद्देशांसाठी आहे. याचा वापर आपला संगणक आणि आपले डिव्हाइस यांच्या दरम्यान डेटा कॉपी करण्यासाठी करा, सूचनेशिवाय आपल्या डिव्हाइसवर अॅप्स स्थापित करा आणि लॉग डेटा वाचा."</string> - <string name="adb_keys_warning_message" msgid="5659849457135841625">"आपण पूर्वी प्राधिकृत केलेल्या सर्व संगणकांवरुन USB डीबग करण्यासाठी प्रवेश पुनर्प्राप्त करायचा?"</string> + <string name="adb_warning_message" msgid="7316799925425402244">"USB डीबग करण्याचा हेतू फक्त विकास उद्देशांसाठी आहे. याचा वापर तुमचा कॉंप्युटर आणि तुमचे डीव्हाइस यांच्या दरम्यान डेटा कॉपी करण्यासाठी करा, सूचनेशिवाय तुमच्या डीव्हाइस वर अॅप्स इंस्टॉल करा आणि लॉग डेटा वाचा."</string> + <string name="adb_keys_warning_message" msgid="5659849457135841625">"आपण पूर्वी अॉथोराइझ केलेल्या सर्व संगणकांवरुन USB डीबग करण्यासाठी अॅक्सेस रीव्होक करायचा?"</string> <string name="dev_settings_warning_title" msgid="7244607768088540165">"विकास सेटिंग्जला अनुमती द्यायची?"</string> - <string name="dev_settings_warning_message" msgid="2298337781139097964">"या सेटिंग्जचा हेतू फक्त विकास करण्याच्या वापरासाठी आहे. त्यामुळे आपले डिव्हाइस आणि त्यावरील अनुप्रयोग विघटित होऊ शकतात किंवा गैरवर्तन करू शकतात."</string> - <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB वरील अॅप्स सत्यापित करा"</string> - <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"हानिकारक वर्तनासाठी ADB/ADT द्वारे स्थापित अॅप्स तपासा."</string> - <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"दूरस्थ डिव्हाइसेसमध्ये सहन न होणारा मोठा आवाज किंवा नियंत्रणचा अभाव यासारखी आवाजाची समस्या असल्यास ब्लूटुथ संपूर्ण आवाज वैशिष्ट्य अक्षम करते."</string> - <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"फोनवरील रिंगटोन ब्लूटुथ हेडसेटवर वाजू द्या"</string> + <string name="dev_settings_warning_message" msgid="2298337781139097964">"या सेटिंग्जचा हेतू फक्त विकास वापरासाठी आहे. त्यामुळे तुमचे डीव्हाइस आणि त्यावरील अॅप्लिकेशन ब्रेक होऊ शकतात किंवा नेहमीपेक्षा वेगळे वर्तन करू शकतात."</string> + <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB वर अॅप्स पडताळून पाहा"</string> + <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"हानिकारक वर्तनासाठी ADB/ADT द्वारे इंस्टॉल अॅप्स तपासा."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> + <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"दूरस्थ डीव्हाइसमध्ये सहन न होणारा मोठा आवाज किंवा नियंत्रणचा अभाव यासारखी आवाजाची समस्या असल्यास ब्लूटूथ संपूर्ण आवाज वैशिष्ट्य अक्षम करते."</string> + <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"फोनवरील रिंगटोन ब्लूटूथ हेडसेटवर वाजू द्या"</string> <string name="enable_terminal_title" msgid="95572094356054120">"स्थानिक टर्मिनल"</string> <string name="enable_terminal_summary" msgid="67667852659359206">"स्थानिक शेल प्रवेश देणारा टर्मिनल अॅप सक्षम करा"</string> <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP तपासणी"</string> <string name="hdcp_checking_dialog_title" msgid="5141305530923283">"HDCP तपासणी वर्तन सेट करा"</string> <string name="debug_debugging_category" msgid="6781250159513471316">"डीबग करणे"</string> <string name="debug_app" msgid="8349591734751384446">"डीबग अॅप निवडा"</string> - <string name="debug_app_not_set" msgid="718752499586403499">"कोणताही डीबग अनुप्रयोग सेट नाही"</string> - <string name="debug_app_set" msgid="2063077997870280017">"अनुप्रयोग डीबग करीत आहे: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> - <string name="select_application" msgid="5156029161289091703">"अनुप्रयोग निवडा"</string> + <string name="debug_app_not_set" msgid="718752499586403499">"कोणतेही डीबग अॅप्लिकेशन सेट नाही"</string> + <string name="debug_app_set" msgid="2063077997870280017">"अॅप्लिकेशन डीबग करीत आहे: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="select_application" msgid="5156029161289091703">"अॅप्लिकेशन निवडा"</string> <string name="no_application" msgid="2813387563129153880">"काहीही नाही"</string> <string name="wait_for_debugger" msgid="1202370874528893091">"डीबगरची प्रतीक्षा करा"</string> - <string name="wait_for_debugger_summary" msgid="1766918303462746804">"डीबग केलेला अनुप्रयोग अंमलात आणण्यापूर्वी डीबगर संलग्न करण्याची प्रतीक्षा करतो"</string> + <string name="wait_for_debugger_summary" msgid="1766918303462746804">"डीबग केलेले अॅप्लिकेशन अंमलात आणण्यापूर्वी डीबगर संलग्न करण्याची प्रतीक्षा करतो"</string> <string name="telephony_monitor_switch" msgid="1764958220062121194">"टेलिफोनी मॉनिटर"</string> <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"टेलिफोनी/मोडेमच्या कार्यक्षमतेत समस्या आढळल्यावर टेलिफोनी मॉनिटर लॉग्ज गोळा करेल आणि दोष फाइल करण्यासाठी वापरकर्त्याला सूचनेचे संकेत देईल"</string> <string name="debug_input_category" msgid="1811069939601180246">"इनपुट"</string> @@ -256,18 +260,18 @@ <string name="strict_mode" msgid="1938795874357830695">"कठोर मोड सक्षम"</string> <string name="strict_mode_summary" msgid="142834318897332338">"मुख्य थ्रेडवर अॅप्स मोठी कार्ये करतात तेव्हा स्क्रीन फ्लॅश करा"</string> <string name="pointer_location" msgid="6084434787496938001">"पॉइंटर स्थान"</string> - <string name="pointer_location_summary" msgid="840819275172753713">"वर्तमान स्पर्श डेटा दर्शविणारे स्क्रीन आच्छादन"</string> + <string name="pointer_location_summary" msgid="840819275172753713">"वर्तमान स्पर्श डेटा दर्शविणारे स्क्रीन ओव्हरले"</string> <string name="show_touches" msgid="2642976305235070316">"टॅप दर्शवा"</string> <string name="show_touches_summary" msgid="6101183132903926324">"टॅपसाठी दृश्यमान अभिप्राय दर्शवा"</string> - <string name="show_screen_updates" msgid="5470814345876056420">"पृष्ठभाग अद्यतने दर्शवा"</string> + <string name="show_screen_updates" msgid="5470814345876056420">"पृष्ठभाग अपडेट दर्शवा"</string> <string name="show_screen_updates_summary" msgid="2569622766672785529">"संपूर्ण विंडो पृष्ठभाग अद्ययावत होतात तेव्हा ते फ्लॅश करा"</string> - <string name="show_hw_screen_updates" msgid="5036904558145941590">"GPU दृश्य अद्यतने दर्शवा"</string> + <string name="show_hw_screen_updates" msgid="5036904558145941590">"GPU दृश्य अपडेट दर्शवा"</string> <string name="show_hw_screen_updates_summary" msgid="1115593565980196197">"GPU सह रेखांकित करताना विंडोच्या आतील दृश्ये फ्लॅश करा"</string> - <string name="show_hw_layers_updates" msgid="5645728765605699821">"हार्डवेअर स्तर अद्यतने दर्शवा"</string> + <string name="show_hw_layers_updates" msgid="5645728765605699821">"हार्डवेअर स्तर अपडेट दर्शवा"</string> <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"हार्डवेअर स्तर अद्ययावत झाल्यावर ते हिरव्या रंगात फ्लॅश करा"</string> - <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU अधोरेखांकित डीबग करा"</string> + <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ओव्हरड्रॉ डीबग करा"</string> <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU प्रदाता सेट करा"</string> - <string name="disable_overlays" msgid="2074488440505934665">"HW आच्छादने अक्षम करा"</string> + <string name="disable_overlays" msgid="2074488440505934665">"HW ओव्हरले अक्षम करा"</string> <string name="disable_overlays_summary" msgid="3578941133710758592">"स्क्रीन तयार करण्यासाठी नेहमी GPU वापरा"</string> <string name="simulate_color_space" msgid="6745847141353345872">"रंग स्थानाची बतावणी करा"</string> <string name="enable_opengl_traces_title" msgid="6790444011053219871">"OpenGL ट्रेस सक्षम करा"</string> @@ -288,8 +292,8 @@ <string name="animator_duration_scale_title" msgid="3406722410819934083">"अॅनिमेटर कालावधी स्केल"</string> <string name="overlay_display_devices_title" msgid="5364176287998398539">"दुय्यम प्रदर्शनांची बतावणी करा"</string> <string name="debug_applications_category" msgid="4206913653849771549">"अॅप्स"</string> - <string name="immediately_destroy_activities" msgid="1579659389568133959">"क्रियाकलाप ठेवू नका"</string> - <string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"वापरकर्त्याने प्रत्येक क्रियाकलाप सोडताच तो नष्ट करा"</string> + <string name="immediately_destroy_activities" msgid="1579659389568133959">"अॅक्टिव्हिटी ठेवू नका"</string> + <string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"वापरकर्त्याने प्रत्येक अॅक्टिव्हिटी सोडताच ती नष्ट करा"</string> <string name="app_process_limit_title" msgid="4280600650253107163">"पार्श्वभूमी प्रक्रिया मर्यादा"</string> <string name="show_all_anrs" msgid="28462979638729082">"सर्व ANR दर्शवा"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"पार्श्वभूमी अॅप्ससाठी अॅप प्रतिसाद देत नाही संवाद दर्शवा"</string> @@ -304,9 +308,9 @@ <string name="local_backup_password_title" msgid="3860471654439418822">"डेस्कटॉप बॅकअप संकेतशब्द"</string> <string name="local_backup_password_summary_none" msgid="6951095485537767956">"डेस्कटॉप पूर्ण बॅक अप सध्या संरक्षित नाहीत"</string> <string name="local_backup_password_summary_change" msgid="5376206246809190364">"डेस्कटॉपच्या पूर्ण बॅकअपसाठी असलेला संकेतशब्द बदलण्यासाठी किंवा काढण्यासाठी टॅप करा"</string> - <string name="local_backup_password_toast_success" msgid="582016086228434290">"नवीन बॅक अप संकेतशब्द सेट झाला"</string> + <string name="local_backup_password_toast_success" msgid="582016086228434290">"नवीन बॅक अप पासवर्ड सेट झाला"</string> <string name="local_backup_password_toast_confirmation_mismatch" msgid="7805892532752708288">"नवीन संकेतशब्द आणि पुष्टीकरण जुळत नाही"</string> - <string name="local_backup_password_toast_validation_failure" msgid="5646377234895626531">"बॅक अप संकेतशब्द सेट करणे अयशस्वी"</string> + <string name="local_backup_password_toast_validation_failure" msgid="5646377234895626531">"बॅक अप पासवर्ड सेट करणे अयशस्वी"</string> <string-array name="color_mode_names"> <item msgid="2425514299220523812">"सशक्त (डीफॉल्ट)"</item> <item msgid="8446070607501413455">"नैसर्गिक"</item> @@ -327,7 +331,7 @@ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"ही निवड यापुढे वैध असणार नाही. पुन्हा प्रयत्न करा."</string> <string name="convert_to_file_encryption" msgid="3060156730651061223">"फाईल कूटबद्धीकरणावर रूपांतरित करा"</string> <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"रूपांतरित करा..."</string> - <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"फाईल आधीपासून कूटबद्ध केली"</string> + <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"फाईल आधीपासून एंक्रिप्ट होती"</string> <string name="title_convert_fbe" msgid="1263622876196444453">"फाईल आधारित कूटबद्धीकरणावर रूपांतरित करणे"</string> <string name="convert_to_fbe_warning" msgid="6139067817148865527">"फाईल आधारित कूटबद्धीकरणावर डेटा विभाजक रूपांतरित करा.\n !!चेतावणी!! हे आपल्या सर्व डेटास मिटवेल.\n हे वैशिष्ट्य अल्फा आहे आणि कदाचित योग्यरित्या कार्य करू शकत नाही.\n सुरु ठेवण्यासाठी \'पुसा आणि रूपांतरित करा...\' दाबा."</string> <string name="button_convert_fbe" msgid="5152671181309826405">"पुसा आणि रुपांतरित करा..."</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> शिल्लक"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - पूर्णपणे चार्ज होण्यात <xliff:g id="TIME">^2</xliff:g>"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज होत आहे"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"चार्ज होत आहे"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"चार्ज होत नाही"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"प्लग इन केलेले आहे, आता चार्ज करू शकत नाही"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"पूर्ण"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"प्रशासकाने नियंत्रित केलेले"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"प्रशासकाने सक्षम केलेले"</string> @@ -365,8 +367,8 @@ <string name="disabled" msgid="9206776641295849915">"अक्षम"</string> <string name="external_source_trusted" msgid="2707996266575928037">"अनुमती आहे"</string> <string name="external_source_untrusted" msgid="2677442511837596726">"अनुमती नाही"</string> - <string name="install_other_apps" msgid="6986686991775883017">"अज्ञात अॅप्स स्थापित करा"</string> - <string name="home" msgid="3256884684164448244">"सेटिंग्ज मुख्यपृष्ठ"</string> + <string name="install_other_apps" msgid="6986686991775883017">"अज्ञात अॅप्स इंस्टॉल करा"</string> + <string name="home" msgid="3256884684164448244">"सेटिंग्ज होम"</string> <string-array name="battery_labels"> <item msgid="8494684293649631252">"0%"</item> <item msgid="8934126114226089439">"50%"</item> @@ -382,12 +384,12 @@ <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"सानुकूल करा (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string> <string name="help_feedback_label" msgid="6815040660801785649">"मदत आणि अभिप्राय"</string> <string name="content_description_menu_button" msgid="8182594799812351266">"मेनू"</string> - <string name="retail_demo_reset_message" msgid="118771671364131297">"डेमो मोडमध्ये फॅक्टरी रीसेट करण्यासाठी संकेतशब्द प्रविष्ट करा"</string> + <string name="retail_demo_reset_message" msgid="118771671364131297">"डेमो मोडमध्ये फॅक्टरी रीसेट करण्यासाठी पासवर्ड प्रविष्ट करा"</string> <string name="retail_demo_reset_next" msgid="8356731459226304963">"पुढील"</string> <string name="retail_demo_reset_title" msgid="696589204029930100">"संकेतशब्द आवश्यक"</string> <string name="active_input_method_subtypes" msgid="3596398805424733238">"सक्रिय इनपुट पद्धती"</string> <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"सिस्टीम भाषा वापरा"</string> <string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> साठी सेटिंग्ज उघडण्यात अयशस्वी"</string> <string name="ime_security_warning" msgid="4135828934735934248">"ही इनपुट पद्धत संकेतशब्द आणि क्रेडिट कार्ड नंबर यासह, आपण टाइप करता तो सर्व मजकूर संकलित करण्यात सक्षम होऊ शकते. ही <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> अॅपवरून येते. ही इनपुट पद्धत वापरायची?"</string> - <string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"टीप: रीबूट केल्यानंतर, आपण आपला फोन अनलॉक करे पर्यंत हा अॅप प्रारंभ होऊ शकत नाही"</string> + <string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"टीप: रीबूट केल्यानंतर, तुम्ही आपला फोन अनलॉक करे पर्यंत हे अॅप सुरू होऊ शकत नाही"</string> </resources> diff --git a/packages/SettingsLib/res/values-ms/arrays.xml b/packages/SettingsLib/res/values-ms/arrays.xml index bab4642fc1a4..9338c02f3c8e 100644 --- a/packages/SettingsLib/res/values-ms/arrays.xml +++ b/packages/SettingsLib/res/values-ms/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Gunakan Pilihan Sistem (Lalai)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Dayakan Codec Pilihan"</item> - <item msgid="3304843301758635896">"Lumpuhkan Codec Pilihan"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Gunakan Pilihan Sistem (Lalai)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Dayakan Codec Pilihan"</item> - <item msgid="741805482892725657">"Lumpuhkan Codec Pilihan"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Gunakan Pilihan Sistem (Lalai)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml index eef4dd5d7688..e3a86f7bbb66 100644 --- a/packages/SettingsLib/res/values-ms/strings.xml +++ b/packages/SettingsLib/res/values-ms/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sentiasa benarkan Imbasan Perayauan Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Data mudah alih sentiasa aktif"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Pecutan perkakasan penambatan"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Lumpuhkan kelantangan mutlak"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Dayakan dering dalam jalur"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versi AVRCP Bluetooth"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Tetapan ini adalah untuk penggunaan pembangunan sahaja. Peranti dan aplikasi yang terdapat padanya boleh rosak atau tidak berfungsi dengan betul."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Sahkan apl melalui USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Semak apl yang dipasang melalui ADB/ADT untuk tingkah laku yang berbahaya."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Lumpuhkan ciri kelantangan mutlak Bluetooth dalam kes isu kelantangan menggunakan peranti kawalan jauh seperti kelantangan yang sangat kuat atau tidak dapat mengawal."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Benarkan nada dering pada telefon dimainkan pada set kepala Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Terminal setempat"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> lagi"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> sehingga dicas penuh"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Tidak diketahui"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Mengecas"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"mengecas"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Tidak mengecas"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Dipalamkan, tidak boleh mengecas sekarang"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Penuh"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Dikawal oleh pentadbir"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Didayakan oleh pentadbir"</string> diff --git a/packages/SettingsLib/res/values-my/arrays.xml b/packages/SettingsLib/res/values-my/arrays.xml index 97a9c53a70ff..750c0420db6f 100644 --- a/packages/SettingsLib/res/values-my/arrays.xml +++ b/packages/SettingsLib/res/values-my/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> အသံ"</item> + <item msgid="2091430979086738145">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> အသံ"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"စိတ်ကြိုက်ထည့်သွင်းနိုင်သော ကိုးဒက်ခ်များကို ဖွင့်ပါ"</item> <item msgid="3304843301758635896">"စိတ်ကြိုက်ထည့်သွင်းနိုင်သော ကိုးဒက်ခ်များကို ပိတ်ပါ"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> အသံ"</item> + <item msgid="298198075927343893">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> အသံ"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"စိတ်ကြိုက်ထည့်သွင်းနိုင်သော ကိုးဒက်ခ်များကို ဖွင့်ပါ"</item> <item msgid="741805482892725657">"စိတ်ကြိုက်ထည့်သွင်းနိုင်သော ကိုးဒက်ခ်များကို ပိတ်ပါ"</item> diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml index 6aad3aabf651..ebbb7df70803 100644 --- a/packages/SettingsLib/res/values-my/strings.xml +++ b/packages/SettingsLib/res/values-my/strings.xml @@ -45,7 +45,7 @@ <string name="available_via_carrier" msgid="1469036129740799053">"%1$s မှတစ်ဆင့် ရနိုင်သည်"</string> <string name="speed_label_very_slow" msgid="1867055264243608530">"အလွန်နှေး"</string> <string name="speed_label_slow" msgid="813109590815810235">"နှေး"</string> - <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> + <string name="speed_label_okay" msgid="2331665440671174858">"အိုကေ"</string> <string name="speed_label_medium" msgid="3175763313268941953">"အတော်အသင့်"</string> <string name="speed_label_fast" msgid="7715732164050975057">"မြန်"</string> <string name="speed_label_very_fast" msgid="2265363430784523409">"အလွန်မြန်"</string> @@ -119,7 +119,7 @@ <string name="user_guest" msgid="8475274842845401871">"ဧည့်သည်"</string> <string name="unknown" msgid="1592123443519355854">"အကြောင်းအရာ မသိရှိ"</string> <string name="running_process_item_user_label" msgid="3129887865552025943">"သုံးစွဲသူ၊ <xliff:g id="USER_NAME">%1$s</xliff:g>"</string> - <string name="launch_defaults_some" msgid="313159469856372621">"တချို့အားပုံမှတ်အဖြစ်သတ်မှတ်"</string> + <string name="launch_defaults_some" msgid="313159469856372621">"မူရင်းအချို့ သတ်မှတ်ပြီး"</string> <string name="launch_defaults_none" msgid="4241129108140034876">"ပုံမှန်သတ်မှတ်ထားခြင်းမရှိ"</string> <string name="tts_settings" msgid="8186971894801348327">"စာသားမှစကားပြောပြောင်း ဆက်တင်များ"</string> <string name="tts_settings_title" msgid="1237820681016639683">"စာသားမှ အသံထွက်စေခြင်း"</string> @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi ရွမ်းရှာဖွေမှုကို အမြဲတမ်း ခွင့်ပြုမည်"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"မိုဘိုင်းဒေတာကို အမြဲဖွင့်ထားရန်"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"ဖုန်းကို မိုဒမ်အဖြစ်အသုံးပြုမှု စက်ပစ္စည်းဖြင့် အရှိန်မြှင့်တင်ခြင်း"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ပကတိ အသံနှုန်း သတ်မှတ်ချက် ပိတ်ရန်"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"သတ်မှတ်ထားသည့်ဖုန်းမြည်သံကို အသုံးပြုခြင်းအား ဖွင့်ရန်"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ဘလူးတုသ် AVRCP ဗားရှင်း"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"ဤဆက်တင်းများကို တည်ဆောက်ပြုပြင်ရာတွင် သုံးရန်အတွက်သာ ရည်ရွယ်သည်။ ၎င်းတို့သည် သင်၏စက်နှင့် အပလီကေးရှင်းများကို ရပ်စေခြင်း သို့ လုပ်ဆောင်ချက်မမှန်ကန်ခြင်းများ ဖြစ်ပေါ်စေနိုင်သည်။"</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USBပေါ်မှ အပလီကေးရှင်းများကို အတည်ပြုစိစစ်ရန်"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT မှတဆင့် ထည့်သွင်းသော အပလီကေးရှင်းများကို အန္တရာယ်ဖြစ်နိုင်ခြင်း ရှိမရှိ စစ်ဆေးရန်။"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ချိတ်ဆက်ထားသည့် ကိရိယာတွင် လက်မခံနိုင်လောက်အောင် ဆူညံ သို့မဟုတ် ထိန်းညှိမရနိုင်သော အသံပိုင်းပြဿနာ ရှိခဲ့လျှင် ဘလူးတုသ် ပကတိ အသံနှုန်းကို ပိတ်ပါ။"</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ဖုန်းတွင်းရှိ ဖုန်းမြည်သံများကို ဘလူးတုသ် မိုက်ခွက်ပါနားကြပ်တွင် ဖွင့်ခွင့်ပြုရန်"</string> <string name="enable_terminal_title" msgid="95572094356054120">"လိုကယ်တာမီနယ်"</string> @@ -351,21 +355,19 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> ကျန်သည်"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> − အားပြည့်ရန် <xliff:g id="TIME">^2</xliff:g> ကျန်သည်"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"အကြောင်းအရာ မသိရှိ"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"အားသွင်းနေပါသည်"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"အားသွင်းနေပါသည်"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"အားသွင်းမနေပါ"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"ပလပ်ထိုးထားသောကြောင့် ယခုအားသွင်း၍ မရသေးပါ"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"အပြည့်"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"စီမံခန့်ခွဲသူမှ ထိန်းချုပ်ပါသည်"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"စီမံခန့်ခွဲသူက ဖွင့်ထားသည်"</string> <string name="disabled_by_admin" msgid="8505398946020816620">"စီမံခန့်ခွဲသူက ပိတ်ထားသည်"</string> <string name="disabled" msgid="9206776641295849915">"ပိတ်ထားပြီး"</string> <string name="external_source_trusted" msgid="2707996266575928037">"ခွင့်ပြုထားသည်"</string> - <string name="external_source_untrusted" msgid="2677442511837596726">"ခွင့်ပြုမထားပါ"</string> - <string name="install_other_apps" msgid="6986686991775883017">"အမျိုးအမည်မသိအက်ပ် ထည့်သွင်းနိုင်ခြင်း"</string> + <string name="external_source_untrusted" msgid="2677442511837596726">"ခွင့်မပြုပါ"</string> + <string name="install_other_apps" msgid="6986686991775883017">"အမည်မသိအက်ပ်"</string> <string name="home" msgid="3256884684164448244">"ဆက်တင် ပင်မစာမျက်နှာ"</string> <string-array name="battery_labels"> <item msgid="8494684293649631252">"၀%"</item> diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml index 287c38618802..1c9186a22f02 100644 --- a/packages/SettingsLib/res/values-nb/arrays.xml +++ b/packages/SettingsLib/res/values-nb/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Bruk systemvalg (standard)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Slå på valgfrie kodeker"</item> - <item msgid="3304843301758635896">"Slå av valgfrie kodeker"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Bruk systemvalg (standard)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Slå på valgfrie kodeker"</item> - <item msgid="741805482892725657">"Slå av valgfrie kodeker"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Bruk systemvalg (standard)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index 756c2fc94096..3f82a0536b75 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillat alltid skanning for Wi-Fi-roaming"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobildata er alltid aktiv"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Maskinvareakselerasjon for internettdeling"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Slå av funksjonen for absolutt volum"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Slå på innenbåndsringing"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP-versjon"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Disse innstillingene er bare beregnet for bruk under programutvikling. De kan forårsake problemer med enheten din og tilhørende apper."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Bekreft apper via USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Sjekk apper som er installert via ADB/ADT for skadelig adferd."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Slår av funksjonen for absolutt volum via Bluetooth i tilfelle det oppstår volumrelaterte problemer med eksterne enheter, for eksempel uakseptabelt høyt volum eller mangel på kontroll."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Tillater at ringelyder på telefonen spilles av på Bluetooth-hodetelefoner"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Lokal terminal"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> gjenstår"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> til det er fulladet"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Ukjent"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Lader"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"lader"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Lader ikke"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Laderen er koblet til – kan ikke lade akkurat nå"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Fullt"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontrollert av administratoren"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Slått på av administratoren"</string> diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml index ba7affd95971..b22dc12621ea 100644 --- a/packages/SettingsLib/res/values-ne/arrays.xml +++ b/packages/SettingsLib/res/values-ne/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"वैकल्पिक कोडेकहरूलाई सक्षम पार्नुहोस्"</item> - <item msgid="3304843301758635896">"वैकल्पिक कोडेकहरूलाई असक्षम पार्नुहोस्"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"वैकल्पिक कोडेकहरूलाई सक्षम पार्नुहोस्"</item> - <item msgid="741805482892725657">"वैकल्पिक कोडेकहरूलाई असक्षम पार्नुहोस्"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item> <item msgid="8895532488906185219">"४४.१ kHz"</item> diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml index 03d39afe0c25..1b8f47086b33 100644 --- a/packages/SettingsLib/res/values-ne/strings.xml +++ b/packages/SettingsLib/res/values-ne/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi घुम्ने स्क्यान गर्न सधैँ अनुमति दिनुहोस्"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"मोबाइल डेटा सधैँ सक्रिय राख्नुहोस्"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"टेदरिङको लागि हार्डवेयरको प्रवेग"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"निरपेक्ष आवाज असक्षम गर्नुहोस्"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"इन-ब्यान्ड घन्टी बज्ने सुविधालाई सक्षम पार्नुहोस्"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ब्लुटुथको AVRCP संस्करण"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"यी सेटिङहरू केवल विकास प्रयोगको लागि विचार गरिएको हो। तिनीहरूले तपाईंको उपकरण र अनुप्रयोगहरूलाई विच्छेदन गर्न वा दुर्व्यवहार गर्न सक्दछ।"</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB मा अनुप्रयोगहरू रुजु गर्नुहोस्"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"हानिकारक व्यवहारको लागि ADB/ADT को माध्यमबाट स्थापित अनुप्रयोगहरूको जाँच गर्नुहोस्।"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"रिमोट यन्त्रहरूमा अस्वीकार्य चर्को आवाज वा नियन्त्रणमा कमी जस्ता आवाज सम्बन्धी समस्याहरूको अवस्थामा ब्लुटुथ निरपेक्ष आवाज सुविधालाई असक्षम गराउँछ।"</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"उक्त फोनमा भएका रिङटोनहरूलाई ब्लुटुथका हेडसेटहरूमा प्ले गर्न दिनुहोस्"</string> <string name="enable_terminal_title" msgid="95572094356054120">"स्थानीय टर्मिनल"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"बाँकी समय <xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - पूर्णरूपमा चार्ज हुन <xliff:g id="TIME">^2</xliff:g> बाँकी"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज हुँदै"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"चार्ज हुँदै"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"चार्ज भइरहेको छैन"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"प्लगइन गरिएको छ, अहिले नै चार्ज गर्न सकिँदैन"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"पूर्ण"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"प्रशासकद्वारा नियन्त्रित"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"प्रशासकद्वारा सक्षम पारिएको छ"</string> diff --git a/packages/SettingsLib/res/values-nl/arrays.xml b/packages/SettingsLib/res/values-nl/arrays.xml index 25b803ac6771..94443c2e1cb7 100644 --- a/packages/SettingsLib/res/values-nl/arrays.xml +++ b/packages/SettingsLib/res/values-nl/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Systeemselectie gebruiken (standaard)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Optionele codecs inschakelen"</item> - <item msgid="3304843301758635896">"Optionele codecs uitschakelen"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Systeemselectie gebruiken (standaard)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Optionele codecs inschakelen"</item> - <item msgid="741805482892725657">"Optionele codecs uitschakelen"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Systeemselectie gebruiken (standaard)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index 6ca23af74946..93291a04572a 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -163,7 +163,7 @@ <string name="choose_profile" msgid="6921016979430278661">"Profiel kiezen"</string> <string name="category_personal" msgid="1299663247844969448">"Persoonlijk"</string> <string name="category_work" msgid="8699184680584175622">"Werk"</string> - <string name="development_settings_title" msgid="215179176067683667">"Opties voor ontwikkelaars"</string> + <string name="development_settings_title" msgid="215179176067683667">"Ontwikkelaarsopties"</string> <string name="development_settings_enable" msgid="542530994778109538">"Opties voor ontwikkelaars inschakelen"</string> <string name="development_settings_summary" msgid="1815795401632854041">"Opties instellen voor appontwikkeling"</string> <string name="development_settings_not_available" msgid="4308569041701535607">"Ontwikkelaarsopties zijn niet beschikbaar voor deze gebruiker"</string> @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Altijd roamingscans voor wifi toestaan"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiele data altijd actief"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwareversnelling voor tethering"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Absoluut volume uitschakelen"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"In-band bellen inschakelen"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth-AVRCP-versie"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Deze instellingen zijn uitsluitend bedoeld voor ontwikkelingsgebruik. Je apparaat en apps kunnen hierdoor vastlopen of anders reageren."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Apps verifiëren via USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Apps die zijn geïnstalleerd via ADB/ADT, controleren op schadelijk gedrag"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Hiermee wordt de functie voor absoluut volume van Bluetooth uitgeschakeld in geval van volumeproblemen met externe apparaten, zoals een onacceptabel hoog volume of geen volumeregeling."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Toestaan dat beltonen worden afgespeeld op Bluetooth-headsets"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Lokale terminal"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> resterend"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> tot volledig opgeladen"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Onbekend"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Opladen"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"opladen"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Wordt niet opgeladen"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Aangesloten, kan nu niet opladen"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Volledig"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Ingesteld door beheerder"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Ingeschakeld door beheerder"</string> diff --git a/packages/SettingsLib/res/values-pa/arrays.xml b/packages/SettingsLib/res/values-pa/arrays.xml index 2715f9d78df8..af209923f698 100644 --- a/packages/SettingsLib/res/values-pa/arrays.xml +++ b/packages/SettingsLib/res/values-pa/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"ਵਿਕਲਪਿਕ ਕੋਡੈਕ ਯੋਗ ਬਣਾਓ"</item> - <item msgid="3304843301758635896">"ਵਿਕਲਪਿਕ ਕੋਡੈਕ ਅਯੋਗ ਬਣਾਓ"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"ਵਿਕਲਪਿਕ ਕੋਡੈਕ ਯੋਗ ਬਣਾਓ"</item> - <item msgid="741805482892725657">"ਵਿਕਲਪਿਕ ਕੋਡੈਕ ਅਯੋਗ ਬਣਾਓ"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml index 3a4349575696..95a9cce6999f 100644 --- a/packages/SettingsLib/res/values-pa/strings.xml +++ b/packages/SettingsLib/res/values-pa/strings.xml @@ -66,7 +66,7 @@ <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"ਮੀਡੀਆ ਔਡੀਓ"</string> <string name="bluetooth_profile_headset" msgid="7815495680863246034">"ਫ਼ੋਨ ਕਾਲਾਂ"</string> <string name="bluetooth_profile_opp" msgid="9168139293654233697">"ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ"</string> - <string name="bluetooth_profile_hid" msgid="3680729023366986480">"ਇਨਪੁਟ ਡੀਵਾਈਸ"</string> + <string name="bluetooth_profile_hid" msgid="3680729023366986480">"ਇਨਪੁੱਟ ਡੀਵਾਈਸ"</string> <string name="bluetooth_profile_pan" msgid="3391606497945147673">"ਇੰਟਰਨੈਟ ਪਹੁੰਚ"</string> <string name="bluetooth_profile_pbap" msgid="5372051906968576809">"ਸੰਪਰਕ ਸ਼ੇਅਰਿੰਗ"</string> <string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"ਸੰਪਰਕ ਸ਼ੇਅਰਿੰਗ ਲਈ ਵਰਤੋ"</string> @@ -81,9 +81,9 @@ <string name="bluetooth_map_profile_summary_connected" msgid="8191407438851351713">"ਨਕਸ਼ੇ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string> <string name="bluetooth_sap_profile_summary_connected" msgid="8561765057453083838">"SAP ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string> <string name="bluetooth_opp_profile_summary_not_connected" msgid="1267091356089086285">"ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ ਸਰਵਰ ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ"</string> - <string name="bluetooth_hid_profile_summary_connected" msgid="3381760054215168689">"ਇਨਪੁਟ ਡੀਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string> - <string name="bluetooth_pan_user_profile_summary_connected" msgid="4602294638909590612">"ਇੰਟਰਨੈਟ ਪਹੁੰਚ ਲਈ ਡੀਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string> - <string name="bluetooth_pan_nap_profile_summary_connected" msgid="1561383706411975199">"ਡੀਵਾਈਸ ਨਾਲ ਸਥਾਨਕ ਇੰਟਰਨੈਟ ਕਨੈਕਸ਼ਨ ਸ਼ੇਅਰ ਕਰ ਰਿਹਾ ਹੈ"</string> + <string name="bluetooth_hid_profile_summary_connected" msgid="3381760054215168689">"ਇਨਪੁੱਟ ਡੀਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string> + <string name="bluetooth_pan_user_profile_summary_connected" msgid="4602294638909590612">"ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ ਲਈ ਡੀਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string> + <string name="bluetooth_pan_nap_profile_summary_connected" msgid="1561383706411975199">"ਡੀਵਾਈਸ ਨਾਲ ਸਥਾਨਕ ਇੰਟਰਨੈੱਟ ਕਨੈਕਸ਼ਨ ਸਾਂਝਾ ਕਰ ਰਿਹਾ ਹੈ"</string> <string name="bluetooth_pan_profile_summary_use_for" msgid="5664884523822068653">"ਇੰਟਰਨੈਟ ਪਹੁੰਚ ਲਈ ਵਰਤੋ"</string> <string name="bluetooth_map_profile_summary_use_for" msgid="5154200119919927434">"ਨਕਸ਼ੇ ਲਈ ਵਰਤੋ"</string> <string name="bluetooth_sap_profile_summary_use_for" msgid="7085362712786907993">"SIM ਪਹੁੰਚ ਲਈ ਵਰਤੋ"</string> @@ -96,7 +96,7 @@ <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ਰੱਦ ਕਰੋ"</string> <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"ਪੇਅਰ ਕਰਨਾ ਕਨੈਕਟ ਕੀਤੇ ਜਾਣ ਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਅਤੇ ਕਾਲ ਇਤਿਹਾਸ ਤੱਕ ਪਹੁੰਚ ਦੀ ਅਨੁਮਤੀ ਦਿੰਦਾ ਹੈ।"</string> <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਨਾਲ ਪੇਅਰ ਨਹੀਂ ਕਰ ਸਕਿਆ।"</string> - <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"ਇੱਕ ਗ਼ਲਤ PIN ਜਾਂ ਪਾਸਕੁੰਜੀ ਦੇ ਕਾਰਨ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਨਾਲ ਪੇਅਰ ਨਹੀਂ ਕਰ ਸਕਿਆ।"</string> + <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"ਇੱਕ ਗ਼ਲਤ ਪਿੰਨ ਜਾਂ ਪਾਸਕੁੰਜੀ ਦੇ ਕਾਰਨ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਨਾਲ ਜੋੜਾਬੱਧ ਨਹੀਂ ਹੋ ਸਕਿਆ।"</string> <string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਨਾਲ ਸੰਚਾਰ ਨਹੀਂ ਕਰ ਸਕਦਾ।"</string> <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"ਪੇਅਰਿੰਗ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਵੱਲੋਂ ਰੱਦ ਕੀਤੀ ਗਈ।"</string> <string name="accessibility_wifi_off" msgid="1166761729660614716">"Wifi ਬੰਦ।"</string> @@ -135,7 +135,7 @@ <string name="tts_play_example_summary" msgid="8029071615047894486">"ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਦਾ ਇੱਕ ਛੋਟਾ ਪ੍ਰਦਰਸ਼ਨ ਪਲੇ ਕਰੋ"</string> <string name="tts_install_data_title" msgid="4264378440508149986">"ਵੌਇਸ ਡੈਟਾ ਇੰਸਟੌਲ ਕਰੋ"</string> <string name="tts_install_data_summary" msgid="5742135732511822589">"ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਲਈ ਲੁੜੀਂਦਾ ਵੌਇਸ ਡੈਟਾ ਇੰਸਟੌਲ ਕਰੋ"</string> - <string name="tts_engine_security_warning" msgid="8786238102020223650">"ਇਹ ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਇੰਜਣ ਉਹ ਸਾਰਾ ਟੈਕਸਟ ਇਕੱਤਰ ਕਰਨ ਵਿੱਚ ਸਮਰੱਥ ਹੋ ਸਕਦਾ ਹੈ, ਜੋ ਬੋਲਿਆ ਜਾਏਗਾ, ਨਿੱਜੀ ਡੈਟਾ ਸਮੇਤ ਜਿਵੇਂ ਪਾਸਵਰਡ ਅਤੇ ਕ੍ਰੈਡਿਟ ਕਾਰਡ ਨੰਬਰ। ਇਹ <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> ਇੰਜਣ ਤੋਂ ਆਉਂਦਾ ਹੈ। ਕੀ ਇਸ ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਇੰਜਣ ਦੀ ਵਰਤੋਂ ਕਰਨੀ ਹੈ?"</string> + <string name="tts_engine_security_warning" msgid="8786238102020223650">"ਇਹ ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਇੰਜਣ ਉਹ ਸਾਰੀ ਲਿਖਤ ਇਕੱਤਰ ਕਰਨ ਵਿੱਚ ਸਮਰੱਥ ਹੋ ਸਕਦਾ ਹੈ, ਜੋ ਬੋਲੀ ਜਾਏ, ਨਿੱਜੀ ਡਾਟਾ ਸਮੇਤ ਜਿਵੇਂ ਪਾਸਵਰਡ ਅਤੇ ਕ੍ਰੈਡਿਟ ਕਾਰਡ ਨੰਬਰ। ਇਹ <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> ਇੰਜਣ ਤੋਂ ਆਉਂਦਾ ਹੈ। ਕੀ ਇਸ ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਇੰਜਣ ਦੀ ਵਰਤੋਂ ਕਰਨੀ ਹੈ?"</string> <string name="tts_engine_network_required" msgid="1190837151485314743">"ਇਸ ਭਾਸ਼ਾ ਲਈ ਟੈਕਸਟ-ਟੂ-ਸਪੀਚ ਆਊਟਪੁਟ ਲਈ ਇੱਕ ਚਾਲੂ ਨੈੱਟਵਰਕ ਕਨੈਕਸ਼ਨ ਦੀ ਲੋੜ ਹੈ।"</string> <string name="tts_default_sample_string" msgid="4040835213373086322">"ਇਹ ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਦਾ ਇੱਕ ਉਦਾਹਰਨ ਹੈ"</string> <string name="tts_status_title" msgid="7268566550242584413">"ਪੂਰਵ-ਨਿਰਧਾਰਤ ਭਾਸ਼ਾ ਸਥਿਤੀ"</string> @@ -144,7 +144,7 @@ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ"</string> <string name="tts_status_checking" msgid="5339150797940483592">"ਜਾਂਚ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ..."</string> <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> ਲਈ ਸੈਟਿੰਗਾਂ"</string> - <string name="tts_engine_settings_button" msgid="1030512042040722285">"ਇੰਜਨ ਸੈਟਿੰਗਾਂ ਲੌਂਚ ਕਰੋ"</string> + <string name="tts_engine_settings_button" msgid="1030512042040722285">"ਇੰਜਨ ਸੈਟਿੰਗਾਂ ਲਾਂਚ ਕਰੋ"</string> <string name="tts_engine_preference_section_title" msgid="448294500990971413">"ਤਰਜੀਹੀ ਇੰਜਣ"</string> <string name="tts_general_section_title" msgid="4402572014604490502">"ਸਧਾਰਨ"</string> <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"ਬੋਲਣ ਦੀ ਪਿੱਚ ਨੂੰ ਦੁਬਾਰਾ ਮੁੜ-ਸੈੱਟ ਕਰੋ"</string> @@ -174,7 +174,7 @@ <string name="enable_adb_summary" msgid="4881186971746056635">"ਡੀਬਗ ਮੋਡ ਜਦੋਂ USB ਕਨੈਕਟ ਕੀਤੀ ਜਾਏ"</string> <string name="clear_adb_keys" msgid="4038889221503122743">"USB ਡੀਬਗਿੰਗ ਅਧਿਕਾਰ ਰੱਦ ਕਰੋ"</string> <string name="bugreport_in_power" msgid="7923901846375587241">"ਬਗ ਰਿਪੋਰਟ ਸ਼ਾਰਟਕੱਟ"</string> - <string name="bugreport_in_power_summary" msgid="1778455732762984579">"ਇੱਕ ਬਗ ਰਿਪੋਰਟ ਲੈਣ ਲਈ ਪਾਵਰ ਮੀਨੂ ਵਿੱਚ ਇੱਕ ਬਟਨ ਦਿਖਾਓ"</string> + <string name="bugreport_in_power_summary" msgid="1778455732762984579">"ਇੱਕ ਬੱਗ ਰਿਪੋਰਟ ਲੈਣ ਲਈ ਪਾਵਰ ਮੀਨੂ ਵਿੱਚ ਇੱਕ ਬਟਨ ਦਿਖਾਓ"</string> <string name="keep_screen_on" msgid="1146389631208760344">"ਸਕਿਰਿਆ ਰੱਖੋ"</string> <string name="keep_screen_on_summary" msgid="2173114350754293009">"ਸਕ੍ਰੀਨ ਚਾਰਜਿੰਗ ਦੇ ਸਮੇਂ ਕਦੇ ਵੀ ਸਲੀਪ ਨਹੀਂ ਹੋਵੇਗੀ"</string> <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Bluetooth HCI ਸਨੂਪ ਲੌਗ ਨੂੰ ਸਮਰੱਥ ਬਣਾਓ"</string> @@ -182,17 +182,19 @@ <string name="oem_unlock_enable" msgid="6040763321967327691">"OEM ਅਨਲੌਕ ਕਰਨਾ"</string> <string name="oem_unlock_enable_summary" msgid="4720281828891618376">"ਬੂਟਲੋਡਰ ਨੂੰ ਅਨਲੌਕ ਕੀਤੇ ਜਾਣ ਦੀ ਆਗਿਆ ਦਿਓ"</string> <string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"ਕੀ OEM ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string> - <string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"ਚਿਤਾਵਨੀ: ਡੀਵਾਈਸ ਸੁਰੱਖਿਆ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਉਦੋਂ ਇਸ ਡੀਵਾਈਸ ਤੇ ਕੰਮ ਨਹੀਂ ਕਰਨਗੀਆਂ ਜਦੋਂ ਇਹ ਸੈਟਿੰਗ ਚਾਲੂ ਹੋਵੇਗੀ।"</string> + <string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"ਚਿਤਾਵਨੀ: ਉਦੋਂ ਇਸ ਡੀਵਾਈਸ ਤੇ ਕੰਮ ਨਹੀਂ ਕਰਨਗੀਆਂ ਜਦੋਂ ਇਹ ਸੈਟਿੰਗ ਚਾਲੂ ਹੋਵੇਗੀ।"</string> <string name="mock_location_app" msgid="7966220972812881854">"ਮੌਕ ਸਥਾਨ ਐਪ ਚੁਣੋ"</string> <string name="mock_location_app_not_set" msgid="809543285495344223">"ਕੋਈ ਵੀ ਮੌਕ ਸਥਾਨ ਐਪ ਸੈੱਟ ਨਹੀਂ ਕੀਤੀ ਗਈ"</string> <string name="mock_location_app_set" msgid="8966420655295102685">"ਮੌਕ ਸਥਾਨ ਐਪ: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="debug_networking_category" msgid="7044075693643009662">"ਨੈੱਟਵਰਕਿੰਗ"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"ਵਾਇਰਲੈਸ ਡਿਸਪਲੇ ਪ੍ਰਮਾਣੀਕਰਨ"</string> - <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi ਵਰਬੋਸ ਲੌਗਿੰਗ ਸਮਰੱਥ ਬਣਾਓ"</string> - <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ਆਕਰਮਣਸ਼ੀਲ Wi‑Fi ਤੋਂ ਮੋਬਾਈਲ ਹੈਂਡਓਵਰ"</string> - <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ਹਮੇਸ਼ਾਂ Wi‑Fi Roam Scans ਦੀ ਆਗਿਆ ਦਿਓ"</string> - <string name="mobile_data_always_on" msgid="8774857027458200434">"ਮੋਬਾਈਲ ਡੈਟਾ ਹਮੇਸ਼ਾਂ ਕਿਰਿਆਸ਼ੀਲ"</string> + <string name="wifi_verbose_logging" msgid="4203729756047242344">"ਵਾਈ‑ਫਾਈ ਵਰਬੋਸ ਲੌਗਿੰਗ ਸਮਰੱਥ ਬਣਾਓ"</string> + <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ਆਕਰਮਣਸ਼ੀਲ ਵਾਈ‑ਫਾਈ ਤੋਂ ਮੋਬਾਈਲ ਹੈਂਡਓਵਰ"</string> + <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ਹਮੇਸ਼ਾਂ ਵਾਈ‑ਫਾਈ ਰੋਮ ਸਕੈਨਾਂ ਦੀ ਆਗਿਆ ਦਿਓ"</string> + <string name="mobile_data_always_on" msgid="8774857027458200434">"ਮੋਬਾਈਲ ਡਾਟਾ ਹਮੇਸ਼ਾਂ ਕਿਰਿਆਸ਼ੀਲ"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"ਟੈਦਰਿੰਗ ਹਾਰਡਵੇਅਰ ਐਕਸੇਲਰੇਸ਼ਨ"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ਪੂਰਨ ਵੌਲਿਊਮ ਨੂੰ ਅਯੋਗ ਬਣਾਓ"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"ਇਨ-ਬੈਂਡ ਘੰਟੀ ਵੱਜਣ ਨੂੰ ਯੋਗ ਬਣਾਓ"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ਬਲੂਟੁੱਥ AVRCP ਰੂਪ"</string> @@ -209,13 +211,13 @@ <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"ਬਲੂਟੁੱਥ ਔਡੀਓ LDAC ਕੋਡੇਕ ਚੁਣੋ:\nਪਲੇਬੈਕ ਗੁਣਵੱਤਾ"</string> <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"ਸਟ੍ਰੀਮਿੰਗ: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string> <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ਵਾਇਰਲੈਸ ਡਿਸਪਲੇ ਪ੍ਰਮਾਣੀਕਰਨ ਲਈ ਚੋਣਾਂ ਦਿਖਾਓ"</string> - <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ਲੌਗਿੰਗ ਪੱਧਰ ਵਧਾਓ, Wi‑Fi Picker ਵਿੱਚ ਪ੍ਰਤੀ SSID RSSI ਦਿਖਾਓ"</string> - <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ਜਦੋਂ ਯੋਗ ਬਣਾਇਆ ਹੋਵੇ, ਤਾਂ Wi‑Fi ਸਿਗਨਲ ਘੱਟ ਹੋਣ \'ਤੇ Wi‑Fi ਡੈਟਾ ਕਨੈਕਸ਼ਨ ਮੋਬਾਈਲ ਨੂੰ ਹੈਂਡ ਓਵਰ ਕਰਨ ਵਿੱਚ ਵੱਧ ਆਕਰਮਣਸ਼ੀਲ ਹੋਵੇਗਾ।"</string> - <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ਇੰਟਰਫੇਸ ਤੇ ਮੌਜੂਦ ਡੈਟਾ ਟ੍ਰੈਫਿਕ ਦੀ ਮਾਤਰਾ ਦੇ ਆਧਾਰ ਤੇ Wi‑Fi ਰੋਮ ਸਕੈਨ ਦੀ ਆਗਿਆ ਦਿਓ/ਅਸਵੀਕਾਰ ਕਰੋ"</string> + <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ਵਾਈ‑ਫਾਈ ਲੌਗਿੰਗ ਪੱਧਰ ਵਧਾਓ, ਵਾਈ‑ਫਾਈ Picker ਵਿੱਚ ਪ੍ਰਤੀ SSID RSSI ਦਿਖਾਓ"</string> + <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ਜਦੋਂ ਚਾਲੂ ਕੀਤਾ ਹੋਵੇ, ਤਾਂ ਵਾਈ‑ਫਾਈ ਸਿਗਨਲ ਘੱਟ ਹੋਣ \'ਤੇ ਵਾਈ‑ਫਾਈ ਡਾਟਾ ਕਨੈਕਸ਼ਨ ਮੋਬਾਈਲ ਨੂੰ ਹੈਂਡਓਵਰ ਕਰਨ ਵਿੱਚ ਵੱਧ ਆਕਰਮਣਸ਼ੀਲ ਹੋਵੇਗਾ।"</string> + <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ਇੰਟਰਫੇਸ ਤੇ ਮੌਜੂਦ ਡਾਟਾ ਟ੍ਰੈਫਿਕ ਦੀ ਮਾਤਰਾ ਦੇ ਆਧਾਰ ਤੇ ਵਾਈ‑ਫਾਈ ਰੋਮ ਸਕੈਨ ਦੀ ਆਗਿਆ ਦਿਓ/ਨਾ ਦਿਓ"</string> <string name="select_logd_size_title" msgid="7433137108348553508">"ਲੌਗਰ ਬਫਰ ਆਕਾਰ"</string> <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ਪ੍ਰਤੀ ਲੌਗ ਬਫਰ ਲੌਗਰ ਆਕਾਰ ਚੁਣੋ"</string> <string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"ਕੀ ਲੌਗਰ ਪ੍ਰਸਿੱਸਟੈਂਟ ਸਟੋਰੇਜ ਨੂੰ ਸਾਫ਼ ਕਰਨਾ ਹੈ?"</string> - <string name="dev_logpersist_clear_warning_message" msgid="2256582531342994562">"ਜਦੋਂ ਅਸੀਂ ਪ੍ਰਸਿੱਸਟੈਂਟ ਲੌਗਰ ਨਾਲ ਨਿਗਰਾਨੀ ਨਹੀਂ ਕਰ ਰਹੇ ਹੁੰਦੇ ਹਾਂ, ਤਾਂ ਸਾਨੂੰ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਵਿੱਚ ਮੌਜੂਦ ਲੌਗਰ ਡੈਟੇ ਨੂੰ ਮਿਟਾਉਣ ਦੀ ਲੋੜ ਪੈਂਦੀ ਹੈ।"</string> + <string name="dev_logpersist_clear_warning_message" msgid="2256582531342994562">"ਜਦੋਂ ਅਸੀਂ ਪ੍ਰਸਿੱਸਟੈਂਟ ਲੌਗਰ ਨਾਲ ਨਿਗਰਾਨੀ ਨਹੀਂ ਕਰ ਰਹੇ ਹੁੰਦੇ ਹਾਂ, ਤਾਂ ਸਾਨੂੰ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਵਿੱਚ ਮੌਜੂਦ ਲੌਗਰ ਡਾਟੇ ਨੂੰ ਮਿਟਾਉਣ ਦੀ ਲੋੜ ਪੈਂਦੀ ਹੈ।"</string> <string name="select_logpersist_title" msgid="7530031344550073166">"ਡੀਵਾਈਸ \'ਤੇ ਲੌਗ ਬਫ਼ਰਾਂ ਨੂੰ ਸਥਾਈ ਤੌਰ \'ਤੇ ਸਟੋਰ ਕਰੋ"</string> <string name="select_logpersist_dialog_title" msgid="4003400579973269060">"ਡੀਵਾਈਸ \'ਤੇ ਸਥਾਈ ਤੌਰ \'ਤੇ ਸਟੋਰ ਕਰਨ ਲਈ ਲੌਗ ਬਫ਼ਰਾਂ ਨੂੰ ਚੁਣੋ"</string> <string name="select_usb_configuration_title" msgid="2649938511506971843">"USB ਕੌਂਫਿਗਰੇਸ਼ਨ ਚੁਣੋ"</string> @@ -223,15 +225,17 @@ <string name="allow_mock_location" msgid="2787962564578664888">"ਨਕਲੀ ਨਿਰਧਾਰਿਤ ਸਥਾਨਾਂ ਦੀ ਆਗਿਆ ਦਿਓ"</string> <string name="allow_mock_location_summary" msgid="317615105156345626">"ਨਕਲੀ ਨਿਰਧਾਰਿਤ ਸਥਾਨਾਂ ਦੀ ਆਗਿਆ ਦਿਓ"</string> <string name="debug_view_attributes" msgid="6485448367803310384">"ਗੁਣ ਛਾਣਬੀਣ ਦੇਖੋ ਨੂੰ ਸਮਰੱਥ ਬਣਾਓ"</string> - <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"ਹਮੇਸ਼ਾ ਮੋਬਾਈਲ ਡੇਟਾ ਨੂੰ ਕਿਰਿਆਸ਼ੀਲ ਰੱਖੋ ਭਾਵੇਂ Wi‑Fi ਕਿਰਿਆਸ਼ੀਲ ਹੋਵੇ (ਤੇਜ਼ ਨੈੱਟਵਰਕ ਸਵਿੱਚਿੰਗ ਲਈ)।"</string> + <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"ਹਮੇਸ਼ਾਂ ਮੋਬਾਈਲ ਡਾਟਾ ਨੂੰ ਕਿਰਿਆਸ਼ੀਲ ਰੱਖੋ, ਭਾਵੇਂ ਵਾਈ‑ਫਾਈ ਕਿਰਿਆਸ਼ੀਲ ਹੋਵੇ (ਤੇਜ਼ ਨੈੱਟਵਰਕ ਸਵਿੱਚਿੰਗ ਲਈ)।"</string> <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"ਉਪਲਬਧ ਹੋਣ \'ਤੇ ਟੈਦਰਿੰਗ ਹਾਰਡਵੇਅਰ ਐਕਸੇਲਰੇਸ਼ਨ ਵਰਤੋ"</string> <string name="adb_warning_title" msgid="6234463310896563253">"ਕੀ USB ਡੀਬਗਿੰਗ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string> - <string name="adb_warning_message" msgid="7316799925425402244">"USB ਡੀਬਗਿੰਗ ਕੇਵਲ ਵਿਕਾਸ ਮੰਤਵਾਂ ਲਈ ਹੁੰਦੀ ਹੈ। ਇਸਨੂੰ ਆਪਣੇ ਕੰਪਿਊਟਰ ਅਤੇ ਆਪਣੀ ਡੀਵਾਈਸ ਵਿਚਕਾਰ ਡੈਟਾ ਕਾਪੀ ਕਰਨ ਲਈ ਵਰਤੋ, ਸੂਚਨਾ ਦੇ ਬਿਨਾਂ ਆਪਣੀ ਡੀਵਾਈਸ ਤੇ ਐਪਸ ਇੰਸਟੌਲ ਕਰੋ ਅਤੇ ਲੌਗ ਡੈਟਾ ਪੜ੍ਹੋ।"</string> + <string name="adb_warning_message" msgid="7316799925425402244">"USB ਡੀਬਗਿੰਗ ਕੇਵਲ ਵਿਕਾਸ ਮੰਤਵਾਂ ਲਈ ਹੁੰਦੀ ਹੈ। ਇਸਨੂੰ ਆਪਣੇ ਕੰਪਿਊਟਰ ਅਤੇ ਆਪਣੇ ਡੀਵਾਈਸ ਵਿਚਕਾਰ ਡਾਟਾ ਕਾਪੀ ਕਰਨ ਲਈ ਵਰਤੋ, ਸੂਚਨਾ ਦੇ ਬਿਨਾਂ ਆਪਣੇ ਡੀਵਾਈਸ ਤੇ ਐਪਾਂ ਸਥਾਪਤ ਕਰੋ ਅਤੇ ਲੌਗ ਡਾਟਾ ਪੜ੍ਹੋ।"</string> <string name="adb_keys_warning_message" msgid="5659849457135841625">"ਕੀ ਉਹਨਾਂ ਸਾਰੇ ਕੰਪਿਊਟਰਾਂ ਤੋਂ USB ਡੀਬਗਿੰਗ ਤੱਕ ਪਹੁੰਚ ਰੱਦ ਕਰਨੀ ਹੈ, ਜਿਹਨਾਂ ਲਈ ਪਹਿਲਾਂ ਤੁਸੀਂ ਅਧਿਕਾਰਤ ਕੀਤਾ ਹੈ?"</string> <string name="dev_settings_warning_title" msgid="7244607768088540165">"ਕੀ ਵਿਕਾਸ ਸੈਟਿੰਗਾਂ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string> - <string name="dev_settings_warning_message" msgid="2298337781139097964">"ਇਹ ਸੈਟਿੰਗਾਂ ਕੇਵਲ ਵਿਕਾਸਕਾਰ ਦੀ ਵਰਤੋਂ ਲਈ ਹਨ। ਇਹ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਅਤੇ ਇਸਤੇ ਮੌਜੂਦ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਬ੍ਰੇਕ ਕਰਨ ਜਾਂ ਦੁਰਵਿਵਹਾਰ ਕਰਨ ਦਾ ਕਾਰਨ ਬਣ ਸਕਦੇ ਹਨ।"</string> + <string name="dev_settings_warning_message" msgid="2298337781139097964">"ਇਹ ਸੈਟਿੰਗਾਂ ਕੇਵਲ ਵਿਕਾਸਕਾਰ ਦੀ ਵਰਤੋਂ ਲਈ ਹਨ। ਇਹ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਅਤੇ ਇਸਤੇ ਮੌਜੂਦ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਬ੍ਰੇਕ ਕਰਨ ਜਾਂ ਦੁਰਵਿਵਹਾਰ ਕਰਨ ਦਾ ਕਾਰਨ ਬਣ ਸਕਦੇ ਹਨ।"</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB ਤੇ ਐਪਸ ਨੂੰ ਪ੍ਰਮਾਣਿਤ ਕਰੋ"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ਹਾਨੀਕਾਰਕ ਵਿਵਹਾਰ ਲਈ ADB/ADT ਰਾਹੀਂ ਇੰਸਟੌਲ ਕੀਤੇ ਐਪਸ ਦੀ ਜਾਂਚ ਕਰੋ।"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ਰਿਮੋਟ ਡੀਵਾਈਸਾਂ ਨਾਲ ਵੌਲਿਊਮ ਸਮੱਸਿਆਵਾਂ ਜਿਵੇਂ ਕਿ ਨਾ ਪਸੰਦ ਕੀਤੀ ਜਾਣ ਵਾਲੀ ਉੱਚੀ ਵੌਲਿਊਮ ਜਾਂ ਕੰਟਰੋਲ ਦੀ ਕਮੀ ਵਰਗੀ ਹਾਲਤ ਵਿੱਚ ਬਲੂਟੁੱਥ ਪੂਰਨ ਵੌਲਿਊਮ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਅਯੋਗ ਬਣਾਉਂਦਾ ਹੈ।"</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ਤੁਹਾਡੇ ਫ਼ੋਨ ਦੀਆਂ ਰਿੰਗਟੋਨਾਂ ਨੂੰ ਬਲੂਟੁੱਥ ਹੈੱਡਸੈੱਟਾਂ \'ਤੇ ਚਲਾਉਣ ਦੀ ਇਜਾਜ਼ਤ ਦਿਓ"</string> <string name="enable_terminal_title" msgid="95572094356054120">"ਸਥਾਨਕ ਟਰਮੀਨਲ"</string> @@ -250,7 +254,7 @@ <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"ਟੈਲੀਫ਼ੋਨੀ ਮੋਨੀਟਰ ਟੈਲੀਫ਼ੋਨੀ/ਮੌਡਮ ਪ੍ਰਕਾਰਜਾਤਮਕਤਾ ਵਿੱਚ ਕਿਸੇ ਸਮੱਸਿਆ ਦਾ ਪਤਾ ਲੱਗਣ \'ਤੇ ਲੌਗਾਂ ਨੂੰ ਇਕੱਤਰ ਕਰੇਗਾ ਅਤੇ ਵਰਤੋਂਕਾਰ ਨੂੰ ਇੱਕ ਬੱਗ ਦਾਇਰ ਕਰਨ ਲਈ ਸੂਚਨਾ ਦੇਵੇਗਾ"</string> <string name="debug_input_category" msgid="1811069939601180246">"ਇਨਪੁਟ"</string> <string name="debug_drawing_category" msgid="6755716469267367852">"ਡਰਾਇੰਗ"</string> - <string name="debug_hw_drawing_category" msgid="6220174216912308658">"ਹਾਰਡਵੇਅਰ ਤੇਜ਼ ਕੀਤਾ ਪ੍ਰਗਟਾਅ"</string> + <string name="debug_hw_drawing_category" msgid="6220174216912308658">"ਹਾਰਡਵੇਅਰ ਐਕਸੇਲਰੇਟਿਡ ਰੈਂਡਰਿੰਗ"</string> <string name="media_category" msgid="4388305075496848353">"ਮੀਡੀਆ"</string> <string name="debug_monitoring_category" msgid="7640508148375798343">"ਨਿਰੀਖਣ ਕਰ ਰਿਹਾ ਹੈ"</string> <string name="strict_mode" msgid="1938795874357830695">"ਸਟ੍ਰਿਕਟ ਮੋਡ ਸਮਰਥਿਤ"</string> @@ -263,8 +267,8 @@ <string name="show_screen_updates_summary" msgid="2569622766672785529">"ਸਮੁੱਚੀ ਵਿੰਡੋ ਸਰਫੇਸਾਂ ਫਲੈਸ਼ ਕਰੋ ਜਦੋਂ ਉਹ ਅਪਡੇਟ ਹੁੰਦੀਆਂ ਹਨ"</string> <string name="show_hw_screen_updates" msgid="5036904558145941590">"GPU ਦ੍ਰਿਸ਼ ਅਪਡੇਟਾਂ ਦਿਖਾਓ"</string> <string name="show_hw_screen_updates_summary" msgid="1115593565980196197">"ਜਦੋਂ GPU ਨਾਲ ਡ੍ਰਾ ਕੀਤਾ ਜਾਏ ਤਾਂ ਵਿੰਡੋਜ ਦੇ ਅੰਦਰ ਦ੍ਰਿਸ਼ ਫਲੈਸ਼ ਕਰੋ"</string> - <string name="show_hw_layers_updates" msgid="5645728765605699821">"ਹਾਰਡਵੇਅਰ ਲੇਅਰਸ ਅਪਡੇਟਾਂ ਦਿਖਾਓ"</string> - <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ਹਾਰਡਵੇਅਰ ਲੇਅਰਾਂ ਨੂੰ ਹਰੀਆਂ ਫਲੈਸ਼ ਕਰੋ ਜਦੋਂ ਉਹ ਅਪਡੇਟ ਹੁੰਦੀਆਂ ਹਨ"</string> + <string name="show_hw_layers_updates" msgid="5645728765605699821">"ਹਾਰਡਵੇਅਰ ਲੇਅਰਾਂ ਦੇ ਅੱਪਡੇਟਾਂ ਦਿਖਾਓ"</string> + <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ਹਾਰਡਵੇਅਰ ਲੇਅਰਾਂ ਹਰੀਆਂ ਫਲੈਸ਼ ਕਰੋ ਜਦੋਂ ਉਹ ਅੱਪਡੇਟ ਹੁੰਦੀਆਂ ਹਨ"</string> <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ਓਵਰਡ੍ਰਾ ਡੀਬਗ ਕਰੋ"</string> <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU ਰੈਂਡਰਰ ਸੈੱਟ ਕਰੋ"</string> <string name="disable_overlays" msgid="2074488440505934665">"HW ਓਵਰਲੇਜ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਓ"</string> @@ -292,7 +296,7 @@ <string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"ਹਰੇਕ ਗਤੀਵਿਧੀ ਨੂੰ ਨਸ਼ਟ ਕਰੋ ਜਿਵੇਂ ਹੀ ਉਪਭੋਗਤਾ ਇਸਨੂੰ ਛੱਡ ਦੇਵੇ"</string> <string name="app_process_limit_title" msgid="4280600650253107163">"ਪਿਛੋਕੜ ਪ੍ਰਕਿਰਿਆ ਸੀਮਾ"</string> <string name="show_all_anrs" msgid="28462979638729082">"ਸਾਰੇ ANR ਦਿਖਾਓ"</string> - <string name="show_all_anrs_summary" msgid="641908614413544127">"ਪਿਛੋਕੜ ਐਪਸ ਲਈ ਐਪਸ ਜਵਾਬ ਨਹੀਂ ਦੇ ਰਹੇ ਡਾਇਲੌਗ ਦਿਖਾਓ"</string> + <string name="show_all_anrs_summary" msgid="641908614413544127">"ਬੈਕਗਰਾਊਂਡ ਐਪਾਂ ਲਈ ਐਪ ਜਵਾਬ ਨਹੀਂ ਦੇ ਰਹੇ ਡਾਇਲੌਗ ਦਿਖਾਓ"</string> <string name="show_notification_channel_warnings" msgid="1399948193466922683">"ਸੂਚਨਾ ਚੈਨਲ ਚੇਤਾਵਨੀਆਂ ਦਿਖਾਓ"</string> <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"ਐਪ ਵੱਲੋਂ ਵੈਧ ਚੈਨਲ ਤੋਂ ਬਿਨਾਂ ਸੂਚਨਾ ਪੋਸਟ ਕਰਨ \'ਤੇ ਸਕ੍ਰੀਨ \'ਤੇ ਚੇਤਾਵਨੀ ਦਿਖਾਉਂਦੀ ਹੈ"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"ਐਪਸ ਨੂੰ ਬਾਹਰਲੇ ਤੇ ਜ਼ਬਰਦਸਤੀ ਆਗਿਆ ਦਿਓ"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> ਬਾਕੀ"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"ਪੂਰੀ ਤਰ੍ਹਾਂ ਚਾਰਜ ਹੋਣ ਤੱਕ <xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"ਅਗਿਆਤ"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"ਚਾਰਜਿੰਗ"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ਚਾਰਜ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਿਹਾ"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"ਪਲੱਗ ਲੱਗਾ ਹੋਇਆ ਹੈ, ਇਸ ਸਮੇਂ ਚਾਰਜ ਨਹੀਂ ਹੋ ਸਕਦੀ"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"ਪੂਰੀ"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਕੰਟਰੋਲ ਕੀਤੀ ਗਈ"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"ਪ੍ਰਸ਼ਾਸਕ ਦੁਆਰਾ ਯੋਗ ਬਣਾਇਆ ਗਿਆ"</string> @@ -388,6 +390,6 @@ <string name="active_input_method_subtypes" msgid="3596398805424733238">"ਸਰਗਰਮ ਇਨਪੁਟ ਵਿਧੀਆਂ"</string> <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"ਸਿਸਟਮ ਭਾਸ਼ਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string> <string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> ਲਈ ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹਣ ਵਿੱਚ ਅਸਫਲ"</string> - <string name="ime_security_warning" msgid="4135828934735934248">"ਇਹ ਇਨਪੁਟ ਵਿਧੀ ਤੁਹਾਡੇ ਵੱਲੋਂ ਟਾਈਪ ਕੀਤਾ ਜਾਣ ਵਾਲਾ ਸਾਰਾ ਟੈਕਸਟ ਇਕੱਤਰ ਕਰਨ ਵਿੱਚ ਸਮਰੱਥ ਹੋ ਸਕਦਾ ਹੈ, ਨਿੱਜੀ ਡੈਟਾ ਸਮੇਤ ਜਿਵੇਂ ਪਾਸਵਰਡ ਅਤੇ ਕ੍ਰੈਡਿਟ ਕਾਰਡ ਨੰਬਰ। ਇਹ <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>ਐਪ ਤੋਂ ਆਉਂਦਾ ਹੈ। ਕੀ ਇਹ ਸਪੈੱਲ ਚੈਕਰ ਵਰਤਣਾ ਹੈ?"</string> + <string name="ime_security_warning" msgid="4135828934735934248">"ਇਹ ਇਨਪੁੱਟ ਵਿਧੀ ਤੁਹਾਡੇ ਵੱਲੋਂ ਟਾਈਪ ਕੀਤੇ ਜਾਣ ਵਾਲੀ ਸਾਰੀ ਲਿਖਤ ਇਕੱਤਰ ਕਰਨ ਵਿੱਚ ਸਮਰੱਥ ਹੋ ਸਕਦੀ ਹੈ, ਨਿੱਜੀ ਡਾਟਾ ਸਮੇਤ ਜਿਵੇਂ ਪਾਸਵਰਡ ਅਤੇ ਕ੍ਰੈਡਿਟ ਕਾਰਡ ਨੰਬਰ। ਇਹ <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>ਐਪ ਤੋਂ ਆਉਂਦਾ ਹੈ। ਕੀ ਇਸ ਇਨਪੁੱਟ ਵਿਧੀ ਨੂੰ ਵਰਤਣਾ ਹੈ?"</string> <string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"ਨੋਟ ਕਰੋ: ਰੀਬੂਟ ਤੋਂ ਬਾਅਦ, ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਆਪਣਾ ਫ਼ੋਨ ਅਨਲੌਕ ਨਹੀਂ ਕਰਦੇ ਤਦ ਤੱਕ ਇਹ ਐਪ ਚਾਲੂ ਨਹੀਂ ਹੋ ਸਕਦੀ"</string> </resources> diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml index 375615f7b801..94f497c923e5 100644 --- a/packages/SettingsLib/res/values-pl/arrays.xml +++ b/packages/SettingsLib/res/values-pl/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Użyj wyboru systemu (domyślnie)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Włącz opcjonalne kodeki"</item> - <item msgid="3304843301758635896">"Wyłącz opcjonalne kodeki"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Użyj wyboru systemu (domyślnie)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Włączenie opcjonalnych kodeków"</item> - <item msgid="741805482892725657">"Wyłączenie opcjonalnych kodeków"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Użyj wyboru systemu (domyślnie)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index a635a85f31b3..43cec530e828 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Zawsze szukaj Wi-Fi w roamingu"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilna transmisja danych zawsze aktywna"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Akceleracja sprzętowa tetheringu"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Wyłącz głośność bezwzględną"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Włącz dzwonek w kanale dźwiękowym"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Wersja AVRCP Bluetooth"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Te ustawienia są przeznaczone wyłącznie dla programistów. Ich użycie może spowodować uszkodzenie lub nieprawidłowe działanie urządzenia i zainstalowanych na nim aplikacji."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Zweryfikuj aplikacje przez USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Sprawdź, czy aplikacje zainstalowane przez ADB/ADT nie zachowują się w szkodliwy sposób"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Wyłącza funkcję Głośność bezwzględna Bluetooth, jeśli występują problemy z urządzeniami zdalnymi, np. zbyt duża głośność lub brak kontroli."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Zezwala na odtwarzanie dzwonków telefonu w zestawach słuchawkowych Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Terminal lokalny"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – zostało <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> do pełnego naładowania"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Nieznane"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Ładowanie"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ładowanie"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Nie podłączony"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Podłączony. Nie można teraz ładować"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Naładowana"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontrolowane przez administratora"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Włączone przez administratora"</string> diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml index e3f287bb3829..a5f5f5c0dc0a 100644 --- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml +++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"Usar seleção do sistema (padrão)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="2091430979086738145">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"Ativar codecs opcionais"</item> <item msgid="3304843301758635896">"Desativar codecs opcionais"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"Usar seleção do sistema (padrão)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="298198075927343893">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"Ativar codecs opcionais"</item> <item msgid="741805482892725657">"Desativar codecs opcionais"</item> diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml index 2e1855bfc332..526299388406 100644 --- a/packages/SettingsLib/res/values-pt-rBR/strings.xml +++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sempre permitir verif. de roaming de Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Dados móveis sempre ativos"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleração de hardware de tethering"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desativar volume absoluto"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Ativar o toque em banda"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versão do Bluetooth AVRCP"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Essas configurações são destinadas apenas para o uso de desenvolvedores. Elas podem causar a desativação ou mau funcionamento do dispositivo e dos apps contidos nele."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificar apps por USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Verificar comportamento nocivo em apps instalados via ADB/ADT."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desativa o recurso Bluetooth de volume absoluto em caso de problemas com o volume em dispositivos remotos, como volume excessivamente alto ou falta de controle."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Permitir que os toques no smartphone sejam reproduzidos em fones de ouvido Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> restante(s)"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> até a carga completa"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Carregando"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"carregando"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Não está carregando"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Conectado. Não é possível carregar no momento"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Cheio"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlada pelo admin"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Ativado pelo administrador"</string> diff --git a/packages/SettingsLib/res/values-pt-rPT/arrays.xml b/packages/SettingsLib/res/values-pt-rPT/arrays.xml index 3eeade0644d0..87dbe752c644 100644 --- a/packages/SettingsLib/res/values-pt-rPT/arrays.xml +++ b/packages/SettingsLib/res/values-pt-rPT/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"Utilizar seleção do sistema (predef.)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="2091430979086738145">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"Ativar codecs opcionais"</item> <item msgid="3304843301758635896">"Desativar codecs opcionais"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"Utilizar seleção do sistema (predef.)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="298198075927343893">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"Ativar codecs opcionais"</item> <item msgid="741805482892725657">"Desativar codecs opcionais"</item> diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index 02af40fc27d3..9ad38e1e2cf0 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir sempre a deteção de Wi-Fi em roaming"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Dados móveis sempre ativos"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleração de hardware para ligação (à Internet) via telemóvel"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desativar volume absoluto"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Ativar toque dentro da banda"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versão de Bluetooth AVRCP"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Estas definições destinam-se apenas a programação. Podem fazer com que o seu aparelho e as aplicações nele existentes falhem ou funcionem mal."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificar aplicações de USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Verificar as aplicações instaladas via ADB/ADT para detetar comportamento perigoso."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desativa a funcionalidade de volume absoluto do Bluetooth caso existam problemas de volume com dispositivos remotos, como um volume insuportavelmente alto ou a ausência de controlo."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Permitir que os toques no telemóvel sejam reproduzidos em auscultadores com microfone integrado Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – resta(m) <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> até ficar totalmente carregada"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"A carregar"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"a carregar…"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Não está a carregar"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Ligada à corrente, não é possível carregar neste momento"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Completo"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlado pelo administrador"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Ativada pelo administrador"</string> diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml index e3f287bb3829..a5f5f5c0dc0a 100644 --- a/packages/SettingsLib/res/values-pt/arrays.xml +++ b/packages/SettingsLib/res/values-pt/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"Usar seleção do sistema (padrão)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="2091430979086738145">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"Ativar codecs opcionais"</item> <item msgid="3304843301758635896">"Desativar codecs opcionais"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"Usar seleção do sistema (padrão)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="298198075927343893">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"Ativar codecs opcionais"</item> <item msgid="741805482892725657">"Desativar codecs opcionais"</item> diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml index 2e1855bfc332..526299388406 100644 --- a/packages/SettingsLib/res/values-pt/strings.xml +++ b/packages/SettingsLib/res/values-pt/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sempre permitir verif. de roaming de Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Dados móveis sempre ativos"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleração de hardware de tethering"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desativar volume absoluto"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Ativar o toque em banda"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versão do Bluetooth AVRCP"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Essas configurações são destinadas apenas para o uso de desenvolvedores. Elas podem causar a desativação ou mau funcionamento do dispositivo e dos apps contidos nele."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificar apps por USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Verificar comportamento nocivo em apps instalados via ADB/ADT."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desativa o recurso Bluetooth de volume absoluto em caso de problemas com o volume em dispositivos remotos, como volume excessivamente alto ou falta de controle."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Permitir que os toques no smartphone sejam reproduzidos em fones de ouvido Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> restante(s)"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> até a carga completa"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Carregando"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"carregando"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Não está carregando"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Conectado. Não é possível carregar no momento"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Cheio"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlada pelo admin"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Ativado pelo administrador"</string> diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml index 39ebb82345c0..3877bc952dea 100644 --- a/packages/SettingsLib/res/values-ro/arrays.xml +++ b/packages/SettingsLib/res/values-ro/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"Folosiți selectarea sist. (prestabilit)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="2091430979086738145">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"Activați codecurile opționale"</item> <item msgid="3304843301758635896">"Dezactivați codecurile opționale"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"Folosiți selectarea sist. (prestabilit)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="298198075927343893">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"Activați codecurile opționale"</item> <item msgid="741805482892725657">"Dezactivați codecurile opționale"</item> diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml index 3ecec0ebae6d..717d69028eff 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Se permite întotdeauna scanarea traficului Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Date mobile permanent active"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Accelerare hardware pentru tethering"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Dezactivați volumul absolut"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Activați soneria în căști"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versiunea AVRCP pentru Bluetooth"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Aceste setări sunt destinate exclusiv utilizării pentru dezvoltare. Din cauza lor, este posibil ca dispozitivul dvs. și aplicațiile de pe acesta să nu mai funcționeze sau să funcționeze necorespunzător."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificați aplicațiile prin USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Verificați aplicațiile instalate utilizând ADB/ADT, pentru a detecta un comportament dăunător."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Dezactivează funcția Bluetooth de volum absolut în cazul problemelor de volum apărute la dispozitivele la distanță, cum ar fi volumul mult prea ridicat sau lipsa de control asupra acestuia."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Permiteți ca tonurile de sonerie de pe telefon să fie redate prin căștile Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Aplicație terminal locală"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – timp rămas: <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> până la încărcarea completă"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Necunoscut"</string> - <string name="battery_info_status_charging" msgid="1705179948350365604">"Încarcă"</string> + <string name="battery_info_status_charging" msgid="1705179948350365604">"Se încarcă"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"se încarcă"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Nu se încarcă"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Conectat, nu se poate încărca chiar acum"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Complet"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlată de administrator"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Activat de administrator"</string> diff --git a/packages/SettingsLib/res/values-ru/arrays.xml b/packages/SettingsLib/res/values-ru/arrays.xml index 784e48e7031f..abebbe7664bd 100644 --- a/packages/SettingsLib/res/values-ru/arrays.xml +++ b/packages/SettingsLib/res/values-ru/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Выбор системы (по умолчанию)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Включить дополнительные кодеки"</item> - <item msgid="3304843301758635896">"Отключить дополнительные кодеки"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Выбор системы (по умолчанию)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Включить дополнительные кодеки"</item> - <item msgid="741805482892725657">"Отключить дополнительные кодеки"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Выбор системы (по умолчанию)"</item> <item msgid="8895532488906185219">"44,1 кГц"</item> diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index c35a1e1c7359..c51295df38ae 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Всегда включать поиск сетей Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Не отключать мобильный Интернет"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Аппаратное ускорение в режиме модема"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Отключить абсолютный уровень громкости"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Включить внутриполосное воспроизведение"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Версия Bluetooth AVRCP"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Только для разработчиков. Изменение этих настроек может привести к сбоям или неправильной работе устройства и приложений."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Проверять приложения при установке"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Выполнять проверку безопасности приложений при установке через ADB/ADT"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Отключить абсолютный уровень громкости Bluetooth при возникновении проблем на удаленных устройствах, например при слишком громком звучании или невозможности контролировать настройку."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Разрешить воспроизведение рингтонов на телефоне через Bluetooth-гарнитуру"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Локальный терминальный доступ"</string> @@ -276,12 +280,12 @@ <string name="debug_layout" msgid="5981361776594526155">"Показывать границы элементов"</string> <string name="debug_layout_summary" msgid="2001775315258637682">"Показывать границы обрезки, поля и т. п."</string> <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Отразить интерфейс"</string> - <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Включить написание справа налево для всех языков"</string> + <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Принудительно расположить элементы интерфейса справа налево во всех локалях"</string> <string name="force_hw_ui" msgid="6426383462520888732">"GPU-ускорение"</string> <string name="force_hw_ui_summary" msgid="5535991166074861515">"Всегда использовать GPU для двухмерного рисования"</string> <string name="force_msaa" msgid="7920323238677284387">"Включить 4x MSAA"</string> <string name="force_msaa_summary" msgid="9123553203895817537">"Включить 4x MSAA в приложениях OpenGL ES 2.0"</string> - <string name="show_non_rect_clip" msgid="505954950474595172">"Отладить операции непрямоугольного усечения"</string> + <string name="show_non_rect_clip" msgid="505954950474595172">"Отладка операций усечения сложной формы"</string> <string name="track_frame_time" msgid="6146354853663863443">"Профилировать GPU-отрисовку"</string> <string name="window_animation_scale_title" msgid="6162587588166114700">"Анимация окон"</string> <string name="transition_animation_scale_title" msgid="387527540523595875">"Анимация переходов"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g>, осталось: <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> до полной зарядки"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Неизвестно"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Идет зарядка"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"заряжается"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Не заряжается"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Подключено, не заряжается"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Батарея заряжена"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Контролируется администратором"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Включено администратором"</string> diff --git a/packages/SettingsLib/res/values-si/arrays.xml b/packages/SettingsLib/res/values-si/arrays.xml index 582c2482d1ec..60f951e2f683 100644 --- a/packages/SettingsLib/res/values-si/arrays.xml +++ b/packages/SettingsLib/res/values-si/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"පද්ධති තේරීම භාවිත කරන්න (පෙරනිමි)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ශ්රව්යය"</item> + <item msgid="2091430979086738145">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ශ්රව්යය"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"විකල්පමය කොඩෙක් සබල කරන්න"</item> <item msgid="3304843301758635896">"විකල්පමය කොඩෙක් අබල කරන්න"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"පද්ධති තේරීම භාවිත කරන්න (පෙරනිමි)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ශ්රව්යය"</item> + <item msgid="298198075927343893">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ශ්රව්යය"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"විකල්පමය කොඩෙක් සබල කරන්න"</item> <item msgid="741805482892725657">"විකල්පමය කොඩෙක් අබල කරන්න"</item> diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml index 5e8011a870d7..794272ba8394 100644 --- a/packages/SettingsLib/res/values-si/strings.xml +++ b/packages/SettingsLib/res/values-si/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi රෝම් පරිලෝකන වෙතට සැමවිට අවසර දෙන්න"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"ජංගම දත්ත සැමවිට ක්රියාකාරීය"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"ටෙදරින් දෘඪාංග ත්වරණය"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"නිරපේක්ෂ හඩ පරිමාව අබල කරන්න"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"කලාපය තුළ නාද වීම සබල කරන්න"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"බ්ලූටූත් AVRCP අනුවාදය"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"මෙම සැකසීම් වර්ධක භාවිතය සඳහා පමණි. ඔබගේ උපාංගයේ සහ යෙදුම්වල අක්රිය වීමට හෝ වැරදි ක්රියා කෙරුමකට ඒවා බලපෑ හැක."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB ඔස්සේ යෙදුම් සත්යාපනය කරගන්න"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT හරහා ස්ථාපනය වූ යෙදුම්, විනාශකාරී ක්රියාවන් ඇත්දැයි පරික්ෂාකර බලන්න."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"පිළිගත නොහැකි ලෙස වැඩි හඩ පරිමාව හෝ පාලනය නොමැති වීම යනාදී දුරස්ථ උපාංග සමගින් වන හඬ පරිමා ගැටලුවලදී බ්ලූටූත් නිරපේක්ෂ හඬ පරිමා විශේෂාංගය අබල කරයි."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"දුරකථනයේ නාද රටාවලට බ්ලූටූත් මත වාදනය වීමට ඉඩ දෙන්න"</string> <string name="enable_terminal_title" msgid="95572094356054120">"අභ්යන්තර අන්තය"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - ඉතිරි <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> සම්පූර්ණයෙන් ආරෝපණය වන තෙක්"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"නොදනී"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"ආරෝපණය වෙමින්"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ආරෝපණය වේ"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"ආරෝපණය නොවේ"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"පේනුගත කර ඇත, මේ අවස්ථාවේදී ආරෝපණය කළ නොහැකිය"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"පූර්ණ"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"පරිපාලක විසින් පාලනය කරන ලදී"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"පරිපාලක විසින් සබල කර ඇත"</string> @@ -365,7 +367,7 @@ <string name="disabled" msgid="9206776641295849915">"අබල කර ඇත"</string> <string name="external_source_trusted" msgid="2707996266575928037">"ඉඩ දුන්"</string> <string name="external_source_untrusted" msgid="2677442511837596726">"ඉඩ නොදෙන"</string> - <string name="install_other_apps" msgid="6986686991775883017">"නොදන්නා යෙදුම් ස්ථාපනය කරන්න"</string> + <string name="install_other_apps" msgid="6986686991775883017">"නොදන්නා යෙදුම් ස්ථාප."</string> <string name="home" msgid="3256884684164448244">"සැකසීම් මුල් පිටුව"</string> <string-array name="battery_labels"> <item msgid="8494684293649631252">"0%"</item> diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml index b7ac4353d3de..d28e53013d89 100644 --- a/packages/SettingsLib/res/values-sk/arrays.xml +++ b/packages/SettingsLib/res/values-sk/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Použiť voľbu systému (predvolené)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Povoliť voliteľné kodeky"</item> - <item msgid="3304843301758635896">"Zakázať voliteľné kodeky"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Použiť voľbu systému (predvolené)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Povoliť voliteľné kodeky"</item> - <item msgid="741805482892725657">"Zakázať voliteľné kodeky"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Použiť voľbu systému (predvolené)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> @@ -245,7 +229,7 @@ <item msgid="7899496259191969307">"Najviac 4 procesy"</item> </string-array> <string-array name="usb_configuration_titles"> - <item msgid="488237561639712799">"Nabíjanie"</item> + <item msgid="488237561639712799">"Nabíja sa"</item> <item msgid="5220695614993094977">"MTP (Media Transfer Protocol – protokol na prenos médií)"</item> <item msgid="2086000968159047375">"PTP (Picture Transfer Protocol – protokol na prenos obrázkov)"</item> <item msgid="7398830860950841822">"RNDIS (USB Ethernet)"</item> diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml index b81fee1f3d41..fd9b44985735 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -23,7 +23,7 @@ <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Siete sa nedajú vyhľadávať"</string> <string name="wifi_security_none" msgid="7985461072596594400">"Žiadne"</string> <string name="wifi_remembered" msgid="4955746899347821096">"Uložené"</string> - <string name="wifi_disabled_generic" msgid="4259794910584943386">"Zakázané"</string> + <string name="wifi_disabled_generic" msgid="4259794910584943386">"Vypnuté"</string> <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Zlyhanie konfigurácie adresy IP"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Nepripojené z dôvodu siete nízkej kvality"</string> <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Zlyhanie pripojenia Wi-Fi"</string> @@ -119,7 +119,7 @@ <string name="user_guest" msgid="8475274842845401871">"Hosť"</string> <string name="unknown" msgid="1592123443519355854">"Neznáme"</string> <string name="running_process_item_user_label" msgid="3129887865552025943">"Používateľ: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string> - <string name="launch_defaults_some" msgid="313159469856372621">"Predvolená pre niektoré akcie"</string> + <string name="launch_defaults_some" msgid="313159469856372621">"Pre niektoré akcie"</string> <string name="launch_defaults_none" msgid="4241129108140034876">"Nie je predvolená pre žiadne akcie"</string> <string name="tts_settings" msgid="8186971894801348327">"Nastavenia prevodu textu na reč"</string> <string name="tts_settings_title" msgid="1237820681016639683">"Prevod textu na reč"</string> @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vždy povoliť funkciu Wi-Fi Roam Scans"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilné dáta ponechať vždy aktívne"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardvérovú akcelerácia pre tethering"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Zakázať absolútnu hlasitosť"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Povoliť zvonenie v hovorovom pásme"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Verzia rozhrania Bluetooth AVRCP"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Tieto nastavenia sú určené len pre vývojárov. Môžu spôsobiť poruchu alebo nesprávne fungovanie zariadenia a nainštalovaných aplikácií."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Overovať aplikácie z USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrolovať škodlivosť aplikácií nainštalovaných pomocou nástroja ADB alebo ADT"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Umožňuje zakázať funkciu absolútnej hlasitosti rozhrania Bluetooth v prípade problémov s hlasitosťou na vzdialených zariadeniach, ako je napríklad neprijateľne vysoká hlasitosť alebo absencia ovládacích prvkov."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Umožňuje prehrávať tóny zvonenia na telefóne v náhlavných súpravách Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Miestny terminál"</string> @@ -333,7 +337,7 @@ <string name="button_convert_fbe" msgid="5152671181309826405">"Vymazať a konvertovať…"</string> <string name="picture_color_mode" msgid="4560755008730283695">"Farebný režim obrázka"</string> <string name="picture_color_mode_desc" msgid="1141891467675548590">"Použije sa sRGB"</string> - <string name="daltonizer_mode_disabled" msgid="7482661936053801862">"Zakázané"</string> + <string name="daltonizer_mode_disabled" msgid="7482661936053801862">"Vypnuté"</string> <string name="daltonizer_mode_monochromacy" msgid="8485709880666106721">"Monochromázia (úplna farbosleposť)"</string> <string name="daltonizer_mode_deuteranomaly" msgid="5475532989673586329">"Deuteranomália (červená a zelená)"</string> <string name="daltonizer_mode_protanomaly" msgid="8424148009038666065">"Protanomália (červená a zelená)"</string> @@ -351,18 +355,16 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – zostávajúci čas: <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> do úplného nabitia"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Neznáme"</string> - <string name="battery_info_status_charging" msgid="1705179948350365604">"Nabíjanie"</string> - <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"nabíjanie"</string> + <string name="battery_info_status_charging" msgid="1705179948350365604">"Nabíja sa"</string> + <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"nabíja sa"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Nenabíja sa"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Pripojené, ale nie je možné nabíjať"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Nabitá"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Ovládané správcom"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Povolené správcom"</string> <string name="disabled_by_admin" msgid="8505398946020816620">"Zakázané správcom"</string> - <string name="disabled" msgid="9206776641295849915">"Zakázané"</string> + <string name="disabled" msgid="9206776641295849915">"Deaktivované"</string> <string name="external_source_trusted" msgid="2707996266575928037">"Povolené"</string> <string name="external_source_untrusted" msgid="2677442511837596726">"Nie je povolené"</string> <string name="install_other_apps" msgid="6986686991775883017">"Inštalácia neznámych aplikácií"</string> diff --git a/packages/SettingsLib/res/values-sl/arrays.xml b/packages/SettingsLib/res/values-sl/arrays.xml index 5ffdd17f1407..e09524088469 100644 --- a/packages/SettingsLib/res/values-sl/arrays.xml +++ b/packages/SettingsLib/res/values-sl/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Uporabi sistemsko izbiro (privzeto)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Omogoči izbirne kodeke"</item> - <item msgid="3304843301758635896">"Onemogoči izbirne kodeke"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Uporabi sistemsko izbiro (privzeto)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Omogoči izbirne kodeke"</item> - <item msgid="741805482892725657">"Onemogoči izbirne kodeke"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Uporabi sistemsko izbiro (privzeto)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml index 4f3bce1f9ad1..0fbbfacd8f3f 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vedno omogoči iskanje omrežij Wi-Fi za gostovanje"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Prenos podatkov v mobilnem omrežju je vedno aktiven"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Strojno pospeševanje za internetno povezavo prek mobilnega telefona"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogočanje absolutnega praga glasnosti"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Omogoči zvonjenje iz telefona"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Različica profila AVRCP za Bluetooth"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Te nastavitve so namenjene samo za razvijanje in lahko povzročijo prekinitev ali napačno delovanje naprave in aplikacij v njej."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Preveri aplikacije prek USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Preveri, ali so aplikacije, nameščene prek ADB/ADT, škodljive."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Onemogoči funkcijo absolutnega praga glasnosti za Bluetooth, če pride do težav z glasnostjo z oddaljenimi napravami, kot je nesprejemljivo visoka glasnost ali pomanjkanje nadzora."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Omogoči, da se toni zvonjenja v telefonu predvajajo v slušalkah z mikrofonom Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Lokalni terminal"</string> @@ -351,20 +355,18 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – še <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> do napolnjenosti"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Neznano"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Polnjenje"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"polnjenje"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Se ne polni"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Priključeno, trenutno ni mogoče polniti"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Poln"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Nadzira skrbnik"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Omogočil skrbnik"</string> <string name="disabled_by_admin" msgid="8505398946020816620">"Onemogočil skrbnik"</string> <string name="disabled" msgid="9206776641295849915">"Onemogočeno"</string> <string name="external_source_trusted" msgid="2707996266575928037">"Dovoljene"</string> - <string name="external_source_untrusted" msgid="2677442511837596726">"Nedovoljene"</string> + <string name="external_source_untrusted" msgid="2677442511837596726">"Ni dovoljeno"</string> <string name="install_other_apps" msgid="6986686991775883017">"Nameščanje neznanih aplikacij"</string> <string name="home" msgid="3256884684164448244">"Začetna stran nastavitev"</string> <string-array name="battery_labels"> diff --git a/packages/SettingsLib/res/values-sq/arrays.xml b/packages/SettingsLib/res/values-sq/arrays.xml index 3db4250bac59..7fa2622db8ea 100644 --- a/packages/SettingsLib/res/values-sq/arrays.xml +++ b/packages/SettingsLib/res/values-sq/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Aktivizo kodekët opsionalë"</item> - <item msgid="3304843301758635896">"Çaktivizo kodekët opsionalë"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Aktivizo kodekët opsionalë"</item> - <item msgid="741805482892725657">"Çaktivizo kodekët opsionalë"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml index 0558c362f2f3..48e050641689 100644 --- a/packages/SettingsLib/res/values-sq/strings.xml +++ b/packages/SettingsLib/res/values-sq/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Lejo gjithmonë skanimet për Wi-Fi edhe kur je në lëvizje"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Të dhënat celulare gjithmonë aktive"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Përshpejtimi i harduerit për ndarjen"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Çaktivizo volumin absolut"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Aktivizo zilen brenda të njëjtit brez"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versioni AVRCP i Bluetooth-it"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Këto cilësime janë të projektuara vetëm për përdorim në programim. Ato mund të shkaktojnë që pajisja dhe aplikacionet në të, të mos punojnë ose të veprojnë në mënyrë të gabuar."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verifiko apl. përmes USB-së"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrollo aplikacionet e instaluara nëpërmjet ADB/ADT për sjellje të dëmshme."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Çaktivizon funksionin e volumit absolut të Bluetooth në rast të problemeve të volumit me pajisjet në largësi, si p.sh. një volum i lartë i papranueshëm ose mungesa e kontrollit."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Lejo që zilet në telefon të luhen në kufjet me \"Bluetooth\""</string> <string name="enable_terminal_title" msgid="95572094356054120">"Terminali lokal"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> të mbetura"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> derisa të mbushet plotësisht"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"I panjohur"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Po ngarkohet"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"po ngarkohet"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Nuk po ngarkohet"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Në prizë, por nuk mund të ngarkohet për momentin"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"E mbushur"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontrolluar nga administratori"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Aktivizuar nga administratori"</string> diff --git a/packages/SettingsLib/res/values-sr/arrays.xml b/packages/SettingsLib/res/values-sr/arrays.xml index ef1c9de94847..4e2d1021cd76 100644 --- a/packages/SettingsLib/res/values-sr/arrays.xml +++ b/packages/SettingsLib/res/values-sr/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Користи избор система (подразумевано)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Омогући опционалне кодеке"</item> - <item msgid="3304843301758635896">"Онемогући опционалне кодеке"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Користи избор система (подразумевано)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Омогући опционалне кодеке"</item> - <item msgid="741805482892725657">"Онемогући опционалне кодеке"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Користи избор система (подразумевано)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index f1506d277aa1..cb105f423cb3 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Увек дозволи скенирање Wi‑Fi-ја у ромингу"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Мобилни подаци су увек активни"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Хардверско убрзање привезивања"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Онемогући главно подешавање јачине звука"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Омогућавање звоњаве на истом каналу"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Верзија Bluetooth AVRCP-а"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Ова подешавања су намењена само за програмирање. Могу да изазову престанак функционисања или неочекивано понашање уређаја и апликација на њему."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Верификуј апликације преко USB-а"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Проверава да ли су апликације инсталиране преко ADB-а/ADT-а штетне."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Онемогућава главно подешавање јачине звука на Bluetooth уређају у случају проблема са јачином звука на даљинским уређајима, као што су изузетно велика јачина звука или недостатак контроле."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Омогућите да се мелодија звона на телефону пушта преко Bluetooth слушалица"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Локални терминал"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"Преостало је <xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> до потпуног пуњења"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Непознато"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Пуњење"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"пуни се"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Не пуни се"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Прикључено је, али пуњење тренутно није могуће"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Пуно"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Контролише администратор"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Омогућио је администратор"</string> diff --git a/packages/SettingsLib/res/values-sv/arrays.xml b/packages/SettingsLib/res/values-sv/arrays.xml index 23bb7977f934..b9b30be1433f 100644 --- a/packages/SettingsLib/res/values-sv/arrays.xml +++ b/packages/SettingsLib/res/values-sv/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Använd systemval (standardinställning)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Aktivera valfria kodekar"</item> - <item msgid="3304843301758635896">"Inaktivera valfria kodekar"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Använd systemval (standardinställning)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Aktivera valfria kodekar"</item> - <item msgid="741805482892725657">"Inaktivera valfria kodekar"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Använd systemval (standardinställning)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml index 97511cf01ca5..defbee940a78 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillåt alltid sökning efter Wi-Fi-roaming"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobildata alltid aktiverad"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Maskinvaruacceleration för internetdelning"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Inaktivera Absolute volume"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Aktivera samtal inom nätverket"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"AVRCP-version för Bluetooth"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Inställningarna är endast avsedda att användas för utvecklingsändamål. De kan orsaka problem med enheten eller apparna som finns installerade på den."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verifiera appar via USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrollera om appar som installeras via ADB/ADT kan vara skadliga."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Inaktivera Bluetooth-funktionen Absolute volume om det skulle uppstå problem med volymen på fjärrenheter, t.ex. alldeles för hög volym eller brist på kontroll."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Tillåt att ringsignaler på mobilen kan spelas upp i Bluetooth-headset"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Lokal terminal"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> kvar"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> tills det är fulladdat"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Okänd"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Laddar"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"laddas"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Laddar inte"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Inkopplad, kan inte laddas just nu"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Fullt"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Strys av administratören"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Aktiverad av administratör"</string> diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml index b5953a347c79..97b560a4f6cf 100644 --- a/packages/SettingsLib/res/values-sw/arrays.xml +++ b/packages/SettingsLib/res/values-sw/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"Tumia Uteuzi wa Mfumo (Chaguo-msingi)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="2091430979086738145">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"Washa Kodeki Zisizo za Lazima"</item> <item msgid="3304843301758635896">"Zima Kodeki Zisizo za Lazima"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"Tumia Uteuzi wa Mfumo (Chaguo-msingi)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="298198075927343893">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"Washa Kodeki Zisizo za Lazima"</item> <item msgid="741805482892725657">"Zima Kodeki Zisizo za Lazima"</item> diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index 6e4e85e1d732..a7fba53fc058 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Ruhusu Uchanganuzi wa Matumizi ya Mitandao mingine"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Iendelee kutumia data ya simu"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Kuongeza kasi kwa kutumia maunzi ili kusambaza mtandao"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Zima sauti kamili"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Washa kipengele cha mlio wa simu katika kituo hicho hicho"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Toleo la Bluetooth AVRCP"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Mipangilio hii imekusudiwa kwa matumizi ya usanidi tu. Inaweza kusababisha kifaa chako na programu zilizoko kuvunjika au kutofanya kazi vizuri."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Thibitisha programu kupitia USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kagua programu zilizosakinishwa kupitia ADB/ADT kwa tabia ya kudhuru."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Huzima kipengele cha Bluetooth cha sauti kamili kunapotokea matatizo ya sauti katika vifaa vya mbali kama vile sauti ya juu mno au inaposhindikana kuidhibiti."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Ruhusu milio ya simu kwenye simu ichezwe kwenye Vifaa vya sauti vya Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Kituo cha karibu"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"Imechaji <xliff:g id="LEVEL">^1</xliff:g> - Zimesalia <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> hadi ijae chaji"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Haijulikani"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Inachaji"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"inachaji"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Haichaji"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Haiwezi kuchaji kwa sasa"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Imejaa"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Imedhibitiwa na msimamizi"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Imewashwa na msimamizi"</string> @@ -365,7 +367,7 @@ <string name="disabled" msgid="9206776641295849915">"Imezimwa"</string> <string name="external_source_trusted" msgid="2707996266575928037">"Imeruhusiwa"</string> <string name="external_source_untrusted" msgid="2677442511837596726">"Hairuhusiwi"</string> - <string name="install_other_apps" msgid="6986686991775883017">"Sakinisha programu ambazo hazijulikani"</string> + <string name="install_other_apps" msgid="6986686991775883017">"Kuweka programu zisizojulikana"</string> <string name="home" msgid="3256884684164448244">"Ukurasa wa Kwanza wa Mipangilio"</string> <string-array name="battery_labels"> <item msgid="8494684293649631252">"0%"</item> diff --git a/packages/SettingsLib/res/values-ta/arrays.xml b/packages/SettingsLib/res/values-ta/arrays.xml index 96c9122357ed..1c28912eb3fa 100644 --- a/packages/SettingsLib/res/values-ta/arrays.xml +++ b/packages/SettingsLib/res/values-ta/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"சாதனத் தேர்வைப் பயன்படுத்து (இயல்பு)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"கட்டாயமில்லா கோடெக்குகளை இயக்கு"</item> - <item msgid="3304843301758635896">"கட்டாயமில்லா கோடெக்குகளை முடக்கு"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"சாதனத் தேர்வைப் பயன்படுத்து (இயல்பு)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"கட்டாயமில்லா கோடெக்குகளை இயக்கு"</item> - <item msgid="741805482892725657">"கட்டாயமில்லா கோடெக்குகளை முடக்கு"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"சாதனத் தேர்வைப் பயன்படுத்து (இயல்பு)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml index e707596ad62d..c2fc83e1dd1c 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"எப்போதும் வைஃபை ரோமிங் ஸ்கேன்களை அனுமதி"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"மொபைல் தரவை எப்போதும் இயக்கத்திலேயே வை"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"வன்பொருள் விரைவுப்படுத்துதல் இணைப்பு முறை"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"அப்சல்யூட் ஒலியளவு அம்சத்தை முடக்கு"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"இன்-பேண்ட் ரிங் செய்வதை இயக்கு"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"புளூடூத் AVRCP பதிப்பு"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"இந்த அமைப்பு மேம்பட்டப் பயன்பாட்டிற்காக மட்டுமே. உங்கள் சாதனம் மற்றும் அதில் உள்ள பயன்பாடுகளைச் சிதைக்கும் அல்லது தவறாகச் செயல்படும் வகையில் பாதிப்பை ஏற்படுத்தும்."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB பயன்பாடுகளை சரிபார்"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"தீங்கு விளைவிக்கும் செயல்பாட்டை அறிய ADB/ADT மூலம் நிறுவப்பட்டப் பயன்பாடுகளைச் சரிபார்."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"மிகவும் அதிகமான ஒலியளவு அல்லது கட்டுப்பாடு இழப்பு போன்ற தொலைநிலைச் சாதனங்களில் ஏற்படும் ஒலி தொடர்பான சிக்கல்கள் இருக்கும் சமயங்களில், புளூடூத் அப்சல்யூட் ஒலியளவு அம்சத்தை முடக்கும்."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ஃபோனில் இருக்கும் ரிங்டோன்களை, புளூடூத் ஹெட்செட்களில் இயக்க அனுமதி"</string> <string name="enable_terminal_title" msgid="95572094356054120">"அக முனையம்"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> மீதமுள்ளது"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - முழு சார்ஜாக <xliff:g id="TIME">^2</xliff:g> ஆகும்"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"அறியப்படாத"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"சார்ஜ் ஏற்றப்படுகிறது"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"சார்ஜாகிறது"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"சார்ஜ் செய்யப்படவில்லை"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"செருகப்பட்டது, ஆனால் இப்போது சார்ஜ் செய்ய முடியவில்லை"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"முழுமை"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"நிர்வாகி கட்டுப்படுத்துகிறார்"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"நிர்வாகி இயக்கியுள்ளார்"</string> diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml index cc771390d7b2..fbdfbe1ace66 100644 --- a/packages/SettingsLib/res/values-te/arrays.xml +++ b/packages/SettingsLib/res/values-te/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"సిస్టమ్ ఎంపికను ఉపయోగించండి (డిఫాల్ట్)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"ఐచ్ఛిక కోడెక్లను ప్రారంభించు"</item> - <item msgid="3304843301758635896">"ఐచ్ఛిక కోడెక్లను నిలిపివేయి"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"సిస్టమ్ ఎంపికను ఉపయోగించండి (డిఫాల్ట్)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"ఐచ్ఛిక కోడెక్లను ప్రారంభించు"</item> - <item msgid="741805482892725657">"ఐచ్ఛిక కోడెక్లను నిలిపివేయి"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"సిస్టమ్ ఎంపికను ఉపయోగించండి (డిఫాల్ట్)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index 20e8931ed73e..2b8795ae1f3b 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -33,14 +33,14 @@ <string name="wifi_check_password_try_again" msgid="516958988102584767">"పాస్వర్డ్ను తనిఖీ చేసి, మళ్లీ ప్రయత్నించండి"</string> <string name="wifi_not_in_range" msgid="1136191511238508967">"పరిధిలో లేదు"</string> <string name="wifi_no_internet_no_reconnect" msgid="5724903347310541706">"స్వయంచాలకంగా కనెక్ట్ కాదు"</string> - <string name="wifi_no_internet" msgid="3880396223819116454">"ఇంటర్నెట్ ప్రాప్యత లేదు"</string> + <string name="wifi_no_internet" msgid="3880396223819116454">"ఇంటర్నెట్ యాక్సెస్ లేదు"</string> <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> ద్వారా సేవ్ చేయబడింది"</string> <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s ద్వారా స్వయంచాలకంగా కనెక్ట్ చేయబడింది"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"నెట్వర్క్ రేటింగ్ ప్రదాత ద్వారా స్వయంచాలకంగా కనెక్ట్ చేయబడింది"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s ద్వారా కనెక్ట్ చేయబడింది"</string> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s ద్వారా అందుబాటులో ఉంది"</string> <string name="wifi_connected_no_internet" msgid="3149853966840874992">"కనెక్ట్ చేయబడింది, ఇంటర్నెట్ లేదు"</string> - <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ప్రాప్యత పాయింట్ తాత్కాలికంగా పూర్తయింది"</string> + <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"యాక్సెస్ పాయింట్ తాత్కాలికంగా నిండుకుంది"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s ద్వారా కనెక్ట్ చేయబడింది"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s ద్వారా అందుబాటులో ఉంది"</string> <string name="speed_label_very_slow" msgid="1867055264243608530">"చాలా నెమ్మది"</string> @@ -57,7 +57,7 @@ <string name="bluetooth_pairing" msgid="1426882272690346242">"జత చేస్తోంది..."</string> <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"కనెక్ట్ చేయబడింది (ఫోన్ కాదు)"</string> <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"కనెక్ట్ చేయబడింది (మీడియా కాదు)"</string> - <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"కనెక్ట్ చేయబడింది (సందేశ ప్రాప్యత లేదు)"</string> + <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"కనెక్ట్ చేయబడింది (సందేశ యాక్సెస్ లేదు)"</string> <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"కనెక్ట్ చేయబడింది (ఫోన్ లేదా మీడియా కాకుండా)"</string> <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"కనెక్ట్ చేయబడింది, బ్యాటరీ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"కనెక్ట్ చేయబడింది (ఫోన్ కాదు), బ్యాటరీ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> @@ -67,12 +67,12 @@ <string name="bluetooth_profile_headset" msgid="7815495680863246034">"ఫోన్ కాల్లు"</string> <string name="bluetooth_profile_opp" msgid="9168139293654233697">"ఫైల్ బదిలీ"</string> <string name="bluetooth_profile_hid" msgid="3680729023366986480">"ఇన్పుట్ పరికరం"</string> - <string name="bluetooth_profile_pan" msgid="3391606497945147673">"ఇంటర్నెట్ ప్రాప్యత"</string> + <string name="bluetooth_profile_pan" msgid="3391606497945147673">"ఇంటర్నెట్ యాక్సెస్"</string> <string name="bluetooth_profile_pbap" msgid="5372051906968576809">"పరిచయ భాగస్వామ్యం"</string> <string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"పరిచయ భాగస్వామ్యం కోసం ఉపయోగించు"</string> <string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"ఇంటర్నెట్ కనెక్షన్ భాగస్వామ్యం"</string> <string name="bluetooth_profile_map" msgid="1019763341565580450">"వచన సందేశాలు"</string> - <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM ప్రాప్యత"</string> + <string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM యాక్సెస్"</string> <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ఆడియో: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string> <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ఆడియో"</string> <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"మీడియా ఆడియోకు కనెక్ట్ చేయబడింది"</string> @@ -82,11 +82,11 @@ <string name="bluetooth_sap_profile_summary_connected" msgid="8561765057453083838">"SAPకి కనెక్ట్ చేయబడింది"</string> <string name="bluetooth_opp_profile_summary_not_connected" msgid="1267091356089086285">"ఫైల్ బదిలీ సర్వర్కు కనెక్ట్ చేయబడలేదు"</string> <string name="bluetooth_hid_profile_summary_connected" msgid="3381760054215168689">"ఇన్పుట్ పరికరానికి కనెక్ట్ చేయబడింది"</string> - <string name="bluetooth_pan_user_profile_summary_connected" msgid="4602294638909590612">"ఇంటర్నెట్ ప్రాప్యత కోసం పరికరానికి కనెక్ట్ చేయబడింది"</string> + <string name="bluetooth_pan_user_profile_summary_connected" msgid="4602294638909590612">"ఇంటర్నెట్ యాక్సెస్ కోసం పరికరానికి కనెక్ట్ చేయబడింది"</string> <string name="bluetooth_pan_nap_profile_summary_connected" msgid="1561383706411975199">"స్థానిక ఇంటర్నెట్ కనెక్షన్ను పరికరంతో భాగస్వామ్యం చేయడం"</string> - <string name="bluetooth_pan_profile_summary_use_for" msgid="5664884523822068653">"ఇంటర్నెట్ ప్రాప్యత కోసం ఉపయోగించు"</string> + <string name="bluetooth_pan_profile_summary_use_for" msgid="5664884523822068653">"ఇంటర్నెట్ యాక్సెస్ కోసం ఉపయోగించు"</string> <string name="bluetooth_map_profile_summary_use_for" msgid="5154200119919927434">"మ్యాప్ కోసం ఉపయోగించు"</string> - <string name="bluetooth_sap_profile_summary_use_for" msgid="7085362712786907993">"SIM ప్రాప్యత కోసం ఉపయోగించబడుతుంది"</string> + <string name="bluetooth_sap_profile_summary_use_for" msgid="7085362712786907993">"SIM యాక్సెస్ కోసం ఉపయోగించబడుతుంది"</string> <string name="bluetooth_a2dp_profile_summary_use_for" msgid="4630849022250168427">"మీడియా ఆడియో కోసం ఉపయోగించు"</string> <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ఫోన్ ఆడియో కోసం ఉపయోగించు"</string> <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ఫైల్ బదిలీ కోసం ఉపయోగించు"</string> @@ -96,7 +96,7 @@ <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"రద్దు చేయి"</string> <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"జత చేయడం వలన కనెక్ట్ చేయబడినప్పుడు మీ పరిచయాలకు మరియు కాల్ చరిత్రకు ప్రాప్యతను మంజూరు చేస్తుంది."</string> <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>తో జత చేయడం సాధ్యపడలేదు."</string> - <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"పిన్ లేదా పాస్కీ చెల్లని కారణంగా <xliff:g id="DEVICE_NAME">%1$s</xliff:g>తో జత చేయడం సాధ్యపడలేదు."</string> + <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"పిన్ లేదా పాస్కీ చెల్లని కారణంగా <xliff:g id="DEVICE_NAME">%1$s</xliff:g>తో జత చేయడం సాధ్యపడలేదు."</string> <string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>తో కమ్యూనికేట్ చేయడం సాధ్యపడదు."</string> <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> జత చేయడాన్ని తిరస్కరించింది."</string> <string name="accessibility_wifi_off" msgid="1166761729660614716">"Wifi ఆఫ్లో ఉంది."</string> @@ -169,11 +169,11 @@ <string name="development_settings_not_available" msgid="4308569041701535607">"ఈ వినియోగదారు కోసం డెవలపర్ ఎంపికలు అందుబాటులో లేవు"</string> <string name="vpn_settings_not_available" msgid="956841430176985598">"VPN సెట్టింగ్లు ఈ వినియోగదారుకి అందుబాటులో లేవు"</string> <string name="tethering_settings_not_available" msgid="6765770438438291012">"టీథరింగ్ సెట్టింగ్లు ఈ వినియోగదారుకి అందుబాటులో లేవు"</string> - <string name="apn_settings_not_available" msgid="7873729032165324000">"ప్రాప్యత స్థానం పేరు సెట్టింగ్లు ఈ వినియోగదారుకి అందుబాటులో లేవు"</string> + <string name="apn_settings_not_available" msgid="7873729032165324000">"యాక్సెస్ స్థానం పేరు సెట్టింగ్లు ఈ వినియోగదారుకి అందుబాటులో లేవు"</string> <string name="enable_adb" msgid="7982306934419797485">"USB డీబగ్గింగ్"</string> <string name="enable_adb_summary" msgid="4881186971746056635">"USB కనెక్ట్ చేయబడినప్పుడు డీబగ్ మోడ్"</string> <string name="clear_adb_keys" msgid="4038889221503122743">"USB డీబగ్ ప్రామాణీకరణలను ఉపసంహరించు"</string> - <string name="bugreport_in_power" msgid="7923901846375587241">"బగ్ నివేదిక సత్వరమార్గం"</string> + <string name="bugreport_in_power" msgid="7923901846375587241">"బగ్ నివేదిక షార్ట్కట్"</string> <string name="bugreport_in_power_summary" msgid="1778455732762984579">"బగ్ నివేదికను తీసుకోవడానికి పవర్ మెనులో బటన్ను చూపు"</string> <string name="keep_screen_on" msgid="1146389631208760344">"సక్రియంగా ఉంచు"</string> <string name="keep_screen_on_summary" msgid="2173114350754293009">"ఛార్జ్ చేస్తున్నప్పుడు స్క్రీన్ ఎప్పటికీ నిద్రావస్థలోకి వెళ్లదు"</string> @@ -184,8 +184,8 @@ <string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"OEM అన్లాకింగ్ను అనుమతించాలా?"</string> <string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"హెచ్చరిక: ఈ సెట్టింగ్ ఆన్ చేయబడినప్పుడు పరికరం రక్షణ లక్షణాలు ఈ పరికరంలో పని చేయవు."</string> <string name="mock_location_app" msgid="7966220972812881854">"అనుకృత స్థాన అనువర్తనాన్ని ఎంచుకోండి"</string> - <string name="mock_location_app_not_set" msgid="809543285495344223">"అనుకృత స్థాన అనువర్తనం ఏదీ సెట్ చేయబడలేదు"</string> - <string name="mock_location_app_set" msgid="8966420655295102685">"అనుకృత స్థాన అనువర్తనం: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="mock_location_app_not_set" msgid="809543285495344223">"అనుకృత స్థాన యాప్ ఏదీ సెట్ చేయబడలేదు"</string> + <string name="mock_location_app_set" msgid="8966420655295102685">"అనుకృత స్థాన యాప్: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="debug_networking_category" msgid="7044075693643009662">"నెట్వర్కింగ్"</string> <string name="wifi_display_certification" msgid="8611569543791307533">"వైర్లెస్ ప్రదర్శన ప్రమాణీకరణ"</string> <string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi విశదీకృత లాగింగ్ను ప్రారంభించండి"</string> @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi సంచార స్కాన్లను ఎల్లప్పుడూ అనుమతించు"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"మొబైల్ డేటాని ఎల్లప్పుడూ సక్రియంగా ఉంచు"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"టీథెరింగ్ హార్డ్వేర్ వేగవృద్ధి"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"సంపూర్ణ వాల్యూమ్ను నిలిపివేయి"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"ఇన్-బ్యాండ్ రింగింగ్ని ప్రారంభించండి"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"బ్లూటూత్ AVRCP సంస్కరణ"</string> @@ -229,9 +231,11 @@ <string name="adb_warning_message" msgid="7316799925425402244">"USB డీబగ్గింగ్ అనేది అభివృద్ధి ప్రయోజనాల కోసం మాత్రమే ఉద్దేశించబడింది. మీ కంప్యూటర్ మరియు మీ పరికరం మధ్య డేటాను కాపీ చేయడానికి, నోటిఫికేషన్ లేకుండా మీ పరికరంలో అనువర్తనాలను ఇన్స్టాల్ చేయడానికి మరియు లాగ్ డేటాను చదవడానికి దీన్ని ఉపయోగించండి."</string> <string name="adb_keys_warning_message" msgid="5659849457135841625">"మీరు గతంలో ప్రామాణీకరించిన అన్ని కంప్యూటర్ల నుండి USB డీబగ్గింగ్కు ప్రాప్యతను ఉపసంహరించాలా?"</string> <string name="dev_settings_warning_title" msgid="7244607768088540165">"అభివృద్ధి సెట్టింగ్లను అనుమతించాలా?"</string> - <string name="dev_settings_warning_message" msgid="2298337781139097964">"ఈ సెట్టింగ్లు అభివృద్ధి వినియోగం కోసం మాత్రమే ఉద్దేశించబడినవి. వీటి వలన మీ పరికరం మరియు దీనిలోని అనువర్తనాలు విచ్ఛిన్నం కావచ్చు లేదా తప్పుగా ప్రవర్తించవచ్చు."</string> + <string name="dev_settings_warning_message" msgid="2298337781139097964">"ఈ సెట్టింగ్లు అభివృద్ధి వినియోగం కోసం మాత్రమే ఉద్దేశించబడినవి. వీటి వలన మీ పరికరం మరియు దీనిలోని యాప్లు విచ్ఛిన్నం కావచ్చు లేదా తప్పుగా ప్రవర్తించవచ్చు."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB ద్వారా అనువర్తనాలను ధృవీకరించు"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"హానికరమైన ప్రవర్తన కోసం ADB/ADT ద్వారా ఇన్స్టాల్ చేయబడిన అనువర్తనాలను తనిఖీ చేయి."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"రిమోట్ పరికరాల్లో ఆమోదించలేని స్థాయిలో అధిక వాల్యూమ్ ఉండటం లేదా వాల్యూమ్ నియంత్రణ లేకపోవడం వంటి సమస్యలు ఉంటే బ్లూటూత్ సంపూర్ణ వాల్యూమ్ లక్షణాన్ని నిలిపివేస్తుంది."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"బ్లూటూత్ హెడ్సెట్లలో ప్లే చేయడానికి ఫోన్లో రింగ్టోన్లను అనుమతించండి"</string> <string name="enable_terminal_title" msgid="95572094356054120">"స్థానిక టెర్మినల్"</string> @@ -240,12 +244,12 @@ <string name="hdcp_checking_dialog_title" msgid="5141305530923283">"HDCP తనిఖీ ప్రవర్తనను సెట్ చేయండి"</string> <string name="debug_debugging_category" msgid="6781250159513471316">"డీబగ్గింగ్"</string> <string name="debug_app" msgid="8349591734751384446">"డీబగ్ అనువర్తనాన్ని ఎంచుకోండి"</string> - <string name="debug_app_not_set" msgid="718752499586403499">"డీబగ్ అనువర్తనం సెట్ చేయబడలేదు"</string> - <string name="debug_app_set" msgid="2063077997870280017">"డీబగ్గింగ్ అనువర్తనం: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="debug_app_not_set" msgid="718752499586403499">"డీబగ్ యాప్ సెట్ చేయబడలేదు"</string> + <string name="debug_app_set" msgid="2063077997870280017">"డీబగ్గింగ్ యాప్: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="select_application" msgid="5156029161289091703">"అనువర్తనాన్ని ఎంచుకోండి"</string> <string name="no_application" msgid="2813387563129153880">"ఏదీ వద్దు"</string> <string name="wait_for_debugger" msgid="1202370874528893091">"డీబగ్గర్ కోసం వేచి ఉండండి"</string> - <string name="wait_for_debugger_summary" msgid="1766918303462746804">"డీబగ్ చేయబడిన అనువర్తనం అమలు కావడానికి ముందు జోడించాల్సిన డీబగ్గర్ కోసం వేచి ఉంటుంది"</string> + <string name="wait_for_debugger_summary" msgid="1766918303462746804">"డీబగ్ చేయబడిన యాప్ అమలు కావడానికి ముందు జోడించాల్సిన డీబగ్గర్ కోసం వేచి ఉంటుంది"</string> <string name="telephony_monitor_switch" msgid="1764958220062121194">"టెలిఫోనీ మానిటర్"</string> <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"టెలిఫోనీ/మోడెమ్ కార్యాచరణలో సమస్యను గుర్తించినప్పుడు TelephonyMonitor లాగ్లను సేకరిస్తుంది మరియు బగ్ని ఫైల్ చేయమని వినియోగదారును ప్రోత్సహిస్తుంది"</string> <string name="debug_input_category" msgid="1811069939601180246">"ఇన్పుట్"</string> @@ -259,11 +263,11 @@ <string name="pointer_location_summary" msgid="840819275172753713">"ప్రస్తుత స్పర్శ డేటాను చూపేలా స్క్రీన్ అతివ్యాప్తి చేయండి"</string> <string name="show_touches" msgid="2642976305235070316">"నొక్కినవి చూపు"</string> <string name="show_touches_summary" msgid="6101183132903926324">"నొక్కినవాటికి సంబంధించిన దృశ్య అభిప్రాయాన్ని చూపు"</string> - <string name="show_screen_updates" msgid="5470814345876056420">"సర్ఫేస్ నవీకరణలను చూపండి"</string> + <string name="show_screen_updates" msgid="5470814345876056420">"సర్ఫేస్ అప్డేట్లను చూపండి"</string> <string name="show_screen_updates_summary" msgid="2569622766672785529">"పూర్తి విండో ఉపరితలాలు నవీకరించబడినప్పుడు వాటిని ఫ్లాష్ చేయండి"</string> - <string name="show_hw_screen_updates" msgid="5036904558145941590">"GPU వీక్షణ నవీకరణలను చూపండి"</string> + <string name="show_hw_screen_updates" msgid="5036904558145941590">"GPU వీక్షణ అప్డేట్లను చూపండి"</string> <string name="show_hw_screen_updates_summary" msgid="1115593565980196197">"GPUతో గీసినప్పుడు విండోల లోపల వీక్షణలను ఫ్లాష్ చేయండి"</string> - <string name="show_hw_layers_updates" msgid="5645728765605699821">"హార్డ్వేర్ లేయర్ల నవీకరణలను చూపండి"</string> + <string name="show_hw_layers_updates" msgid="5645728765605699821">"హార్డ్వేర్ లేయర్ల అప్డేట్లను చూపండి"</string> <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"హార్డ్వేర్ లేయర్లు నవీకరించబడినప్పుడు వాటిని ఆకుపచ్చ రంగులో ఫ్లాష్ చేయండి"</string> <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ఓవర్డ్రాను డీబగ్ చేయండి"</string> <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU Rendererని సెట్ చేయండి"</string> @@ -287,14 +291,14 @@ <string name="transition_animation_scale_title" msgid="387527540523595875">"పరివర్తన యానిమేషన్ ప్రమాణం"</string> <string name="animator_duration_scale_title" msgid="3406722410819934083">"యానిమేటర్ వ్యవధి ప్రమాణం"</string> <string name="overlay_display_devices_title" msgid="5364176287998398539">"ప్రత్యామ్నాయ ప్రదర్శనలను అనుకరించండి"</string> - <string name="debug_applications_category" msgid="4206913653849771549">"అనువర్తనాలు"</string> + <string name="debug_applications_category" msgid="4206913653849771549">"యాప్లు"</string> <string name="immediately_destroy_activities" msgid="1579659389568133959">"కార్యాచరణలను ఉంచవద్దు"</string> <string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"ప్రతి కార్యాచరణను వినియోగదారు నిష్క్రమించిన వెంటనే తొలగించండి"</string> <string name="app_process_limit_title" msgid="4280600650253107163">"నేపథ్య ప్రాసెస్ పరిమితి"</string> <string name="show_all_anrs" msgid="28462979638729082">"అన్ని ANRలను చూపు"</string> - <string name="show_all_anrs_summary" msgid="641908614413544127">"నేపథ్య అనువర్తనాల కోసం అనువర్తనం ప్రతిస్పందించడం లేదు డైలాగ్ను చూపు"</string> + <string name="show_all_anrs_summary" msgid="641908614413544127">"నేపథ్య యాప్ల కోసం యాప్ ప్రతిస్పందించడం లేదు డైలాగ్ను చూపు"</string> <string name="show_notification_channel_warnings" msgid="1399948193466922683">"ఛానెల్ హెచ్చరికల నోటిఫికేషన్ను చూపు"</string> - <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"చెల్లుబాటు అయ్యే ఛానెల్ లేకుండా అనువర్తనం నోటిఫికేషన్ను పోస్ట్ చేస్తున్నప్పుడు స్క్రీన్పై హెచ్చరికను చూపిస్తుంది"</string> + <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"చెల్లుబాటు అయ్యే ఛానెల్ లేకుండా యాప్ నోటిఫికేషన్ను పోస్ట్ చేస్తున్నప్పుడు స్క్రీన్పై హెచ్చరికను చూపిస్తుంది"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"అనువర్తనాలను బాహ్య నిల్వలో నిర్బంధంగా అనుమతించు"</string> <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ఏ అనువర్తనాన్ని అయినా మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా బాహ్య నిల్వలో వ్రాయడానికి అనుమతిస్తుంది"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"కార్యాచరణలను పరిమాణం మార్చగలిగేలా నిర్బంధించు"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> మిగిలి ఉంది"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"తెలియదు"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"ఛార్జ్ అవుతోంది"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ఛార్జ్ అవుతోంది"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"ఛార్జ్ కావడం లేదు"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"ప్లగ్ ఇన్ చేయబడింది, ప్రస్తుతం ఛార్జ్ చేయడం సాధ్యం కాదు"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"నిండింది"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"నిర్వాహకుని ద్వారా నియంత్రించబడింది"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"నిర్వాహకులు ప్రారంభించారు"</string> @@ -365,7 +367,7 @@ <string name="disabled" msgid="9206776641295849915">"నిలిపివేయబడింది"</string> <string name="external_source_trusted" msgid="2707996266575928037">"అనుమతించినవి"</string> <string name="external_source_untrusted" msgid="2677442511837596726">"అనుమతించబడలేదు"</string> - <string name="install_other_apps" msgid="6986686991775883017">"తెలియని అనువర్తనాలను ఇన్స్టాల్ చేయండి"</string> + <string name="install_other_apps" msgid="6986686991775883017">"తెలియని యాప్లను ఇన్స్టాల్ చేయండి"</string> <string name="home" msgid="3256884684164448244">"సెట్టింగ్ల హోమ్"</string> <string-array name="battery_labels"> <item msgid="8494684293649631252">"0%"</item> @@ -389,5 +391,5 @@ <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"సిస్టమ్ భాషలను ఉపయోగించు"</string> <string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> యొక్క సెట్టింగ్లను తెరవడం విఫలమైంది"</string> <string name="ime_security_warning" msgid="4135828934735934248">"ఈ ఇన్పుట్ పద్ధతి మీరు టైప్ చేసే మొత్తం వచనాన్ని అలాగే పాస్వర్డ్లు మరియు క్రెడిట్ కార్డు నంబర్ల వంటి వ్యక్తిగత డేటాను సేకరించగలదు. ఇది <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> అనువర్తనంలో అందించబడుతుంది. ఈ ఇన్పుట్ పద్ధతిని ఉపయోగించాలా?"</string> - <string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"గమనిక: రీబూట్ చేసాక, మీరు మీ ఫోన్ను అన్లాక్ చేసే వరకు ఈ అనువర్తనం ప్రారంభం కాదు"</string> + <string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"గమనిక: రీబూట్ చేసాక, మీరు మీ ఫోన్ను అన్లాక్ చేసే వరకు ఈ యాప్ ప్రారంభం కాదు"</string> </resources> diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml index d46fc7d2c616..201db5bb6ca9 100644 --- a/packages/SettingsLib/res/values-th/arrays.xml +++ b/packages/SettingsLib/res/values-th/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"ใช้การเลือกระบบ (ค่าเริ่มต้น)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"เปิดใช้ตัวแปลงรหัสที่ไม่บังคับ"</item> - <item msgid="3304843301758635896">"ปิดใช้ตัวแปลงรหัสที่ไม่บังคับ"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"ใช้การเลือกระบบ (ค่าเริ่มต้น)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"เปิดใช้ตัวแปลงรหัสที่ไม่บังคับ"</item> - <item msgid="741805482892725657">"ปิดใช้ตัวแปลงรหัสที่ไม่บังคับ"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"ใช้การเลือกระบบ (ค่าเริ่มต้น)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml index ef215848fd44..8b49036f2114 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ใช้การสแกน Wi-Fi ข้ามเครือข่ายเสมอ"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"เปิดใช้อินเทอร์เน็ตมือถือเสมอ"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"การเร่งฮาร์ดแวร์การเชื่อมต่ออินเทอร์เน็ตผ่านมือถือ"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ปิดใช้การควบคุมระดับเสียงของอุปกรณ์อื่น"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"เปิดใช้การส่งเสียงในช่องสัญญาณเดียวกัน"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"เวอร์ชันของบลูทูธ AVRCP"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"การตั้งค่านี้มีไว้เพื่อการพัฒนาเท่านั้น จึงอาจทำให้อุปกรณ์และแอปพลิเคชันที่มีอยู่เสียหายหรือทำงานผิดพลาดได้"</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"ยืนยันแอปพลิเคชันผ่าน USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ตรวจสอบแอปพลิเคชันที่ติดตั้งผ่าน ADB/ADT เพื่อตรวจดูพฤติกรรมที่เป็นอันตราย"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ปิดใช้ฟีเจอร์การควบคุมระดับเสียงของอุปกรณ์อื่นผ่านบลูทูธในกรณีที่มีปัญหาเกี่ยวกับระดับเสียงของอุปกรณ์ระยะไกล เช่น ระดับเสียงที่ดังเกินไปหรือระดับเสียงที่ไม่มีการควบคุม"</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ให้เสียงเรียกเข้าในโทรศัพท์เล่นในชุดหูฟังบลูทูธ"</string> <string name="enable_terminal_title" msgid="95572094356054120">"เทอร์มินัลในตัวเครื่อง"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - เหลืออีก <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> จนกว่าจะชาร์จเต็ม"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"ไม่ทราบ"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"กำลังชาร์จ"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"กำลังชาร์จ"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"ไม่ได้ชาร์จ"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"เสียบอยู่ ไม่สามารถชาร์จได้ในขณะนี้"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"เต็ม"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"ผู้ดูแลระบบเป็นผู้ควบคุม"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"เปิดใช้โดยผู้ดูแลระบบ"</string> diff --git a/packages/SettingsLib/res/values-tl/arrays.xml b/packages/SettingsLib/res/values-tl/arrays.xml index 2a82ab6647c3..f913bc4d9494 100644 --- a/packages/SettingsLib/res/values-tl/arrays.xml +++ b/packages/SettingsLib/res/values-tl/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Gamitin ang Pagpili ng System (Default)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"I-enable ang Mga Opsyonal na Codec"</item> - <item msgid="3304843301758635896">"I-disable ang Mga Opsyonal na Codec"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Gamitin ang Pagpili ng System (Default)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"I-enable ang Mga Opsyonal na Codec"</item> - <item msgid="741805482892725657">"I-disable ang Mga Opsyonal na Codec"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Gamitin ang Pagpili ng System (Default)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml index 51630dac9f9f..c054248a6fe5 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Palaging payagan ang Mga Pag-scan sa Roaming ng Wi‑Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Palaging aktibo ang mobile data"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardware acceleration para sa pag-tether"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"I-disable ang absolute volume"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"I-enable ang pag-ring na nasa band"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bersyon ng AVRCP ng Bluetooth"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Nilalayon ang mga setting na ito para sa paggamit sa pag-develop lamang. Maaaring magsanhi ang mga ito ng pagkasira o hindi paggana nang maayos ng iyong device at mga application na nandito."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"I-verify ang mga app sa USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Tingnan kung may nakakahamak na pagkilos sa apps na na-install sa pamamagitan ng ADB/ADT."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Dini-disable ang absolute volume feature ng Bluetooth kung may mga isyu sa volume ang mga malayong device gaya ng hindi katanggap-tanggap na malakas na volume o kawalan ng kontrol."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Payagan ang pag-play ng mga ringtone sa telepono sa mga headset na gumagamit ng Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Lokal na terminal"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> pa"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> hanggang sa makumpleto ang charge"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Hindi Kilala"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Nagcha-charge"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"nagcha-charge"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Hindi nagcha-charge"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Nakasaksak, hindi makapag-charge sa ngayon"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Puno"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Pinapamahalaan ng admin"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Na-enable ng admin"</string> @@ -365,7 +367,7 @@ <string name="disabled" msgid="9206776641295849915">"Naka-disable"</string> <string name="external_source_trusted" msgid="2707996266575928037">"Pinapayagan"</string> <string name="external_source_untrusted" msgid="2677442511837596726">"Hindi pinapayagan"</string> - <string name="install_other_apps" msgid="6986686991775883017">"Mag-install ng mga hindi alam na app"</string> + <string name="install_other_apps" msgid="6986686991775883017">"Mag-install ng di-kilalang app"</string> <string name="home" msgid="3256884684164448244">"Home ng Mga Setting"</string> <string-array name="battery_labels"> <item msgid="8494684293649631252">"0%"</item> diff --git a/packages/SettingsLib/res/values-tr/arrays.xml b/packages/SettingsLib/res/values-tr/arrays.xml index bb43ec7537d8..30c44ca9faf6 100644 --- a/packages/SettingsLib/res/values-tr/arrays.xml +++ b/packages/SettingsLib/res/values-tr/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Sistem Seçimini Kullan (Varsayılan)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"İsteğe Bağlı Codec\'leri Etkinleştir"</item> - <item msgid="3304843301758635896">"İsteğe Bağlı Codec\'leri Devre Dışı Bırak"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Sistem Seçimini Kullan (Varsayılan)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"İsteğe Bağlı Codec\'leri Etkinleştir"</item> - <item msgid="741805482892725657">"İsteğe Bağlı Codec\'leri Devre Dışı Bırak"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Sistem Seçimini Kullan (Varsayılan)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml index f2f94a22b02c..69dd6be97523 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Kablosuz Dolaşım Taramalarına daima izin ver"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobil veri her zaman etkin"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering donanım hızlandırıcısı"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Mutlak sesi iptal et"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Bant içi zil çaldırmayı etkinleştir"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP Sürümü"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Bu ayarlar yalnızca geliştirme amaçlıdır. Cihazınızın veya cihazdaki uygulamaların bozulmasına veya hatalı çalışmasına neden olabilir."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB\'den yüklenen uygulamaları doğrula"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT üzerinden yüklenen uygulamaları zararlı davranışlara karşı denetle."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Uzak cihazda sesin aşırı yüksek olması veya kontrol edilememesi gibi ses sorunları olması ihtimaline karşı Bluetooh mutlak ses özelliğini iptal eder."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Telefondaki zil seslerinin Bluetooth kulaklıklarda çalınmasına olanak tanır"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Yerel terminal"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> kaldı"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - Tam şarj olmasına <xliff:g id="TIME">^2</xliff:g> kaldı"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Bilinmiyor"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Şarj oluyor"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"şarj oluyor"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Şarj olmuyor"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Prize takıldı, şu anda şarj olamıyor"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Dolu"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Yönetici tarafından denetleniyor"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Yönetici tarafından etkinleştirildi"</string> diff --git a/packages/SettingsLib/res/values-uk/arrays.xml b/packages/SettingsLib/res/values-uk/arrays.xml index a8705e729356..76b1b16ef14e 100644 --- a/packages/SettingsLib/res/values-uk/arrays.xml +++ b/packages/SettingsLib/res/values-uk/arrays.xml @@ -72,8 +72,8 @@ <item msgid="7065842274271279580">"Використовувати вибір системи (за умовчанням)"</item> <item msgid="7539690996561263909">"SBC"</item> <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> + <item msgid="5254942598247222737">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="2091430979086738145">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="6751080638867012696">"LDAC"</item> <item msgid="723675059572222462">"Увімкнути додаткові кодеки"</item> <item msgid="3304843301758635896">"Вимкнути додаткові кодеки"</item> @@ -82,8 +82,8 @@ <item msgid="5062108632402595000">"Використовувати вибір системи (за умовчанням)"</item> <item msgid="6898329690939802290">"SBC"</item> <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> + <item msgid="7848030269621918608">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item> + <item msgid="298198075927343893">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item> <item msgid="7950781694447359344">"LDAC"</item> <item msgid="2209680154067241740">"Увімкнути додаткові кодеки"</item> <item msgid="741805482892725657">"Вимкнути додаткові кодеки"</item> diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index 7f329ce2ab0d..6b6e245366b4 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Завжди шукати мережі Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Не вимикати мобільне передавання даних"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Апаратне прискорення під час використання телефона в режимі модема"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Вимкнути абсолютну гучність"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Увімкнути внутрішньосмугові сигнали"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Версія Bluetooth AVRCP"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Ці налаштування застосовуються лише з метою розробки. Вони можуть спричиняти вихід з ладу або неправильне функціонування вашого пристрою чи програм у ньому."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Встановлення через USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Перевіряти безпеку додатків, установлених через ADB/ADT."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Функція абсолютної гучності Bluetooth вимикається, якщо на віддалених пристроях виникають проблеми, як-от надто висока гучність або втрата контролю."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Дозволити відтворювати сигнали дзвінка на телефоні через гарнітуру Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Локальний термінал"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – залишилося <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> до повного заряду"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Невідомо"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Заряджається"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"заряджається"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Не заряджається"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Підключено. Не вдається зарядити"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Акумулятор заряджено"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Керується адміністратором"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Увімкнено адміністратором"</string> diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml index 6da98dcf67d5..d922361b8fac 100644 --- a/packages/SettingsLib/res/values-ur/arrays.xml +++ b/packages/SettingsLib/res/values-ur/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"اختیاری کوڈیکز کو فعال کریں"</item> - <item msgid="3304843301758635896">"اختیاری کوڈیکز کو غیر فعال کریں"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"اختیاری کوڈیکز کو فعال کریں"</item> - <item msgid="741805482892725657">"اختیاری کوڈیکز کو غیر فعال کریں"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml index 9d37602c99fa..09e83188ec99 100644 --- a/packages/SettingsLib/res/values-ur/strings.xml +++ b/packages/SettingsLib/res/values-ur/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ہمیشہ Wi‑Fi روم اسکینز کی اجازت دیں"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"موبائل ڈیٹا ہمیشہ فعال رکھیں"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"ہارڈویئر کی سرعت کاری میں ربط بنایا جا رہا ہے"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"مطلق والیوم کو غیر فعال کریں"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"ان بینڈ رنگنگ فعال کریں"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"بلوٹوتھ AVRCP ورژن"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"یہ ترتیبات صرف ڈویلپمنٹ استعمال کے ارادے سے ہیں۔ ان سے آپ کا آلہ اور اس پر موجود ایپلیکیشنز بریک ہو سکتی یا غلط برتاؤ کر سکتی ہیں۔"</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB پر ایپس کی توثیق کریں"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"نقصان دہ رویے کے مدنظر ADB/ADT کی معرفت انسٹال شدہ ایپس کی جانچ کریں۔"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ریموٹ آلات کے ساتھ والیوم کے مسائل مثلاً نا قابل قبول حد تک بلند والیوم یا کنٹرول نہ ہونے کی صورت میں بلو ٹوتھ مطلق والیوم والی خصوصیت کو غیر فعال کریں۔"</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"فون پر موجود رنگ ٹونز کو بلوٹوتھ ہیڈ سیٹز پر چلنے دیں"</string> <string name="enable_terminal_title" msgid="95572094356054120">"مقامی ٹرمینل"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> باقی ہے"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> پوری طرح چارج ہونے تک"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"نامعلوم"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"چارج ہو رہا ہے"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"چارج ہو رہا ہے"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"چارج نہیں ہو رہا ہے"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"پلگ ان ہے، ابھی چارج نہیں کر سکتے"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"مکمل"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"کنٹرول کردہ بذریعہ منتظم"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"منتظم کی طرف سے فعال کردہ"</string> diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml index 1d4e1e986954..9d75b5184e3c 100644 --- a/packages/SettingsLib/res/values-uz/arrays.xml +++ b/packages/SettingsLib/res/values-uz/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Tizim tanlovi (birlamchi)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Boshqa kodeklarni yoqish"</item> - <item msgid="3304843301758635896">"Boshqa kodeklarni o‘chirib qo‘yish"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Tizim tanlovi (birlamchi)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Boshqa kodeklarni yoqish"</item> - <item msgid="741805482892725657">"Boshqa kodeklarni o‘chirib qo‘yish"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Tizim tanlovi (birlamchi)"</item> <item msgid="8895532488906185219">"44.1 kGs"</item> diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml index 872d1215348a..981b67e4cfb3 100644 --- a/packages/SettingsLib/res/values-uz/strings.xml +++ b/packages/SettingsLib/res/values-uz/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi tarmoqlarini qidirishga doim ruxsat"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobil internet doim yoniq tursin"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Modem rejimida apparatli tezlashtirish"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Ovoz balangligining mutlaq darajasini o‘chirib qo‘yish"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Bitta liniyada jiringlashni yoqish"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP versiyasi"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Bu sozlamalar faqat dasturlash maqsadlariga mo‘ljallangan. Shuning uchun, ular qurilmangizga va undagi ilovalariga shikast yetkazib, noto‘g‘ri ishlashiga sabab bo‘lishi mumkin."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB orqali o‘rnatish"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT orqali o‘rnatilgan ilovalar xavfsizligini tekshiring"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Masofadan ulanadigan qurilmalar bilan muammolar yuz berganda, jumladan, juda baland ovoz yoki sozlamalarni boshqarib bo‘lmaydigan holatlarda Bluetooth ovozi balandligining mutlaq darajasini o‘chirib qo‘yadi."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Bluetooth quloqliklarda ijro etish uchun telefonda ringtonlarga ruxsat bering"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Mahalliy terminal"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> qoldi"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g> ichida to‘ladi"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> – <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Noma’lum"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Quvvat olmoqda"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"quvvat olmoqda"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Quvvat olmayapti"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Ulangan, lekin quvvat olmayapti"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"To‘la"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Administrator tomonidan boshqariladi"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Administrator tomonidan yoqilgan"</string> diff --git a/packages/SettingsLib/res/values-vi/arrays.xml b/packages/SettingsLib/res/values-vi/arrays.xml index 134dc8be7a79..b87bd62ad64c 100644 --- a/packages/SettingsLib/res/values-vi/arrays.xml +++ b/packages/SettingsLib/res/values-vi/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Sử dụng lựa chọn hệ thống (Mặc định)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"Bật codec tùy chọn"</item> - <item msgid="3304843301758635896">"Tắt codec tùy chọn"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Sử dụng lựa chọn hệ thống (Mặc định)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"Bật codec tùy chọn"</item> - <item msgid="741805482892725657">"Tắt codec tùy chọn"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Sử dụng lựa chọn hệ thống (Mặc định)"</item> <item msgid="8895532488906185219">"44,1 kHz"</item> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index 1c9f917ed17f..d5ee2161c215 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Luôn cho phép quét chuyển vùng Wi‑Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Dữ liệu di động luôn hiện hoạt"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"Tăng tốc phần cứng cho chia sẻ kết nối"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Vô hiệu hóa âm lượng tuyệt đối"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Bật đổ chuông trong dải"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth phiên bản AVRCP"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Những cài đặt này chỉ dành cho mục đích phát triển. Chúng có thể làm cho thiết bị và ứng dụng trên thiết bị của bạn bị lỗi và hoạt động sai."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Xác minh ứng dụng qua USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kiểm tra các ứng dụng được cài đặt qua ADB/ADT để xem có hoạt động gây hại hay không."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Vô hiệu hóa tính năng âm lượng tuyệt đối qua Bluetooth trong trường hợp xảy ra sự cố về âm lượng với các thiết bị từ xa, chẳng hạn như âm lượng lớn không thể chấp nhận được hoặc thiếu kiểm soát."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Cho phép nhạc chuông trên điện thoại được phát trên tai nghe Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Dòng lệnh cục bộ"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - còn lại <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> cho tới khi được sạc đầy"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Không xác định"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Đang sạc"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"đang sạc"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Hiện không sạc"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Đã cắm nhưng không thể sạc ngay"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Đầy"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Do quản trị viên kiểm soát"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Kích hoạt bởi quản trị viên"</string> diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml index fadc7a9a76b6..ec5915812632 100644 --- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml +++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"使用系统选择(默认)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"启用可选编解码器"</item> - <item msgid="3304843301758635896">"停用可选编解码器"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"使用系统选择(默认)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"启用可选编解码器"</item> - <item msgid="741805482892725657">"停用可选编解码器"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"使用系统选择(默认)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index c1643474d59a..c6f9061dce43 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"一律允许WLAN漫游扫描"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"始终开启移动数据网络"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"网络共享硬件加速"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"停用绝对音量功能"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"启用手机默认铃声"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"蓝牙 AVRCP 版本"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"这些设置仅适用于开发工作。一旦启用,会导致您的设备以及设备上的应用崩溃或出现异常。"</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"通过USB验证应用"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"通过 ADB/ADT 检查安装的应用是否存在有害行为。"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"停用蓝牙绝对音量功能,即可避免在连接到远程设备时出现音量问题(例如音量高得让人无法接受或无法控制音量等)。"</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"允许手机铃声通过蓝牙耳机播放"</string> <string name="enable_terminal_title" msgid="95572094356054120">"本地终端"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - 还可用 <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - 还需 <xliff:g id="TIME">^2</xliff:g>充满"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"未知"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"正在充电"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"正在充电"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"未在充电"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"已插入电源,但是现在无法充电"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"电量充足"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"由管理员控制"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"已被管理员启用"</string> diff --git a/packages/SettingsLib/res/values-zh-rHK/arrays.xml b/packages/SettingsLib/res/values-zh-rHK/arrays.xml index 7f4c427edc1e..60d2a95af9aa 100644 --- a/packages/SettingsLib/res/values-zh-rHK/arrays.xml +++ b/packages/SettingsLib/res/values-zh-rHK/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"使用系統選擇 (預設)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"啟用選用的編解碼器"</item> - <item msgid="3304843301758635896">"停用選用的編解碼器"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"使用系統選擇 (預設)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"啟用選用的編解碼器"</item> - <item msgid="741805482892725657">"停用選用的編解碼器"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"使用系統選擇 (預設)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index 4fadad1693ae..af9ba2405125 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"永遠允許 Wi-Fi 漫遊掃瞄"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"一律保持啟用流動數據"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"網絡共享硬件加速"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"停用絕對音量功能"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"啟用頻內鈴聲"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"藍牙 AVRCP 版本"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"這些設定僅供開發用途,可能會導致您的裝置及應用程式損毀或運作不正常。"</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"透過 USB 驗證應用程式"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"透過 ADB/ADT 檢查安裝的應用程式有否有害的行為。"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"連線至遠端裝置時,如發生音量過大或無法控制音量等問題,請停用藍牙絕對音量功能。"</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"允許藍牙耳機播放手機鈴聲"</string> <string name="enable_terminal_title" msgid="95572094356054120">"本機終端機"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - 尚餘 <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - 還需 <xliff:g id="TIME">^2</xliff:g>才能充滿電"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"未知"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"正在充電"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"非充電中"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"已插入電源插座,但目前無法充電"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"電量已滿"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"已由管理員停用"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"已由管理員啟用"</string> diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml index 0f3bf239117a..482b871b04d9 100644 --- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml +++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"avrcp15"</item> <item msgid="7142710449249088270">"avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"使用系統選擇 (預設)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"LDAC"</item> - <item msgid="723675059572222462">"啟用選用的轉碼器"</item> - <item msgid="3304843301758635896">"停用選用的轉碼器"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"使用系統選擇 (預設)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"LDAC"</item> - <item msgid="2209680154067241740">"啟用選用的轉碼器"</item> - <item msgid="741805482892725657">"停用選用的轉碼器"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"使用系統選擇 (預設)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index ed21c9a2a99a..9e8d1ca76a54 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"一律允許 Wi-Fi 漫遊掃描"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"行動數據連線一律保持啟用狀態"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"數據連線硬體加速"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"停用絕對音量功能"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"啟用藍牙同步鈴聲功能"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"藍牙 AVRCP 版本"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"這些設定僅供開發之用,可能導致你的裝置及裝置中的應用程式毀損或運作異常。"</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"透過 USB 驗證應用程式"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"檢查透過 ADB/ADT 安裝的應用程式是否具有有害行為。"</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"只要停用藍牙絕對音量功能,即可避免在連線到遠端裝置時,發生音量過大或無法控制音量等問題。"</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"允許手機鈴聲透過藍牙耳機播放"</string> <string name="enable_terminal_title" msgid="95572094356054120">"本機終端機"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - 還剩 <xliff:g id="TIME">^2</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>後充飽"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"不明"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"充電中"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"非充電中"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"已接上電源,但現在無法充電"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"電力充足"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"已由管理員停用"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"已由管理員啟用"</string> diff --git a/packages/SettingsLib/res/values-zu/arrays.xml b/packages/SettingsLib/res/values-zu/arrays.xml index d7449f1de0e7..6ad5a45e0ff7 100644 --- a/packages/SettingsLib/res/values-zu/arrays.xml +++ b/packages/SettingsLib/res/values-zu/arrays.xml @@ -68,26 +68,10 @@ <item msgid="1913619118958233129">"I-avrcp15"</item> <item msgid="7142710449249088270">"I-avrcp16"</item> </string-array> - <string-array name="bluetooth_a2dp_codec_titles"> - <item msgid="7065842274271279580">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item> - <item msgid="7539690996561263909">"SBC"</item> - <item msgid="686685526567131661">"I-AAC"</item> - <item msgid="8910200421843557332">"aptX"</item> - <item msgid="8434403964359457768">"aptX HD"</item> - <item msgid="6751080638867012696">"I-LDAC"</item> - <item msgid="723675059572222462">"Nika amandla amakhodekhi akhethekayo"</item> - <item msgid="3304843301758635896">"Khubaza amakhodekhi akhethekayo"</item> - </string-array> - <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="5062108632402595000">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item> - <item msgid="6898329690939802290">"SBC"</item> - <item msgid="6839647709301342559">"I-AAC"</item> - <item msgid="2279916056363477395">"aptX"</item> - <item msgid="6641171061200063516">"aptX HD"</item> - <item msgid="7950781694447359344">"I-LDAC"</item> - <item msgid="2209680154067241740">"Nika amandla amakhodekhi akhethekayo"</item> - <item msgid="741805482892725657">"Khubaza amakhodekhi akhethekayo"</item> - </string-array> + <!-- no translation found for bluetooth_a2dp_codec_titles:3 (5254942598247222737) --> + <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2091430979086738145) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (7848030269621918608) --> + <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (298198075927343893) --> <string-array name="bluetooth_a2dp_codec_sample_rate_titles"> <item msgid="3093023430402746802">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item> <item msgid="8895532488906185219">"44.1 kHz"</item> diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index b5982978be04..5be0b8ecec61 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -193,6 +193,8 @@ <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vumela njalo ukuskena kokuzula kwe-Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8774857027458200434">"Idatha yeselula ihlala isebenza"</string> <string name="tethering_hardware_offload" msgid="7470077827090325814">"I-Tethering hardware acceleration"</string> + <!-- no translation found for bluetooth_show_devices_without_names (4708446092962060176) --> + <skip /> <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Khubaza ivolumu ngokuphelele"</string> <string name="bluetooth_enable_inband_ringing" msgid="3291686366721786740">"Nika amandla ukukhala okuphakathi nomkhiqizo"</string> <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Inguqulo ye-Bluetooth ye-AVRCP"</string> @@ -232,6 +234,8 @@ <string name="dev_settings_warning_message" msgid="2298337781139097964">"Lezi zilungiselelo zenzelwe ukusetshenziswa ukuthuthukisa kuphela. Zingadala ukuthi idivayisi yakho kanye nensiza ekuyona ukuthi iphuke noma iziphathe kabi."</string> <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Qiniseka izinhlelo zokusebenza nge-USB"</string> <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Hlola izinhlelo zokusebenza ezifakiwe nge-ADB/ADT ngokuziphatha okuyingozi."</string> + <!-- no translation found for bluetooth_show_devices_without_names_summary (2351196058115755520) --> + <skip /> <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Ikhubaza isici esiphelele sevolumu ye-Bluetooth uma kuba nezinkinga zevolumu ngamadivayisi esilawuli kude ezifana nevolumu ephezulu noma eshoda ngokulawuleka."</string> <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Vumela amathoni okukhala efonini ukuthi adlalwe kuma-earphone e-Bluetooth"</string> <string name="enable_terminal_title" msgid="95572094356054120">"Itheminali yasendaweni"</string> @@ -351,13 +355,11 @@ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> okusele"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g> kuze ligcwale ngokuphelele"</string> - <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">^1</xliff:g> - <xliff:g id="TIME">^2</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Akwaziwa"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Iyashaja"</string> <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"iyashaja"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Ayishaji"</string> - <!-- no translation found for battery_info_status_not_charging (8523453668342598579) --> - <skip /> + <string name="battery_info_status_not_charging" msgid="8523453668342598579">"Kuxhunyiwe, ayikwazi ukushaja khona manje"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Kugcwele"</string> <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kulawulwa umqondisi"</string> <string name="enabled_by_admin" msgid="5302986023578399263">"Kunikwe amandla umlawuli"</string> diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml index db3274ab478c..0bf2eda8cc1f 100644 --- a/packages/SettingsLib/res/values/arrays.xml +++ b/packages/SettingsLib/res/values/arrays.xml @@ -121,8 +121,8 @@ <item>Use System Selection (Default)</item> <item>SBC</item> <item>AAC</item> - <item>aptX</item> - <item>aptX HD</item> + <item><xliff:g id="qualcomm">Qualcomm®</xliff:g> <xliff:g id="aptx">aptX™</xliff:g> audio</item> + <item><xliff:g id="qualcomm">Qualcomm®</xliff:g> <xliff:g id="aptx_hd">aptX™ HD</xliff:g> audio</item> <item>LDAC</item> <item>Enable Optional Codecs</item> <item>Disable Optional Codecs</item> @@ -145,8 +145,8 @@ <item>Use System Selection (Default)</item> <item>SBC</item> <item>AAC</item> - <item>aptX</item> - <item>aptX HD</item> + <item><xliff:g id="qualcomm">Qualcomm®</xliff:g> <xliff:g id="aptx">aptX™</xliff:g> audio</item> + <item><xliff:g id="qualcomm">Qualcomm®</xliff:g> <xliff:g id="aptx_hd">aptX™ HD</xliff:g> audio</item> <item>LDAC</item> <item>Enable Optional Codecs</item> <item>Disable Optional Codecs</item> diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml index 3322839ee213..1e35cbc78343 100644 --- a/packages/SettingsLib/res/values/dimens.xml +++ b/packages/SettingsLib/res/values/dimens.xml @@ -55,9 +55,17 @@ <dimen name="battery_height">14.5dp</dimen> <dimen name="battery_width">9.5dp</dimen> + <dimen name="bt_battery_padding">2dp</dimen> + <!-- Margin on the right side of the system icon group on Keyguard. --> <fraction name="battery_button_height_fraction">10.5%</fraction> + <!-- Ratio between height of button part and height of total --> + <fraction name="bt_battery_button_height_fraction">7.5%</fraction> + + <!-- Ratio between width and height --> + <fraction name="bt_battery_ratio_fraction">45%</fraction> + <!-- Fraction value to smooth the edges of the battery icon. The path will be inset by this fraction of a pixel.--> <fraction name="battery_subpixel_smoothing_left">0%</fraction> diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index fd5b70e3142f..bd884a3c9729 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -484,6 +484,8 @@ <string name="mobile_data_always_on">Mobile data always active</string> <!-- Setting Checkbox title whether to enable hardware acceleration for tethering. [CHAR LIMIT=80] --> <string name="tethering_hardware_offload">Tethering hardware acceleration</string> + <!-- Setting Checkbox title for showing Bluetooth devices without names --> + <string name="bluetooth_show_devices_without_names">Show Bluetooth devices without names</string> <!-- Setting Checkbox title for disabling Bluetooth absolute volume --> <string name="bluetooth_disable_absolute_volume">Disable absolute volume</string> <!-- Setting Checkbox title for enabling Bluetooth inband ringing --> @@ -568,12 +570,13 @@ <string name="verify_apps_over_usb_title">Verify apps over USB</string> <!-- Summary of checkbox setting to perform package verification on apps installed over USB/ADT/ADB [CHAR LIMIT=NONE] --> <string name="verify_apps_over_usb_summary">Check apps installed via ADB/ADT for harmful behavior.</string> + <!-- Summary of checkbox for showing Bluetooth devices without names --> + <string name="bluetooth_show_devices_without_names_summary">Bluetooth devices without names (MAC addresses only) will be displayed</string> <!-- Summary of checkbox for disabling Bluetooth absolute volume --> <string name="bluetooth_disable_absolute_volume_summary">Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control.</string> <!-- Summary of checkbox for enabling Bluetooth inband ringing --> <string name="bluetooth_enable_inband_ringing_summary">Allow ringtones on the phone to be played on Bluetooth headsets</string> - <!-- Title of checkbox setting that enables the terminal app. [CHAR LIMIT=32] --> <string name="enable_terminal_title">Local terminal</string> <!-- Summary of checkbox setting that enables the terminal app. [CHAR LIMIT=64] --> @@ -867,8 +870,6 @@ <string name="power_charging"><xliff:g id="level">%1$s</xliff:g> - <xliff:g id="state">%2$s</xliff:g></string> <!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration --> <string name="power_charging_duration"><xliff:g id="level">^1</xliff:g> - <xliff:g id="time">^2</xliff:g> until fully charged</string> - <!-- [CHAR_LIMIT=40] Short label for battery level chart when charging with duration --> - <string name="power_charging_duration_short"><xliff:g id="level">^1</xliff:g> - <xliff:g id="time">^2</xliff:g></string> <!-- Battery Info screen. Value for a status item. Used for diagnostic info screens, precise translation isn't needed --> <string name="battery_info_status_unknown">Unknown</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java b/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java index ebb5d19eb6bb..78a9064f1400 100644 --- a/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java @@ -76,16 +76,17 @@ public class DeviceInfoUtils { public static String formatKernelVersion(String rawKernelVersion) { // Example (see tests for more): - // Linux version 3.0.31-g6fb96c9 (android-build@xxx.xxx.xxx.xxx.com) \ - // (gcc version 4.6.x-xxx 20120106 (prerelease) (GCC) ) #1 SMP PREEMPT \ - // Thu Jun 28 11:02:39 PDT 2012 - + // Linux version 4.9.29-g958411d (android-build@xyz) (Android clang version 3.8.256229 \ + // (based on LLVM 3.8.256229)) #1 SMP PREEMPT Wed Jun 7 00:06:03 CST 2017 + // Linux version 4.9.29-geb63318482a7 (android-build@xyz) (gcc version 4.9.x 20150123 \ + // (prerelease) (GCC) ) #1 SMP PREEMPT Thu Jun 1 03:41:57 UTC 2017 final String PROC_VERSION_REGEX = "Linux version (\\S+) " + /* group 1: "3.0.31-g6fb96c9" */ - "\\((\\S+)\\)" + /* group 2: "x@y.com" (kernel builder) */ - ".*(#\\d+)" + /* group 3: "#1" */ - /* group 4: "Thu Jun 28 11:02:39 PDT 2012" */ - ".*((?:Sun|Mon|Tue|Wed|Thu|Fri|Sat).+)"; + "\\((\\S+?)\\) " + /* group 2: "(x@y.com) " */ + "\\((.+?)\\) " + /* group 3: kernel toolchain version information */ + "(#\\d+) " + /* group 4: "#1" */ + "(?:.*?)?" + /* ignore: optional SMP, PREEMPT, and any CONFIG_FLAGS */ + "((Sun|Mon|Tue|Wed|Thu|Fri|Sat).+)"; /* group 5: "Thu Jun 28 11:02:39 PDT 2012" */ Matcher m = Pattern.compile(PROC_VERSION_REGEX).matcher(rawKernelVersion); if (!m.matches()) { @@ -96,9 +97,9 @@ public class DeviceInfoUtils { + " groups"); return "Unavailable"; } - return m.group(1) + "\n" + // 3.0.31-g6fb96c9 - m.group(2) + " " + m.group(3) + "\n" + // x@y.com #1 - m.group(4); // Thu Jun 28 11:02:39 PDT 2012 + return m.group(1) + " ("+ m.group(3) + ")\n" + // 3.0.31-g6fb96c9 (toolchain version) + m.group(2) + " " + m.group(4) + "\n" + // x@y.com #1 + m.group(5); // Thu Jun 28 11:02:39 PDT 2012 } /** diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java index dee5a93d8eea..8def03648558 100644 --- a/packages/SettingsLib/src/com/android/settingslib/Utils.java +++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java @@ -14,15 +14,13 @@ import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; +import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; -import android.graphics.drawable.LayerDrawable; import android.net.ConnectivityManager; -import android.net.NetworkBadging; import android.os.BatteryManager; import android.os.UserManager; import android.print.PrintManager; import android.provider.Settings; -import android.view.View; import com.android.internal.util.UserIcons; import com.android.settingslib.drawable.UserIconDrawable; @@ -35,12 +33,12 @@ public class Utils { private static String sServicesSystemSharedLibPackageName; private static String sSharedSystemSharedLibPackageName; - static final int[] WIFI_PIE_FOR_BADGING = { - com.android.internal.R.drawable.ic_signal_wifi_badged_0_bars, - com.android.internal.R.drawable.ic_signal_wifi_badged_1_bar, - com.android.internal.R.drawable.ic_signal_wifi_badged_2_bars, - com.android.internal.R.drawable.ic_signal_wifi_badged_3_bars, - com.android.internal.R.drawable.ic_signal_wifi_badged_4_bars + static final int[] WIFI_PIE = { + com.android.internal.R.drawable.ic_wifi_signal_0, + com.android.internal.R.drawable.ic_wifi_signal_1, + com.android.internal.R.drawable.ic_wifi_signal_2, + com.android.internal.R.drawable.ic_wifi_signal_3, + com.android.internal.R.drawable.ic_wifi_signal_4 }; /** @@ -95,13 +93,12 @@ public class Utils { /** * Returns a circular icon for a user. */ - public static UserIconDrawable getUserIcon(Context context, UserManager um, UserInfo user) { + public static Drawable getUserIcon(Context context, UserManager um, UserInfo user) { final int iconSize = UserIconDrawable.getSizeForList(context); if (user.isManagedProfile()) { - // We use predefined values for managed profiles - Bitmap b = BitmapFactory.decodeResource(context.getResources(), - com.android.internal.R.drawable.ic_corp_icon); - return new UserIconDrawable(iconSize).setIcon(b).bake(); + Drawable drawable = context.getDrawable(com.android.internal.R.drawable.ic_corp_icon); + drawable.setBounds(0, 0, iconSize, iconSize); + return drawable; } if (user.iconPath != null) { Bitmap icon = um.getUserIcon(user.id); @@ -272,42 +269,17 @@ public class Utils { } /** - * Returns a badged Wifi icon drawable. - * - * <p>The first layer contains the Wifi pie and the second layer contains the badge. Callers - * should set the drawable to the appropriate size and tint color. + * Returns the Wifi icon resource for a given RSSI level. * - * @param context The caller's context (must have access to internal resources) * @param level The number of bars to show (0-4) - * @param badge The badge enum {@see android.net.ScoredNetwork} - * - * @throws IllegalArgumentException if an invalid badge enum is given * - * @deprecated TODO(sghuman): Finalize the form of this method and then move it to a new - * location. + * @throws IllegalArgumentException if an invalid RSSI level is given. */ - public static LayerDrawable getBadgedWifiIcon(Context context, int level, int badge) { - return new LayerDrawable( - new Drawable[] { - context.getDrawable(WIFI_PIE_FOR_BADGING[level]), - context.getDrawable(getWifiBadgeResource(badge)) - }); - } - - private static int getWifiBadgeResource(int badge) { - switch (badge) { - case NetworkBadging.BADGING_NONE: - return View.NO_ID; - case NetworkBadging.BADGING_SD: - return com.android.internal.R.drawable.ic_signal_wifi_badged_sd; - case NetworkBadging.BADGING_HD: - return com.android.internal.R.drawable.ic_signal_wifi_badged_hd; - case NetworkBadging.BADGING_4K: - return com.android.internal.R.drawable.ic_signal_wifi_badged_4k; - default: - throw new IllegalArgumentException( - "No badge resource found for badge value: " + badge); + public static int getWifiIconResource(int level) { + if (level < 0 || level >= WIFI_PIE.length) { + throw new IllegalArgumentException("No Wifi icon found for level: " + level); } + return WIFI_PIE[level]; } public static int getDefaultStorageManagerDaysToRetain(Resources resources) { diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java index 443f1ee1d827..87bf0de2b2c8 100644 --- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java +++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java @@ -1638,6 +1638,21 @@ public class ApplicationsState { } }; + public static final AppFilter FILTER_PHOTOS = + new AppFilter() { + @Override + public void init() {} + + @Override + public boolean filterApp(AppEntry entry) { + boolean isPhotosApp; + synchronized (entry) { + isPhotosApp = entry.info.category == ApplicationInfo.CATEGORY_IMAGE; + } + return isPhotosApp; + } + }; + public static final AppFilter FILTER_OTHER_APPS = new AppFilter() { @Override diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java index 7268d00bade1..0946181ab710 100755 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java @@ -233,8 +233,8 @@ public class A2dpProfile implements LocalBluetoothProfile { public String getHighQualityAudioOptionLabel(BluetoothDevice device) { int unknownCodecId = R.string.bluetooth_profile_a2dp_high_quality_unknown_codec; - if (!supportsHighQualityAudio(device) || - getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED) { + if (!supportsHighQualityAudio(device) + || getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED) { return mContext.getString(unknownCodecId); } // We want to get the highest priority codec, since that's the one that will be used with @@ -248,11 +248,36 @@ public class A2dpProfile implements LocalBluetoothProfile { return b.getCodecPriority() - a.getCodecPriority(); }); } - if (selectable == null || selectable.length < 1 || selectable[0].isMandatoryCodec()) { + + final BluetoothCodecConfig codecConfig = (selectable == null || selectable.length < 1) + ? null : selectable[0]; + final int codecType = (codecConfig == null || codecConfig.isMandatoryCodec()) + ? BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID : codecConfig.getCodecType(); + + int index = -1; + switch (codecType) { + case BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC: + index = 1; + break; + case BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC: + index = 2; + break; + case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX: + index = 3; + break; + case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD: + index = 4; + break; + case BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC: + index = 5; + break; + } + + if (index < 0) { return mContext.getString(unknownCodecId); } return mContext.getString(R.string.bluetooth_profile_a2dp_high_quality, - selectable[0].getCodecName()); + mContext.getResources().getStringArray(R.array.bluetooth_a2dp_codec_titles)[index]); } public String toString() { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java index 7d4bc83e3385..28105e2630a4 100755 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java @@ -200,7 +200,7 @@ public class BluetoothEventManager { cachedDevice.setRssi(rssi); cachedDevice.setBtClass(btClass); cachedDevice.setNewName(name); - cachedDevice.setVisible(true); + cachedDevice.setJustDiscovered(true); } } @@ -352,7 +352,7 @@ public class BluetoothEventManager { if (device != null && device.getBondState() == BluetoothDevice.BOND_NONE) { CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); if (cachedDevice != null) { - cachedDevice.setVisible(false); + cachedDevice.setJustDiscovered(false); } } } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index 4bb4b402b990..109446d8ed4a 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -50,8 +50,11 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> private final LocalBluetoothAdapter mLocalAdapter; private final LocalBluetoothProfileManager mProfileManager; private final BluetoothDevice mDevice; + //TODO: consider remove, BluetoothDevice.getName() is already cached private String mName; + // Need this since there is no method for getting RSSI private short mRssi; + //TODO: consider remove, BluetoothDevice.getBluetoothClass() is already cached private BluetoothClass mBtClass; private HashMap<LocalBluetoothProfile, Integer> mProfileConnectionState; @@ -65,7 +68,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> // Device supports PANU but not NAP: remove PanProfile after device disconnects from NAP private boolean mLocalNapRoleConnected; - private boolean mVisible; + private boolean mJustDiscovered; private int mMessageRejectionCount; @@ -360,7 +363,6 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> migrateMessagePermissionChoice(); fetchMessageRejectionCount(); - mVisible = false; dispatchAttributesChanged(); } @@ -395,10 +397,12 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> } /** - * user changes the device name + * User changes the device name + * @param name new alias name to be set, should never be null */ public void setName(String name) { - if (!mName.equals(name)) { + // Prevent mName to be set to null if setName(null) is called + if (name != null && !TextUtils.equals(name, mName)) { mName = name; mDevice.setAlias(name); dispatchAttributesChanged(); @@ -420,6 +424,14 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> } /** + * Checks if device has a human readable name besides MAC address + * @return true if device's alias name is not null nor empty, false otherwise + */ + public boolean hasHumanReadableName() { + return !TextUtils.isEmpty(mDevice.getAliasName()); + } + + /** * Get battery level from remote device * @return battery level in percentage [0-100], or {@link BluetoothDevice#BATTERY_LEVEL_UNKNOWN} */ @@ -431,13 +443,9 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> dispatchAttributesChanged(); } - public boolean isVisible() { - return mVisible; - } - - public void setVisible(boolean visible) { - if (mVisible != visible) { - mVisible = visible; + public void setJustDiscovered(boolean justDiscovered) { + if (mJustDiscovered != justDiscovered) { + mJustDiscovered = justDiscovered; dispatchAttributesChanged(); } } @@ -500,7 +508,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> ParcelUuid[] localUuids = mLocalAdapter.getUuids(); if (localUuids == null) return false; - /** + /* * Now we know if the device supports PBAP, update permissions... */ processPhonebookAccess(); @@ -661,8 +669,8 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> (getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0); if (comparison != 0) return comparison; - // Visible above not visible - comparison = (another.mVisible ? 1 : 0) - (mVisible ? 1 : 0); + // Just discovered above discovered in the past + comparison = (another.mJustDiscovered ? 1 : 0) - (mJustDiscovered ? 1 : 0); if (comparison != 0) return comparison; // Stronger signal above weaker signal diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java index abd4e294fecb..5b39ee4b57f1 100755 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java @@ -47,7 +47,7 @@ public class CachedBluetoothDeviceManager { } public static boolean onDeviceDisappeared(CachedBluetoothDevice cachedDevice) { - cachedDevice.setVisible(false); + cachedDevice.setJustDiscovered(false); return cachedDevice.getBondState() == BluetoothDevice.BOND_NONE; } @@ -131,7 +131,7 @@ public class CachedBluetoothDeviceManager { // Iterate in reverse order since devices may be removed. for (int i = mCachedDevices.size() - 1; i >= 0; i--) { CachedBluetoothDevice cachedDevice = mCachedDevices.get(i); - cachedDevice.setVisible(false); + cachedDevice.setJustDiscovered(false); } } @@ -156,7 +156,7 @@ public class CachedBluetoothDeviceManager { for (int i = mCachedDevices.size() - 1; i >= 0; i--) { CachedBluetoothDevice cachedDevice = mCachedDevices.get(i); if (cachedDevice.getBondState() != BluetoothDevice.BOND_BONDED) { - cachedDevice.setVisible(false); + cachedDevice.setJustDiscovered(false); mCachedDevices.remove(i); } else { // For bonded devices, we need to clear the connection status so that diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java index 426dc7c20a96..d588a6626bd5 100755 --- a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java +++ b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java @@ -50,6 +50,7 @@ public class BatteryMeterDrawableBase extends Drawable { protected final Paint mTextPaint; protected final Paint mBoltPaint; protected final Paint mPlusPaint; + protected float mButtonHeightFraction; private int mLevel = -1; private boolean mCharging; @@ -66,7 +67,6 @@ public class BatteryMeterDrawableBase extends Drawable { private final int mIntrinsicWidth; private final int mIntrinsicHeight; - private float mButtonHeightFraction; private float mSubpixelSmoothingLeft; private float mSubpixelSmoothingRight; private float mTextHeight, mWarningTextHeight; @@ -90,7 +90,6 @@ public class BatteryMeterDrawableBase extends Drawable { private final RectF mPlusFrame = new RectF(); private final Path mShapePath = new Path(); - private final Path mClipPath = new Path(); private final Path mTextPath = new Path(); public BatteryMeterDrawableBase(Context context, int frameColor) { @@ -298,7 +297,7 @@ public class BatteryMeterDrawableBase extends Drawable { float drawFrac = (float) level / 100f; final int height = mHeight; - final int width = (int) (ASPECT_RATIO * mHeight); + final int width = (int) (getAspectRatio() * mHeight); final int px = (mWidth - width) / 2; final int buttonHeight = Math.round(height * mButtonHeightFraction); @@ -329,7 +328,7 @@ public class BatteryMeterDrawableBase extends Drawable { // define the battery shape mShapePath.reset(); - final float radius = RADIUS_RATIO * (mFrame.height() + buttonHeight); + final float radius = getRadiusRatio() * (mFrame.height() + buttonHeight); mShapePath.setFillType(FillType.WINDING); mShapePath.addRoundRect(mFrame, radius, radius, Direction.CW); mShapePath.addRect(mButtonFrame, Direction.CW); @@ -429,10 +428,10 @@ public class BatteryMeterDrawableBase extends Drawable { // draw the battery shape, clipped to charging level mFrame.top = levelTop; - mClipPath.reset(); - mClipPath.addRect(mFrame, Path.Direction.CCW); - mShapePath.op(mClipPath, Path.Op.INTERSECT); + c.save(); + c.clipRect(mFrame); c.drawPath(mShapePath, mBatteryPaint); + c.restore(); if (!mCharging && !mPowerSaveEnabled) { if (level <= mCriticalLevel) { @@ -469,4 +468,12 @@ public class BatteryMeterDrawableBase extends Drawable { public int getCriticalLevel() { return mCriticalLevel; } + + protected float getAspectRatio() { + return ASPECT_RATIO; + } + + protected float getRadiusRatio() { + return RADIUS_RATIO; + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawable.java b/packages/SettingsLib/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawable.java new file mode 100644 index 000000000000..61790b96099f --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawable.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.graph; + +import android.annotation.NonNull; +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; +import android.support.annotation.VisibleForTesting; +import android.view.Gravity; +import android.view.View; + +import com.android.settingslib.R; +import com.android.settingslib.Utils; + +/** + * LayerDrawable contains the bluetooth device icon and battery gauge icon + */ +public class BluetoothDeviceLayerDrawable extends LayerDrawable { + + private BluetoothDeviceLayerDrawableState mState; + + private BluetoothDeviceLayerDrawable(@NonNull Drawable[] layers) { + super(layers); + } + + /** + * Create the {@link LayerDrawable} that contains bluetooth device icon and battery icon. + * This is a vertical layout drawable while bluetooth icon at top and battery icon at bottom. + * + * @param context used to get the spec for icon + * @param resId represents the bluetooth device drawable + * @param batteryLevel the battery level for bluetooth device + */ + public static BluetoothDeviceLayerDrawable createLayerDrawable(Context context, int resId, + int batteryLevel) { + final Drawable deviceDrawable = context.getDrawable(resId); + + final BatteryMeterDrawable batteryDrawable = new BatteryMeterDrawable(context, + R.color.meter_background_color, batteryLevel); + final int pad = context.getResources() + .getDimensionPixelSize(R.dimen.bt_battery_padding); + batteryDrawable.setPadding(0, pad, 0, pad); + + final BluetoothDeviceLayerDrawable drawable = new BluetoothDeviceLayerDrawable( + new Drawable[]{deviceDrawable, + rotateDrawable(context.getResources(), batteryDrawable)}); + // Set the bluetooth icon at the top + drawable.setLayerGravity(0 /* index of deviceDrawable */, Gravity.TOP); + // Set battery icon right below the bluetooth icon + drawable.setLayerInset(1 /* index of batteryDrawable */, 0, + deviceDrawable.getIntrinsicHeight(), 0, 0); + + drawable.setConstantState(context, resId, batteryLevel); + + return drawable; + } + + /** + * Rotate the {@code drawable} by 90 degree clockwise and return rotated {@link Drawable} + */ + private static Drawable rotateDrawable(Resources res, Drawable drawable) { + // Get the bitmap from drawable + final Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), + drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); + final Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + + // Create rotate matrix + final Matrix matrix = new Matrix(); + matrix.postRotate( + res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_LTR + ? 90 : 270); + + // Create new bitmap with rotate matrix + final Bitmap rotateBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), + bitmap.getHeight(), matrix, true); + bitmap.recycle(); + + return new BitmapDrawable(res, rotateBitmap); + } + + public void setConstantState(Context context, int resId, int batteryLevel) { + mState = new BluetoothDeviceLayerDrawableState(context, resId, batteryLevel); + } + + @Override + public ConstantState getConstantState() { + return mState; + } + + /** + * Battery gauge icon with new spec. + */ + @VisibleForTesting + static class BatteryMeterDrawable extends BatteryMeterDrawableBase { + private final float mAspectRatio; + + public BatteryMeterDrawable(Context context, int frameColor, int batteryLevel) { + super(context, frameColor); + final Resources resources = context.getResources(); + mButtonHeightFraction = resources.getFraction( + R.fraction.bt_battery_button_height_fraction, 1, 1); + mAspectRatio = resources.getFraction(R.fraction.bt_battery_ratio_fraction, 1, 1); + + final int tintColor = Utils.getColorAttr(context, android.R.attr.colorControlNormal); + setColorFilter(new PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN)); + setBatteryLevel(batteryLevel); + } + + @Override + protected float getAspectRatio() { + return mAspectRatio; + } + + @Override + protected float getRadiusRatio() { + // Remove the round edge + return 0; + } + } + + /** + * {@link ConstantState} to restore the {@link BluetoothDeviceLayerDrawable} + */ + private static class BluetoothDeviceLayerDrawableState extends ConstantState { + Context context; + int resId; + int batteryLevel; + + public BluetoothDeviceLayerDrawableState(Context context, int resId, + int batteryLevel) { + this.context = context; + this.resId = resId; + this.batteryLevel = batteryLevel; + } + + @Override + public Drawable newDrawable() { + return createLayerDrawable(context, resId, batteryLevel); + } + + @Override + public int getChangingConfigurations() { + return 0; + } + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionList.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionList.java index 2151ba096c62..a89092040e71 100644 --- a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionList.java +++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionList.java @@ -17,7 +17,6 @@ package com.android.settingslib.suggestions; import android.content.Intent; -import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -68,15 +67,6 @@ public class SuggestionList { return false; } - public List<Tile> getSuggestionForCategory(String category) { - for (Map.Entry<SuggestionCategory, List<Tile>> entry : mSuggestions.entrySet()) { - if (TextUtils.equals(entry.getKey().category, category)) { - return entry.getValue(); - } - } - return null; - } - /** * Filter suggestions list so they are all unique. */ diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java index 422690ae8f72..37969e01b94f 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java @@ -51,6 +51,7 @@ import android.support.annotation.NonNull; import android.text.Spannable; import android.text.SpannableString; import android.text.TextUtils; +import android.text.format.DateUtils; import android.text.style.TtsSpan; import android.util.Log; @@ -63,6 +64,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; @@ -124,11 +126,20 @@ public class AccessPoint implements Comparable<AccessPoint> { private final ConcurrentHashMap<String, ScanResult> mScanResultCache = new ConcurrentHashMap<String, ScanResult>(32); - /** Map of BSSIDs to speed values for individual ScanResults. */ - private final Map<String, Integer> mScanResultScores = new HashMap<>(); + /** + * Map of BSSIDs to scored networks for individual bssids. + * + * <p>This cache should not be evicted with scan results, as the values here are used to + * generate a fallback in the absence of scores for the visible APs. + */ + private final Map<String, TimestampedScoredNetwork> mScoredNetworkCache = new HashMap<>(); + + /** Maximum age in millis of cached scored networks in {@link #mScoredNetworkCache}. */ + @VisibleForTesting static final long MAX_CACHED_SCORE_AGE_MILLIS = + 24 * DateUtils.DAY_IN_MILLIS; /** Maximum age of scan results to hold onto while actively scanning. **/ - private static final long MAX_SCAN_RESULT_AGE_MS = 15000; + private static final long MAX_SCAN_RESULT_AGE_MILLIS = 15000; static final String KEY_NETWORKINFO = "key_networkinfo"; static final String KEY_WIFIINFO = "key_wifiinfo"; @@ -138,6 +149,7 @@ public class AccessPoint implements Comparable<AccessPoint> { static final String KEY_SPEED = "key_speed"; static final String KEY_PSKTYPE = "key_psktype"; static final String KEY_SCANRESULTCACHE = "key_scanresultcache"; + static final String KEY_SCOREDNETWORKCACHE = "key_scorednetworkcache"; static final String KEY_CONFIG = "key_config"; static final String KEY_FQDN = "key_fqdn"; static final String KEY_PROVIDER_FRIENDLY_NAME = "key_provider_friendly_name"; @@ -180,7 +192,6 @@ public class AccessPoint implements Comparable<AccessPoint> { private WifiConfiguration mConfig; private int mRssi = UNREACHABLE_RSSI; - private long mSeen = 0; private WifiInfo mInfo; private NetworkInfo mNetworkInfo; @@ -188,7 +199,7 @@ public class AccessPoint implements Comparable<AccessPoint> { private Object mTag; - private int mSpeed = Speed.NONE; + @Speed private int mSpeed = Speed.NONE; private boolean mIsScoredNetworkMetered = false; // used to co-relate internal vs returned accesspoint. @@ -238,6 +249,13 @@ public class AccessPoint implements Comparable<AccessPoint> { mScanResultCache.put(result.BSSID, result); } } + if (savedState.containsKey(KEY_SCOREDNETWORKCACHE)) { + ArrayList<TimestampedScoredNetwork> scoredNetworkArrayList = + savedState.getParcelableArrayList(KEY_SCOREDNETWORKCACHE); + for (TimestampedScoredNetwork timedScore : scoredNetworkArrayList) { + mScoredNetworkCache.put(timedScore.getScore().networkKey.wifiKey.bssid, timedScore); + } + } if (savedState.containsKey(KEY_FQDN)) { mFqdn = savedState.getString(KEY_FQDN); } @@ -257,7 +275,6 @@ public class AccessPoint implements Comparable<AccessPoint> { // Do not evict old scan results on initial creation updateRssi(); - updateSeen(); mId = sLastId.incrementAndGet(); } @@ -303,13 +320,12 @@ public class AccessPoint implements Comparable<AccessPoint> { this.pskType = that.pskType; this.mConfig = that.mConfig; //TODO: Watch out, this object is mutated. this.mRssi = that.mRssi; - this.mSeen = that.mSeen; this.mInfo = that.mInfo; this.mNetworkInfo = that.mNetworkInfo; this.mScanResultCache.clear(); this.mScanResultCache.putAll(that.mScanResultCache); - this.mScanResultScores.clear(); - this.mScanResultScores.putAll(that.mScanResultScores); + this.mScoredNetworkCache.clear(); + this.mScoredNetworkCache.putAll(that.mScoredNetworkCache); this.mId = that.mId; this.mSpeed = that.mSpeed; this.mIsScoredNetworkMetered = that.mIsScoredNetworkMetered; @@ -347,7 +363,7 @@ public class AccessPoint implements Comparable<AccessPoint> { if (isSaved() && !other.isSaved()) return -1; if (!isSaved() && other.isSaved()) return 1; - // Faster speeds go before slower speeds + // Faster speeds go before slower speeds - but only if visible change in speed label if (getSpeed() != other.getSpeed()) { return other.getSpeed() - getSpeed(); } @@ -425,7 +441,6 @@ public class AccessPoint implements Comparable<AccessPoint> { */ boolean update(WifiNetworkScoreCache scoreCache, boolean scoringUiEnabled) { boolean scoreChanged = false; - mScanResultScores.clear(); if (scoringUiEnabled) { scoreChanged = updateScores(scoreCache); } @@ -435,37 +450,99 @@ public class AccessPoint implements Comparable<AccessPoint> { /** * Updates the AccessPoint rankingScore and speed, returning true if the data has changed. * + * <p>Any cached {@link TimestampedScoredNetwork} objects older than + * {@link #MAX_CACHED_SCORE_AGE_MILLIS} will be removed when this method is invoked. + * + * <p>Precondition: {@link #mRssi} is up to date before invoking this method. + * * @param scoreCache The score cache to use to retrieve scores. + * @return true if the set speed has changed */ private boolean updateScores(WifiNetworkScoreCache scoreCache) { - int oldSpeed = mSpeed; - mSpeed = Speed.NONE; - + long nowMillis = SystemClock.elapsedRealtime(); for (ScanResult result : mScanResultCache.values()) { ScoredNetwork score = scoreCache.getScoredNetwork(result); if (score == null) { continue; } - - int speed = score.calculateBadge(result.level); - mScanResultScores.put(result.BSSID, speed); - mSpeed = Math.max(mSpeed, speed); + TimestampedScoredNetwork timedScore = mScoredNetworkCache.get(result.BSSID); + if (timedScore == null) { + mScoredNetworkCache.put( + result.BSSID, new TimestampedScoredNetwork(score, nowMillis)); + } else { + // Update data since the has been seen in the score cache + timedScore.update(score, nowMillis); + } } - // set mSpeed to the connected ScanResult if the AccessPoint is the active network + // Remove old cached networks + long evictionCutoff = nowMillis - MAX_CACHED_SCORE_AGE_MILLIS; + Iterator<TimestampedScoredNetwork> iterator = mScoredNetworkCache.values().iterator(); + iterator.forEachRemaining(timestampedScoredNetwork -> { + if (timestampedScoredNetwork.getUpdatedTimestampMillis() < evictionCutoff) { + iterator.remove(); + } + }); + + return updateSpeed(); + } + + /** + * Updates the internal speed, returning true if the update resulted in a speed label change. + */ + private boolean updateSpeed() { + int oldSpeed = mSpeed; + mSpeed = generateAverageSpeedForSsid(); + + // set speed to the connected ScanResult if the AccessPoint is the active network if (isActive() && mInfo != null) { - NetworkKey key = NetworkKey.createFromWifiInfo(mInfo); - ScoredNetwork score = scoreCache.getScoredNetwork(key); - if (score != null) { - mSpeed = score.calculateBadge(mInfo.getRssi()); + TimestampedScoredNetwork timedScore = mScoredNetworkCache.get(mInfo.getBSSID()); + if (timedScore != null) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "Set score using specific access point curve for connected AP: " + + getSsidStr()); + } + // TODO(b/63073866): Map using getLevel rather than specific rssi value so score + // doesn't change without a visible wifi bar change. + int speed = timedScore.getScore().calculateBadge(mInfo.getRssi()); + if (speed != Speed.NONE) { + mSpeed = speed; + } } } - if(WifiTracker.sVerboseLogging) { + boolean changed = oldSpeed != mSpeed; + if(WifiTracker.sVerboseLogging && changed) { Log.i(TAG, String.format("%s: Set speed to %d", ssid, mSpeed)); } + return changed; + } + + /** Creates a speed value for the current {@link #mRssi} by averaging all non zero badges. */ + @Speed private int generateAverageSpeedForSsid() { + if (mScoredNetworkCache.isEmpty()) { + return Speed.NONE; + } - return oldSpeed != mSpeed; + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, String.format("Generating fallbackspeed for %s using cache: %s", + getSsidStr(), mScoredNetworkCache)); + } + + int count = 0; + int totalSpeed = 0; + for (TimestampedScoredNetwork timedScore : mScoredNetworkCache.values()) { + int speed = timedScore.getScore().calculateBadge(mRssi); + if (speed != Speed.NONE) { + count++; + totalSpeed += speed; + } + } + int speed = count == 0 ? Speed.NONE : totalSpeed / count; + if (WifiTracker.sVerboseLogging) { + Log.i(TAG, String.format("%s generated fallback speed is: %d", getSsidStr(), speed)); + } + return roundToClosestSpeedEnum(speed); } /** @@ -499,7 +576,7 @@ public class AccessPoint implements Comparable<AccessPoint> { for (Iterator<ScanResult> iter = mScanResultCache.values().iterator(); iter.hasNext(); ) { ScanResult result = iter.next(); // result timestamp is in microseconds - if (nowMs - result.timestamp / 1000 > MAX_SCAN_RESULT_AGE_MS) { + if (nowMs - result.timestamp / 1000 > MAX_SCAN_RESULT_AGE_MILLIS) { iter.remove(); } } @@ -578,23 +655,6 @@ public class AccessPoint implements Comparable<AccessPoint> { } } - /** Updates {@link #mSeen} based on the scan result cache. */ - private void updateSeen() { - // TODO(sghuman): Set to now if connected - - long seen = 0; - for (ScanResult result : mScanResultCache.values()) { - if (result.timestamp > seen) { - seen = result.timestamp; - } - } - - // Only replace the previous value if we have a recent scan result to use - if (seen != 0) { - mSeen = seen; - } - } - /** * Returns if the network should be considered metered. */ @@ -940,17 +1000,23 @@ public class AccessPoint implements Comparable<AccessPoint> { } stringBuilder.append("=").append(result.frequency); stringBuilder.append(",").append(result.level); - if (hasSpeed(result)) { + int speed = getSpecificApSpeed(result); + if (speed != Speed.NONE) { stringBuilder.append(",") - .append(getSpeedLabel(mScanResultScores.get(result.BSSID))); + .append(getSpeedLabel(speed)); } stringBuilder.append("}"); return stringBuilder.toString(); } - private boolean hasSpeed(ScanResult result) { - return mScanResultScores.containsKey(result.BSSID) - && mScanResultScores.get(result.BSSID) != Speed.NONE; + @Speed private int getSpecificApSpeed(ScanResult result) { + TimestampedScoredNetwork timedScore = mScoredNetworkCache.get(result.BSSID); + if (timedScore == null) { + return Speed.NONE; + } + // For debugging purposes we may want to use mRssi rather than result.level as the average + // speed wil be determined by mRssi + return timedScore.getScore().calculateBadge(result.level); } /** @@ -1049,7 +1115,6 @@ public class AccessPoint implements Comparable<AccessPoint> { mScanResultCache.put(result.BSSID, result); updateRssi(); - mSeen = result.timestamp; // even if the timestamp is old it is still valid mIsCarrierAp = result.isCarrierAp; mCarrierApEapType = result.carrierApEapType; mCarrierName = result.carrierName; @@ -1065,6 +1130,8 @@ public class AccessPoint implements Comparable<AccessPoint> { evictOldScanResults(); savedState.putParcelableArrayList(KEY_SCANRESULTCACHE, new ArrayList<ScanResult>(mScanResultCache.values())); + savedState.putParcelableArrayList(KEY_SCOREDNETWORKCACHE, + new ArrayList<>(mScoredNetworkCache.values())); if (mNetworkInfo != null) { savedState.putParcelable(KEY_NETWORKINFO, mNetworkInfo); } @@ -1099,12 +1166,15 @@ public class AccessPoint implements Comparable<AccessPoint> { /* Add or update the scan result for the BSSID */ mScanResultCache.put(result.BSSID, result); if (evictOldScanResults) evictOldScanResults(); - updateSeen(); updateRssi(); int newLevel = getLevel(); - if (newLevel > 0 && newLevel != oldLevel && mAccessPointListener != null) { - mAccessPointListener.onLevelChanged(this); + if (newLevel > 0 && newLevel != oldLevel) { + // Only update labels on visible rssi changes + updateSpeed(); + if (mAccessPointListener != null) { + mAccessPointListener.onLevelChanged(this); + } } // This flag only comes from scans, is not easily saved in config if (security == SECURITY_PSK) { @@ -1189,7 +1259,23 @@ public class AccessPoint implements Comparable<AccessPoint> { } @Nullable - private String getSpeedLabel(int speed) { + @Speed + private int roundToClosestSpeedEnum(int speed) { + if (speed < Speed.SLOW) { + return Speed.NONE; + } else if (speed < (Speed.SLOW + Speed.MODERATE) / 2) { + return Speed.SLOW; + } else if (speed < (Speed.MODERATE + Speed.FAST) / 2) { + return Speed.MODERATE; + } else if (speed < (Speed.FAST + Speed.VERY_FAST) / 2) { + return Speed.FAST; + } else { + return Speed.VERY_FAST; + } + } + + @Nullable + private String getSpeedLabel(@Speed int speed) { switch (speed) { case Speed.VERY_FAST: return mContext.getString(R.string.speed_label_very_fast); diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java index 2c4f9c432194..0ecb8be627f6 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java @@ -15,13 +15,13 @@ */ package com.android.settingslib.wifi; +import android.annotation.Nullable; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.graphics.drawable.StateListDrawable; -import android.net.NetworkBadging; import android.net.wifi.WifiConfiguration; import android.os.Looper; import android.os.UserHandle; @@ -37,6 +37,7 @@ import android.widget.TextView; import com.android.settingslib.R; import com.android.settingslib.TronUtils; import com.android.settingslib.Utils; +import com.android.settingslib.wifi.AccessPoint.Speed; public class AccessPointPreference extends Preference { @@ -60,9 +61,10 @@ public class AccessPointPreference extends Preference { R.string.accessibility_wifi_signal_full }; - private final StateListDrawable mFrictionSld; + @Nullable private final StateListDrawable mFrictionSld; private final int mBadgePadding; private final UserBadgeCache mBadgeCache; + private final IconInjector mIconInjector; private TextView mTitleView; private boolean mForSavedNetworks = false; @@ -71,7 +73,7 @@ public class AccessPointPreference extends Preference { private int mLevel; private CharSequence mContentDescription; private int mDefaultIconResId; - private int mWifiSpeed = NetworkBadging.BADGING_NONE; + private int mWifiSpeed = Speed.NONE; public static String generatePreferenceKey(AccessPoint accessPoint) { StringBuilder builder = new StringBuilder(); @@ -86,60 +88,53 @@ public class AccessPointPreference extends Preference { return builder.toString(); } + @Nullable + private static StateListDrawable getFrictionStateListDrawable(Context context) { + TypedArray frictionSld; + try { + frictionSld = context.getTheme().obtainStyledAttributes(FRICTION_ATTRS); + } catch (Resources.NotFoundException e) { + // Fallback for platforms that do not need friction icon resources. + frictionSld = null; + } + return frictionSld != null ? (StateListDrawable) frictionSld.getDrawable(0) : null; + } + // Used for dummy pref. public AccessPointPreference(Context context, AttributeSet attrs) { super(context, attrs); mFrictionSld = null; mBadgePadding = 0; mBadgeCache = null; + mIconInjector = new IconInjector(context); } public AccessPointPreference(AccessPoint accessPoint, Context context, UserBadgeCache cache, boolean forSavedNetworks) { - super(context); - setWidgetLayoutResource(R.layout.access_point_friction_widget); - mBadgeCache = cache; - mAccessPoint = accessPoint; - mForSavedNetworks = forSavedNetworks; - mAccessPoint.setTag(this); - mLevel = -1; - - TypedArray frictionSld; - try { - frictionSld = context.getTheme().obtainStyledAttributes(FRICTION_ATTRS); - } catch (Resources.NotFoundException e) { - // Fallback for platforms that do not need friction icon resources. - frictionSld = null; - } - mFrictionSld = frictionSld != null ? (StateListDrawable) frictionSld.getDrawable(0) : null; - - // Distance from the end of the title at which this AP's user badge should sit. - mBadgePadding = context.getResources() - .getDimensionPixelSize(R.dimen.wifi_preference_badge_padding); + this(accessPoint, context, cache, 0 /* iconResId */, forSavedNetworks); refresh(); } public AccessPointPreference(AccessPoint accessPoint, Context context, UserBadgeCache cache, int iconResId, boolean forSavedNetworks) { + this(accessPoint, context, cache, iconResId, forSavedNetworks, + getFrictionStateListDrawable(context), -1 /* level */, new IconInjector(context)); + } + + @VisibleForTesting + AccessPointPreference(AccessPoint accessPoint, Context context, UserBadgeCache cache, + int iconResId, boolean forSavedNetworks, StateListDrawable frictionSld, + int level, IconInjector iconInjector) { super(context); setWidgetLayoutResource(R.layout.access_point_friction_widget); mBadgeCache = cache; mAccessPoint = accessPoint; mForSavedNetworks = forSavedNetworks; mAccessPoint.setTag(this); - mLevel = -1; + mLevel = level; mDefaultIconResId = iconResId; - - TypedArray frictionSld; - try { - frictionSld = context.getTheme().obtainStyledAttributes(FRICTION_ATTRS); - } catch (Resources.NotFoundException e) { - // Fallback for platforms that do not need friction icon resources. - frictionSld = null; - } - mFrictionSld = frictionSld != null ? (StateListDrawable) frictionSld.getDrawable(0) : null; - - // Distance from the end of the title at which this AP's user badge should sit. + mFrictionSld = frictionSld; + mIconInjector = iconInjector; mBadgePadding = context.getResources() .getDimensionPixelSize(R.dimen.wifi_preference_badge_padding); } @@ -179,9 +174,7 @@ public class AccessPointPreference extends Preference { } TronUtils.logWifiSettingsSpeed(context, mWifiSpeed); - // TODO(b/62355275): Revert this to N code after deleting NetworkBadging API - Drawable drawable = NetworkBadging.getWifiIcon( - level, NetworkBadging.BADGING_NONE, getContext().getTheme()); + Drawable drawable = mIconInjector.getIcon(level); if (!mForSavedNetworks && drawable != null) { drawable.setTint(Utils.getColorAttr(context, android.R.attr.colorControlNormal)); setIcon(drawable); @@ -321,4 +314,16 @@ public class AccessPointPreference extends Preference { return mBadges.valueAt(index); } } + + static class IconInjector { + private final Context mContext; + + public IconInjector(Context context) { + mContext = context; + } + + public Drawable getIcon(int level) { + return mContext.getDrawable(Utils.getWifiIconResource(level)); + } + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java b/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java index 93bf3c7ec20e..3dec1d382026 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java @@ -24,6 +24,7 @@ import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.os.Bundle; import android.support.annotation.Keep; + import com.android.settingslib.wifi.AccessPoint.Speed; import java.util.ArrayList; @@ -58,6 +59,7 @@ public class TestAccessPointBuilder { Context mContext; private ArrayList<ScanResult> mScanResultCache; + private ArrayList<TimestampedScoredNetwork> mScoredNetworkCache; @Keep public TestAccessPointBuilder(Context context) { @@ -85,6 +87,9 @@ public class TestAccessPointBuilder { if (mScanResultCache != null) { bundle.putParcelableArrayList(AccessPoint.KEY_SCANRESULTCACHE, mScanResultCache); } + if (mScoredNetworkCache != null) { + bundle.putParcelableArrayList(AccessPoint.KEY_SCOREDNETWORKCACHE, mScoredNetworkCache); + } bundle.putInt(AccessPoint.KEY_SECURITY, mSecurity); bundle.putInt(AccessPoint.KEY_SPEED, mSpeed); bundle.putBoolean(AccessPoint.KEY_IS_CARRIER_AP, mIsCarrierAp); @@ -238,4 +243,10 @@ public class TestAccessPointBuilder { mCarrierName = carrierName; return this; } + + public TestAccessPointBuilder setScoredNetworkCache( + ArrayList<TimestampedScoredNetwork> scoredNetworkCache) { + mScoredNetworkCache = scoredNetworkCache; + return this; + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/TimestampedScoredNetwork.java b/packages/SettingsLib/src/com/android/settingslib/wifi/TimestampedScoredNetwork.java new file mode 100644 index 000000000000..cb15a795fe9b --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/TimestampedScoredNetwork.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.wifi; + +import android.net.ScoredNetwork; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Data encapsulation object to associate a time with a {@link ScoredNetwork} + */ +class TimestampedScoredNetwork implements Parcelable { + private ScoredNetwork mScore; + private long mUpdatedTimestampMillis; + + TimestampedScoredNetwork(ScoredNetwork score, long updatedTimestampMillis) { + mScore = score; + mUpdatedTimestampMillis = updatedTimestampMillis; + } + + protected TimestampedScoredNetwork(Parcel in) { + mScore = ScoredNetwork.CREATOR.createFromParcel(in); + mUpdatedTimestampMillis = in.readLong(); + } + + public void update(ScoredNetwork score, long updatedTimestampMillis) { + mScore = score; + mUpdatedTimestampMillis = updatedTimestampMillis; + } + + public ScoredNetwork getScore() { + return mScore; + } + + public long getUpdatedTimestampMillis() { + return mUpdatedTimestampMillis; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(mScore, flags); + dest.writeLong(mUpdatedTimestampMillis); + } + + public static final Creator<TimestampedScoredNetwork> CREATOR = + new Creator<TimestampedScoredNetwork>() { + @Override + public TimestampedScoredNetwork createFromParcel(Parcel in) { + return new TimestampedScoredNetwork(in); + } + + @Override + public TimestampedScoredNetwork[] newArray(int size) { + return new TimestampedScoredNetwork[size]; + } + }; +} diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java index a242570d6930..8ef6a0df7204 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java @@ -149,6 +149,20 @@ public class WifiTracker { @GuardedBy("mLock") private boolean mStaleScanResults = true; + private static IntentFilter newIntentFilter() { + IntentFilter filter = new IntentFilter(); + filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); + filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); + filter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION); + filter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); + filter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION); + filter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION); + filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); + filter.addAction(WifiManager.RSSI_CHANGED_ACTION); + + return filter; + } + public WifiTracker(Context context, WifiListener wifiListener, boolean includeSaved, boolean includeScans) { this(context, wifiListener, null, includeSaved, includeScans); @@ -165,19 +179,20 @@ public class WifiTracker { } public WifiTracker(Context context, WifiListener wifiListener, Looper workerLooper, - boolean includeSaved, boolean includeScans, boolean includePasspoints) { + boolean includeSaved, boolean includeScans, boolean includePasspoints) { this(context, wifiListener, workerLooper, includeSaved, includeScans, includePasspoints, context.getSystemService(WifiManager.class), context.getSystemService(ConnectivityManager.class), - context.getSystemService(NetworkScoreManager.class), Looper.myLooper() - ); + context.getSystemService(NetworkScoreManager.class), + Looper.myLooper(), newIntentFilter()); } @VisibleForTesting WifiTracker(Context context, WifiListener wifiListener, Looper workerLooper, - boolean includeSaved, boolean includeScans, boolean includePasspoints, - WifiManager wifiManager, ConnectivityManager connectivityManager, - NetworkScoreManager networkScoreManager, Looper currentLooper) { + boolean includeSaved, boolean includeScans, boolean includePasspoints, + WifiManager wifiManager, ConnectivityManager connectivityManager, + NetworkScoreManager networkScoreManager, Looper currentLooper, + IntentFilter filter) { if (!includeSaved && !includeScans) { throw new IllegalArgumentException("Must include either saved or scans"); } @@ -199,15 +214,7 @@ public class WifiTracker { // check if verbose logging has been turned on or off sVerboseLogging = (mWifiManager.getVerboseLoggingLevel() > 0); - mFilter = new IntentFilter(); - mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); - mFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); - mFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION); - mFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); - mFilter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION); - mFilter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION); - mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); - mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION); + mFilter = filter; mNetworkRequest = new NetworkRequest.Builder() .clearCapabilities() diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java index fed18fa1bcb0..751b4ba316d7 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java @@ -110,6 +110,27 @@ public class ApplicationsStateTest { } @Test + public void testPhotosFilterAcceptsFilter() { + mEntry.info.category = ApplicationInfo.CATEGORY_IMAGE; + + assertThat(ApplicationsState.FILTER_PHOTOS.filterApp(mEntry)).isTrue(); + } + + @Test + public void testPhotosFilterRejectsNotPhotos() { + mEntry.info.category = ApplicationInfo.CATEGORY_VIDEO; + + assertThat(ApplicationsState.FILTER_PHOTOS.filterApp(mEntry)).isFalse(); + } + + @Test + public void testPhotosFilterRejectsDefaultCategory() { + mEntry.info.category = ApplicationInfo.CATEGORY_UNDEFINED; + + assertThat(ApplicationsState.FILTER_PHOTOS.filterApp(mEntry)).isFalse(); + } + + @Test public void testDownloadAndLauncherAndInstantAcceptsCorrectApps() { // should include instant apps mEntry.isHomeApp = false; diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java index ae59d3781430..6f1b25f6747e 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java @@ -21,8 +21,6 @@ import static com.google.common.truth.Truth.assertWithMessage; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -50,8 +48,8 @@ import android.text.SpannableString; import android.text.style.TtsSpan; import com.android.settingslib.R; - import com.android.settingslib.wifi.AccessPoint.Speed; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -59,17 +57,36 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; @SmallTest @RunWith(AndroidJUnit4.class) public class AccessPointTest { - private static final String TEST_SSID = "test_ssid"; + private static final String TEST_SSID = "\"test_ssid\""; + private static final int NUM_SCAN_RESULTS = 5; + + private static final ArrayList<ScanResult> SCAN_RESULTS = buildScanResultCache(); + + private static final RssiCurve FAST_BADGE_CURVE = + new RssiCurve(-150, 10, new byte[]{Speed.FAST}); + public static final String TEST_BSSID = "00:00:00:00:00:00"; + private Context mContext; @Mock private RssiCurve mockBadgeCurve; @Mock private WifiNetworkScoreCache mockWifiNetworkScoreCache; + private static ScanResult createScanResult(String ssid, String bssid, int rssi) { + ScanResult scanResult = new ScanResult(); + scanResult.SSID = ssid; + scanResult.level = rssi; + scanResult.BSSID = bssid; + scanResult.timestamp = SystemClock.elapsedRealtime() * 1000; + scanResult.capabilities = ""; + return scanResult; + } + @Before public void setUp() { MockitoAnnotations.initMocks(this); @@ -400,7 +417,7 @@ public class AccessPointTest { } @Test - public void testSpeedLabel_isDerivedFromConnectedBssid() { + public void testSpeedLabel_isDerivedFromConnectedBssidWhenScoreAvailable() { int rssi = -55; String bssid = "00:00:00:00:00:00"; int networkId = 123; @@ -411,24 +428,42 @@ public class AccessPointTest { info.setBSSID(bssid); info.setNetworkId(networkId); + ArrayList<ScanResult> scanResults = new ArrayList<>(); + ScanResult scanResultUnconnected = createScanResult(TEST_SSID, "11:11:11:11:11:11", rssi); + scanResults.add(scanResultUnconnected); + + ScanResult scanResultConnected = createScanResult(TEST_SSID, bssid, rssi); + scanResults.add(scanResultConnected); + AccessPoint ap = new TestAccessPointBuilder(mContext) .setActive(true) .setNetworkId(networkId) .setSsid(TEST_SSID) - .setScanResultCache(buildScanResultCache()) + .setScanResultCache(scanResults) .setWifiInfo(info) .build(); - NetworkKey key = new NetworkKey(new WifiKey('"' + TEST_SSID + '"', bssid)); - when(mockWifiNetworkScoreCache.getScoredNetwork(key)) + when(mockWifiNetworkScoreCache.getScoredNetwork(scanResultUnconnected)) .thenReturn(buildScoredNetworkWithMockBadgeCurve()); - when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) AccessPoint.Speed.FAST); + when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) Speed.SLOW); + + int connectedSpeed = Speed.VERY_FAST; + RssiCurve connectedBadgeCurve = mock(RssiCurve.class); + Bundle attr1 = new Bundle(); + attr1.putParcelable(ScoredNetwork.ATTRIBUTES_KEY_BADGING_CURVE, connectedBadgeCurve); + ScoredNetwork connectedScore = new ScoredNetwork( + NetworkKey.createFromScanResult(scanResultConnected), + connectedBadgeCurve, + false /* meteredHint */, + attr1); + when(mockWifiNetworkScoreCache.getScoredNetwork(scanResultConnected)) + .thenReturn(connectedScore); + when(connectedBadgeCurve.lookupScore(anyInt())).thenReturn((byte) connectedSpeed); ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */); - verify(mockWifiNetworkScoreCache, times(2)).getScoredNetwork(key); - assertThat(ap.getSpeed()).isEqualTo(AccessPoint.Speed.FAST); + assertThat(ap.getSpeed()).isEqualTo(connectedSpeed); } @Test @@ -562,11 +597,16 @@ public class AccessPointTest { } private ScoredNetwork buildScoredNetworkWithMockBadgeCurve() { + return buildScoredNetworkWithGivenBadgeCurve(mockBadgeCurve); + + } + + private ScoredNetwork buildScoredNetworkWithGivenBadgeCurve(RssiCurve badgeCurve) { Bundle attr1 = new Bundle(); - attr1.putParcelable(ScoredNetwork.ATTRIBUTES_KEY_BADGING_CURVE, mockBadgeCurve); + attr1.putParcelable(ScoredNetwork.ATTRIBUTES_KEY_BADGING_CURVE, badgeCurve); return new ScoredNetwork( - new NetworkKey(new WifiKey("\"ssid\"", "00:00:00:00:00:00")), - mockBadgeCurve, + new NetworkKey(new WifiKey(TEST_SSID, TEST_BSSID)), + badgeCurve, false /* meteredHint */, attr1); @@ -574,19 +614,14 @@ public class AccessPointTest { private AccessPoint createAccessPointWithScanResultCache() { Bundle bundle = new Bundle(); - ArrayList<ScanResult> scanResults = buildScanResultCache(); - bundle.putParcelableArrayList(AccessPoint.KEY_SCANRESULTCACHE, scanResults); + bundle.putParcelableArrayList(AccessPoint.KEY_SCANRESULTCACHE, SCAN_RESULTS); return new AccessPoint(mContext, bundle); } - private ArrayList<ScanResult> buildScanResultCache() { + private static ArrayList<ScanResult> buildScanResultCache() { ArrayList<ScanResult> scanResults = new ArrayList<>(); for (int i = 0; i < 5; i++) { - ScanResult scanResult = new ScanResult(); - scanResult.level = i; - scanResult.BSSID = "bssid-" + i; - scanResult.timestamp = SystemClock.elapsedRealtime() * 1000; - scanResult.capabilities = ""; + ScanResult scanResult = createScanResult(TEST_SSID, "bssid-" + i, i); scanResults.add(scanResult); } return scanResults; @@ -600,6 +635,18 @@ public class AccessPointTest { return configuration; } + private AccessPoint createApWithFastTimestampedScoredNetworkCache( + long elapsedTimeMillis) { + TimestampedScoredNetwork recentScore = new TimestampedScoredNetwork( + buildScoredNetworkWithGivenBadgeCurve(FAST_BADGE_CURVE), + elapsedTimeMillis); + return new TestAccessPointBuilder(mContext) + .setSsid(TEST_SSID) + .setScoredNetworkCache( + new ArrayList<>(Arrays.asList(recentScore))) + .build(); + } + /** * Assert that the first AccessPoint appears before the second AccessPoint * once sorting has been completed. @@ -849,4 +896,194 @@ public class AccessPointTest { ap.update(null, wifiInfo, networkInfo); } + + @Test + public void testSpeedLabelAveragesAllBssidScores() { + AccessPoint ap = createAccessPointWithScanResultCache(); + + int speed1 = Speed.MODERATE; + RssiCurve badgeCurve1 = mock(RssiCurve.class); + when(badgeCurve1.lookupScore(anyInt())).thenReturn((byte) speed1); + when(mockWifiNetworkScoreCache.getScoredNetwork(SCAN_RESULTS.get(0))) + .thenReturn(buildScoredNetworkWithGivenBadgeCurve(badgeCurve1)); + int speed2 = Speed.VERY_FAST; + RssiCurve badgeCurve2 = mock(RssiCurve.class); + when(badgeCurve2.lookupScore(anyInt())).thenReturn((byte) speed2); + when(mockWifiNetworkScoreCache.getScoredNetwork(SCAN_RESULTS.get(1))) + .thenReturn(buildScoredNetworkWithGivenBadgeCurve(badgeCurve2)); + + int expectedSpeed = (speed1 + speed2) / 2; + + ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */); + + assertThat(ap.getSpeed()).isEqualTo(expectedSpeed); + } + + @Test + public void testSpeedLabelAverageIgnoresNoSpeedScores() { + AccessPoint ap = createAccessPointWithScanResultCache(); + + int speed1 = Speed.VERY_FAST; + RssiCurve badgeCurve1 = mock(RssiCurve.class); + when(badgeCurve1.lookupScore(anyInt())).thenReturn((byte) speed1); + when(mockWifiNetworkScoreCache.getScoredNetwork(SCAN_RESULTS.get(0))) + .thenReturn(buildScoredNetworkWithGivenBadgeCurve(badgeCurve1)); + int speed2 = Speed.NONE; + RssiCurve badgeCurve2 = mock(RssiCurve.class); + when(badgeCurve2.lookupScore(anyInt())).thenReturn((byte) speed2); + when(mockWifiNetworkScoreCache.getScoredNetwork(SCAN_RESULTS.get(1))) + .thenReturn(buildScoredNetworkWithGivenBadgeCurve(badgeCurve2)); + + ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */); + + assertThat(ap.getSpeed()).isEqualTo(speed1); + } + + @Test + public void testSpeedLabelUsesFallbackScoreWhenConnectedAccessPointScoreUnavailable() { + int rssi = -55; + String bssid = "00:00:00:00:00:00"; + int networkId = 123; + + WifiInfo info = new WifiInfo(); + info.setRssi(rssi); + info.setSSID(WifiSsid.createFromAsciiEncoded(TEST_SSID)); + info.setBSSID(bssid); + info.setNetworkId(networkId); + + ArrayList<ScanResult> scanResults = new ArrayList<>(); + ScanResult scanResultUnconnected = createScanResult(TEST_SSID, "11:11:11:11:11:11", rssi); + scanResults.add(scanResultUnconnected); + + ScanResult scanResultConnected = createScanResult(TEST_SSID, bssid, rssi); + scanResults.add(scanResultConnected); + + AccessPoint ap = + new TestAccessPointBuilder(mContext) + .setActive(true) + .setNetworkId(networkId) + .setSsid(TEST_SSID) + .setScanResultCache(scanResults) + .setWifiInfo(info) + .build(); + + int fallbackSpeed = Speed.SLOW; + when(mockWifiNetworkScoreCache.getScoredNetwork(scanResultUnconnected)) + .thenReturn(buildScoredNetworkWithMockBadgeCurve()); + when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) fallbackSpeed); + + when(mockWifiNetworkScoreCache.getScoredNetwork(scanResultConnected)) + .thenReturn(null); + + ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */); + + assertThat(ap.getSpeed()).isEqualTo(fallbackSpeed); + } + + @Test + public void testScoredNetworkCacheBundling() { + long timeMillis = SystemClock.elapsedRealtime(); + AccessPoint ap = createApWithFastTimestampedScoredNetworkCache(timeMillis); + Bundle bundle = new Bundle(); + ap.saveWifiState(bundle); + + ArrayList<TimestampedScoredNetwork> list = + bundle.getParcelableArrayList(AccessPoint.KEY_SCOREDNETWORKCACHE); + assertThat(list).hasSize(1); + assertThat(list.get(0).getUpdatedTimestampMillis()).isEqualTo(timeMillis); + + RssiCurve curve = list.get(0).getScore().attributes.getParcelable( + ScoredNetwork.ATTRIBUTES_KEY_BADGING_CURVE); + assertThat(curve).isEqualTo(FAST_BADGE_CURVE); + } + + @Test + public void testRecentNetworkScoresAreUsedForSpeedLabelGeneration() { + AccessPoint ap = + createApWithFastTimestampedScoredNetworkCache(SystemClock.elapsedRealtime()); + + ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */); + + assertThat(ap.getSpeed()).isEqualTo(Speed.FAST); + } + + @Test + public void testNetworkScoresAreUsedForSpeedLabelGenerationWhenWithinAgeRange() { + long withinRangeTimeMillis = + SystemClock.elapsedRealtime() - (AccessPoint.MAX_CACHED_SCORE_AGE_MILLIS - 10000); + AccessPoint ap = + createApWithFastTimestampedScoredNetworkCache(withinRangeTimeMillis); + + ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */); + + assertThat(ap.getSpeed()).isEqualTo(Speed.FAST); + } + + @Test + public void testOldNetworkScoresAreNotUsedForSpeedLabelGeneration() { + long tooOldTimeMillis = + SystemClock.elapsedRealtime() - (AccessPoint.MAX_CACHED_SCORE_AGE_MILLIS + 1); + AccessPoint ap = + createApWithFastTimestampedScoredNetworkCache(tooOldTimeMillis); + + ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */); + + assertThat(ap.getSpeed()).isEqualTo(Speed.NONE); + } + + @Test + public void testUpdateScoresRefreshesScoredNetworkCacheTimestamps () { + long tooOldTimeMillis = + SystemClock.elapsedRealtime() - (AccessPoint.MAX_CACHED_SCORE_AGE_MILLIS + 1); + + ScoredNetwork scoredNetwork = buildScoredNetworkWithGivenBadgeCurve(FAST_BADGE_CURVE); + TimestampedScoredNetwork recentScore = new TimestampedScoredNetwork( + scoredNetwork, + tooOldTimeMillis); + AccessPoint ap = new TestAccessPointBuilder(mContext) + .setSsid(TEST_SSID) + .setBssid(TEST_BSSID) + .setActive(true) + .setScoredNetworkCache( + new ArrayList(Arrays.asList(recentScore))) + .setScanResultCache(SCAN_RESULTS) + .build(); + + when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class))) + .thenReturn(scoredNetwork); + + ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */); + + // Fast should still be returned since cache was updated with recent time + assertThat(ap.getSpeed()).isEqualTo(Speed.FAST); + } + + @Test + public void testUpdateScoresRefreshesScoredNetworkCacheWithNewSpeed () { + long tooOldTimeMillis = + SystemClock.elapsedRealtime() - (AccessPoint.MAX_CACHED_SCORE_AGE_MILLIS + 1); + + ScoredNetwork scoredNetwork = buildScoredNetworkWithGivenBadgeCurve(FAST_BADGE_CURVE); + TimestampedScoredNetwork recentScore = new TimestampedScoredNetwork( + scoredNetwork, + tooOldTimeMillis); + AccessPoint ap = new TestAccessPointBuilder(mContext) + .setSsid(TEST_SSID) + .setBssid(TEST_BSSID) + .setActive(true) + .setScoredNetworkCache( + new ArrayList(Arrays.asList(recentScore))) + .setScanResultCache(SCAN_RESULTS) + .build(); + + int newSpeed = Speed.MODERATE; + when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class))) + .thenReturn(buildScoredNetworkWithMockBadgeCurve()); + when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) newSpeed); + + ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */); + + // Fast should still be returned since cache was updated with recent time + assertThat(ap.getSpeed()).isEqualTo(newSpeed); + } } diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java index df6587e5042f..3d01f6bce565 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java @@ -36,6 +36,7 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.Network; import android.net.NetworkInfo; @@ -265,21 +266,18 @@ public class WifiTrackerTest { } private WifiTracker createMockedWifiTracker() { - WifiTracker tracker = - new WifiTracker( - mContext, - mockWifiListener, - mWorkerLooper, - true, - true, - true, - mockWifiManager, - mockConnectivityManager, - mockNetworkScoreManager, - mMainLooper - ); - - return tracker; + return new WifiTracker( + mContext, + mockWifiListener, + mWorkerLooper, + true, + true, + true, + mockWifiManager, + mockConnectivityManager, + mockNetworkScoreManager, + mMainLooper, + new IntentFilter()); // empty filter to ignore system broadcasts } private void startTracking(WifiTracker tracker) throws InterruptedException { diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java index e2ebbeb411fb..b1dbb0af54a7 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java @@ -17,8 +17,12 @@ package com.android.settingslib.bluetooth; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; @@ -42,6 +46,10 @@ import org.robolectric.annotation.Config; @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, resourceDir = "../../res") public class CachedBluetoothDeviceTest { + private final static String DEVICE_NAME = "TestName"; + private final static String DEVICE_ALIAS = "TestAlias"; + private final static String DEVICE_ADDRESS = "AA:BB:CC:DD:EE:FF"; + private final static String DEVICE_ALIAS_NEW = "TestAliasNew"; @Mock private LocalBluetoothAdapter mAdapter; @Mock @@ -62,6 +70,7 @@ public class CachedBluetoothDeviceTest { public void setUp() { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; + when(mDevice.getAddress()).thenReturn(DEVICE_ADDRESS); when(mAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON); when(mHfpProfile.isProfileReady()).thenReturn(true); when(mA2dpProfile.isProfileReady()).thenReturn(true); @@ -152,4 +161,49 @@ public class CachedBluetoothDeviceTest { mCachedDevice.onProfileStateChanged(mHidProfile, BluetoothProfile.STATE_DISCONNECTED); assertThat(mCachedDevice.getConnectionSummary()).isNull(); } + + @Test + public void testDeviceName_testAliasNameAvailable() { + when(mDevice.getAliasName()).thenReturn(DEVICE_ALIAS); + when(mDevice.getName()).thenReturn(DEVICE_NAME); + CachedBluetoothDevice cachedBluetoothDevice = + new CachedBluetoothDevice(mContext, mAdapter, mProfileManager, mDevice); + // Verify alias is returned on getName + assertThat(cachedBluetoothDevice.getName()).isEqualTo(DEVICE_ALIAS); + // Verify device is visible + assertThat(cachedBluetoothDevice.hasHumanReadableName()).isTrue(); + } + + @Test + public void testDeviceName_testNameNotAvailable() { + CachedBluetoothDevice cachedBluetoothDevice = + new CachedBluetoothDevice(mContext, mAdapter, mProfileManager, mDevice); + // Verify device address is returned on getName + assertThat(cachedBluetoothDevice.getName()).isEqualTo(DEVICE_ADDRESS); + // Verify device is not visible + assertThat(cachedBluetoothDevice.hasHumanReadableName()).isFalse(); + } + + @Test + public void testDeviceName_testRenameDevice() { + final String[] alias = {DEVICE_ALIAS}; + doAnswer(invocation -> alias[0]).when(mDevice).getAliasName(); + doAnswer(invocation -> { + alias[0] = (String) invocation.getArguments()[0]; + return true; + }).when(mDevice).setAlias(anyString()); + when(mDevice.getName()).thenReturn(DEVICE_NAME); + CachedBluetoothDevice cachedBluetoothDevice = + new CachedBluetoothDevice(mContext, mAdapter, mProfileManager, mDevice); + // Verify alias is returned on getName + assertThat(cachedBluetoothDevice.getName()).isEqualTo(DEVICE_ALIAS); + // Verify null name does not get set + cachedBluetoothDevice.setName(null); + verify(mDevice, never()).setAlias(any()); + // Verify new name is set properly + cachedBluetoothDevice.setName(DEVICE_ALIAS_NEW); + verify(mDevice).setAlias(DEVICE_ALIAS_NEW); + // Verify new alias is returned on getName + assertThat(cachedBluetoothDevice.getName()).isEqualTo(DEVICE_ALIAS_NEW); + } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawableTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawableTest.java new file mode 100644 index 000000000000..f6fe158691fa --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawableTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.graph; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.VectorDrawable; + +import com.android.settingslib.R; +import com.android.settingslib.SettingsLibRobolectricTestRunner; +import com.android.settingslib.TestConfig; +import com.android.settingslib.testutils.shadow.SettingsLibShadowResources; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(SettingsLibRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, + shadows = SettingsLibShadowResources.class) +public class BluetoothDeviceLayerDrawableTest { + private static final int RES_ID = R.drawable.ic_bt_cellphone; + private static final int BATTERY_LEVEL = 15; + private static final float TOLERANCE = 0.001f; + + private Context mContext; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + } + + @Test + public void testCreateLayerDrawable_configCorrect() { + BluetoothDeviceLayerDrawable drawable = BluetoothDeviceLayerDrawable.createLayerDrawable( + mContext, RES_ID, BATTERY_LEVEL); + + assertThat(drawable.getDrawable(0)).isInstanceOf(VectorDrawable.class); + assertThat(drawable.getDrawable(1)).isInstanceOf(BitmapDrawable.class); + assertThat(drawable.getLayerInsetTop(1)).isEqualTo( + drawable.getDrawable(0).getIntrinsicHeight()); + } + + @Test + public void testBatteryMeterDrawable_configCorrect() { + BluetoothDeviceLayerDrawable.BatteryMeterDrawable batteryDrawable = + new BluetoothDeviceLayerDrawable.BatteryMeterDrawable(mContext, + R.color.meter_background_color, BATTERY_LEVEL); + + assertThat(batteryDrawable.getAspectRatio()).isWithin(TOLERANCE).of(0.45f); + assertThat(batteryDrawable.getRadiusRatio()).isWithin(TOLERANCE).of(0f); + assertThat(batteryDrawable.getBatteryLevel()).isEqualTo(BATTERY_LEVEL); + } + + @Test + public void testConstantState_returnTwinBluetoothLayerDrawable() { + BluetoothDeviceLayerDrawable drawable = BluetoothDeviceLayerDrawable.createLayerDrawable( + mContext, RES_ID, BATTERY_LEVEL); + + BluetoothDeviceLayerDrawable twinDrawable = + (BluetoothDeviceLayerDrawable) drawable.getConstantState().newDrawable(); + + assertThat(twinDrawable.getDrawable(0)).isEqualTo(drawable.getDrawable(0)); + assertThat(twinDrawable.getDrawable(1)).isEqualTo(drawable.getDrawable(1)); + assertThat(twinDrawable.getLayerInsetTop(1)).isEqualTo( + drawable.getLayerInsetTop(1)); + } +} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java index cbc07b889df0..f31d2e1afcd8 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java @@ -166,12 +166,6 @@ public class SuggestionParserTest { final List<Tile> suggestions = sl.getSuggestions(); assertThat(suggestions).hasSize(3); - - final List<Tile> category1Suggestions = sl.getSuggestionForCategory("category1"); - final List<Tile> category3Suggestions = sl.getSuggestionForCategory("category3"); - - assertThat(category1Suggestions).hasSize(2); - assertThat(category3Suggestions).hasSize(1); } @Test @@ -181,7 +175,6 @@ public class SuggestionParserTest { final List<Tile> suggestions = sl.getSuggestions(); assertThat(suggestions).hasSize(1); - assertThat(sl.getSuggestionForCategory("category2")).hasSize(1); } @Test diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/SettingsLibShadowResources.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/SettingsLibShadowResources.java new file mode 100644 index 000000000000..a376dcdbbbd3 --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/SettingsLibShadowResources.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.testutils.shadow; + +import static org.robolectric.internal.Shadow.directlyOn; + +import android.content.res.Resources; +import android.content.res.Resources.NotFoundException; +import android.support.annotation.ArrayRes; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.annotation.RealObject; +import org.robolectric.shadows.ShadowResources; + +/** + * Shadow Resources to handle resource references that Robolectric shadows cannot + * handle because they are too new or private. + */ +@Implements(Resources.class) +public class SettingsLibShadowResources extends ShadowResources { + + @RealObject + public Resources realResources; + + @Implementation + public int[] getIntArray(@ArrayRes int id) throws NotFoundException { + // The Robolectric has resource mismatch for these values, so we need to stub it here + if (id == com.android.settingslib.R.array.batterymeter_bolt_points + || id == com.android.settingslib.R.array.batterymeter_plus_points) { + return new int[2]; + } + return directlyOn(realResources, Resources.class).getIntArray(id); + } +} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java index 08757b28a686..7f89fd5d079c 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java @@ -16,16 +16,23 @@ package com.android.settingslib.wifi; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; +import static org.mockito.Mockito.verify; import android.content.Context; +import android.graphics.drawable.ColorDrawable; import com.android.settingslib.SettingsLibRobolectricTestRunner; import com.android.settingslib.TestConfig; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; @@ -35,6 +42,22 @@ public class AccessPointPreferenceTest { private Context mContext = RuntimeEnvironment.application; + @Mock private AccessPoint mockAccessPoint; + @Mock private AccessPointPreference.UserBadgeCache mockUserBadgeCache; + @Mock private AccessPointPreference.IconInjector mockIconInjector; + + private AccessPointPreference createWithAccessPoint(AccessPoint accessPoint) { + return new AccessPointPreference(accessPoint, mContext, mockUserBadgeCache, + 0, true, null, -1, mockIconInjector); + } + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + when(mockIconInjector.getIcon(anyInt())).thenReturn(new ColorDrawable()); + } + @Test public void generatePreferenceKey_shouldReturnSsidPlusSecurity() { String ssid = "ssid"; @@ -78,4 +101,16 @@ public class AccessPointPreferenceTest { RuntimeEnvironment.application, pref, ap)) .isEqualTo("ssid,connected,Wifi signal full.,Secure network"); } + + @Test + public void refresh_shouldUpdateIcon() { + int level = 1; + when(mockAccessPoint.getSpeed()).thenReturn(0); + when(mockAccessPoint.getLevel()).thenReturn(level); + + AccessPointPreference pref = createWithAccessPoint(mockAccessPoint); + pref.refresh(); + + verify(mockIconInjector).getIcon(level); + } } diff --git a/packages/SettingsProvider/res/values-en-rCA/defaults.xml b/packages/SettingsProvider/res/values-en-rCA/defaults.xml new file mode 100644 index 000000000000..4a87a1250404 --- /dev/null +++ b/packages/SettingsProvider/res/values-en-rCA/defaults.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright (c) 2009, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> + <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> + <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> +</resources> diff --git a/packages/SettingsProvider/res/values-en-rCA/strings.xml b/packages/SettingsProvider/res/values-en-rCA/strings.xml new file mode 100644 index 000000000000..c19fdd7aed7f --- /dev/null +++ b/packages/SettingsProvider/res/values-en-rCA/strings.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright (c) 2007, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="app_label" msgid="4567566098528588863">"Settings Storage"</string> +</resources> diff --git a/packages/SettingsProvider/res/values-en-rXC/defaults.xml b/packages/SettingsProvider/res/values-en-rXC/defaults.xml new file mode 100644 index 000000000000..b32199f372dc --- /dev/null +++ b/packages/SettingsProvider/res/values-en-rXC/defaults.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright (c) 2009, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string> + <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string> + <string name="def_nfc_payment_component" msgid="5861297439873026958"></string> +</resources> diff --git a/packages/SettingsProvider/res/values-en-rXC/strings.xml b/packages/SettingsProvider/res/values-en-rXC/strings.xml new file mode 100644 index 000000000000..e7abd48d9571 --- /dev/null +++ b/packages/SettingsProvider/res/values-en-rXC/strings.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright (c) 2007, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="app_label" msgid="4567566098528588863">"Settings Storage"</string> +</resources> diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 53ffe9503f4d..7d7f9ae7f19e 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -2896,7 +2896,7 @@ public class SettingsProvider extends ContentProvider { } private final class UpgradeController { - private static final int SETTINGS_VERSION = 147; + private static final int SETTINGS_VERSION = 148; private final int mUserId; @@ -3345,22 +3345,11 @@ public class SettingsProvider extends ContentProvider { } if (currentVersion == 141) { - // Version 142: We added the notion of a default and whether the system set - // the setting. This is used for resetting the internal state and we need - // to make sure this value is updated for the existing settings, otherwise - // we would delete system set settings while they should stay unmodified. - SettingsState globalSettings = getGlobalSettingsLocked(); - ensureLegacyDefaultValueAndSystemSetUpdatedLocked(globalSettings); - globalSettings.persistSyncLocked(); - - SettingsState secureSettings = getSecureSettingsLocked(mUserId); - ensureLegacyDefaultValueAndSystemSetUpdatedLocked(secureSettings); - secureSettings.persistSyncLocked(); - - SettingsState systemSettings = getSystemSettingsLocked(mUserId); - ensureLegacyDefaultValueAndSystemSetUpdatedLocked(systemSettings); - systemSettings.persistSyncLocked(); - + // This implementation was incorrectly setting the current value of + // settings changed by non-system packages as the default which default + // is set by the system. We add a new upgrade step at the end to properly + // handle this case which would also fix incorrect changes made by the + // old implementation of this step. currentVersion = 142; } @@ -3407,24 +3396,51 @@ public class SettingsProvider extends ContentProvider { } if (currentVersion == 145) { - // Version 146: Set the default value for WIFI_WAKEUP_AVAILABLE. + // Version 146: In step 142 we had a bug where incorrectly + // some settings were considered system set and as a result + // made the default and marked as the default being set by + // the system. Here reevaluate the default and default system + // set flags. This would both fix corruption by the old impl + // of step 142 and also properly handle devices which never + // run 142. + if (userId == UserHandle.USER_SYSTEM) { + SettingsState globalSettings = getGlobalSettingsLocked(); + ensureLegacyDefaultValueAndSystemSetUpdatedLocked(globalSettings, userId); + globalSettings.persistSyncLocked(); + } + + SettingsState secureSettings = getSecureSettingsLocked(mUserId); + ensureLegacyDefaultValueAndSystemSetUpdatedLocked(secureSettings, userId); + secureSettings.persistSyncLocked(); + + SettingsState systemSettings = getSystemSettingsLocked(mUserId); + ensureLegacyDefaultValueAndSystemSetUpdatedLocked(systemSettings, userId); + systemSettings.persistSyncLocked(); + + currentVersion = 146; + } + + if (currentVersion == 146) { + // Version 147: Set the default value for WIFI_WAKEUP_AVAILABLE. if (userId == UserHandle.USER_SYSTEM) { final SettingsState globalSettings = getGlobalSettingsLocked(); final Setting currentSetting = globalSettings.getSettingLocked( Settings.Global.WIFI_WAKEUP_AVAILABLE); - final int defaultValue = getContext().getResources().getInteger( - com.android.internal.R.integer.config_wifi_wakeup_available); - globalSettings.insertSettingLocked( - Settings.Global.WIFI_WAKEUP_AVAILABLE, - String.valueOf(defaultValue), - null, true, SettingsState.SYSTEM_PACKAGE_NAME); + if (currentSetting.getValue() == null) { + final int defaultValue = getContext().getResources().getInteger( + com.android.internal.R.integer.config_wifi_wakeup_available); + globalSettings.insertSettingLocked( + Settings.Global.WIFI_WAKEUP_AVAILABLE, + String.valueOf(defaultValue), + null, true, SettingsState.SYSTEM_PACKAGE_NAME); + } } - currentVersion = 146; + currentVersion = 147; } - if (currentVersion == 146) { - // Version 146: Set the default value for DEFAULT_RESTRICT_BACKGROUND_DATA. + if (currentVersion == 147) { + // Version 148: Set the default value for DEFAULT_RESTRICT_BACKGROUND_DATA. if (userId == UserHandle.USER_SYSTEM) { final SettingsState globalSettings = getGlobalSettingsLocked(); final Setting currentSetting = globalSettings.getSettingLocked( @@ -3437,7 +3453,7 @@ public class SettingsProvider extends ContentProvider { null, true, SettingsState.SYSTEM_PACKAGE_NAME); } } - currentVersion = 147; + currentVersion = 148; } // vXXX: Add new settings above this point. @@ -3458,19 +3474,46 @@ public class SettingsProvider extends ContentProvider { } } - private void ensureLegacyDefaultValueAndSystemSetUpdatedLocked(SettingsState settings) { + private void ensureLegacyDefaultValueAndSystemSetUpdatedLocked(SettingsState settings, + int userId) { List<String> names = settings.getSettingNamesLocked(); final int nameCount = names.size(); for (int i = 0; i < nameCount; i++) { String name = names.get(i); Setting setting = settings.getSettingLocked(name); - if (setting.getDefaultValue() == null) { - boolean systemSet = SettingsState.isSystemPackage(getContext(), - setting.getPackageName()); + + // In the upgrade case we pretend the call is made from the app + // that made the last change to the setting to properly determine + // whether the call has been made by a system component. + int callingUid = -1; + try { + callingUid = mPackageManager.getPackageUid(setting.getPackageName(), 0, userId); + } catch (RemoteException e) { + /* ignore - handled below */ + } + if (callingUid < 0) { + Slog.e(LOG_TAG, "Unknown package: " + setting.getPackageName()); + continue; + } + try { + final boolean systemSet = SettingsState.isSystemPackage(getContext(), + setting.getPackageName(), callingUid); if (systemSet) { settings.insertSettingLocked(name, setting.getValue(), setting.getTag(), true, setting.getPackageName()); + } else if (setting.getDefaultValue() != null && setting.isDefaultFromSystem()) { + // We had a bug where changes by non-system packages were marked + // as system made and as a result set as the default. Therefore, if + // the package changed the setting last is not a system one but the + // setting is marked as its default coming from the system we clear + // the default and clear the system set flag. + settings.resetSettingDefaultValueLocked(name); } + } catch (IllegalStateException e) { + // If the package goes over its quota during the upgrade, don't + // crash but just log the error as the system does the upgrade. + Slog.e(LOG_TAG, "Error upgrading setting: " + setting.getName(), e); + } } } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java index d3ac11a7942e..4151ada9ce80 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java @@ -298,6 +298,22 @@ final class SettingsState { } // The settings provider must hold its lock when calling here. + public void resetSettingDefaultValueLocked(String name) { + Setting oldSetting = getSettingLocked(name); + if (oldSetting != null && !oldSetting.isNull() && oldSetting.getDefaultValue() != null) { + String oldValue = oldSetting.getValue(); + String oldDefaultValue = oldSetting.getDefaultValue(); + Setting newSetting = new Setting(name, oldSetting.getValue(), null, + oldSetting.getPackageName(), oldSetting.getTag(), false, + oldSetting.getId()); + mSettings.put(name, newSetting); + updateMemoryUsagePerPackageLocked(newSetting.getPackageName(), oldValue, + newSetting.getValue(), oldDefaultValue, newSetting.getDefaultValue()); + scheduleWriteIfNeededLocked(); + } + } + + // The settings provider must hold its lock when calling here. public boolean insertSettingLocked(String name, String value, String tag, boolean makeDefault, String packageName) { if (TextUtils.isEmpty(name)) { @@ -1007,6 +1023,10 @@ final class SettingsState { } public static boolean isSystemPackage(Context context, String packageName) { + return isSystemPackage(context, packageName, Binder.getCallingUid()); + } + + public static boolean isSystemPackage(Context context, String packageName, int callingUid) { synchronized (sLock) { if (SYSTEM_PACKAGE_NAME.equals(packageName)) { return true; @@ -1019,7 +1039,7 @@ final class SettingsState { } // Native services running as a special UID get a pass - final int callingAppId = UserHandle.getAppId(Binder.getCallingUid()); + final int callingAppId = UserHandle.getAppId(callingUid); if (callingAppId < FIRST_APPLICATION_UID) { sSystemUids.put(callingAppId, callingAppId); return true; @@ -1030,7 +1050,7 @@ final class SettingsState { // profile for the purpose of determining whether the other end is a // system component we need to use the user id of the caller for // pulling information about the caller from the package manager. - final int callingUserId = UserHandle.getCallingUserId(); + final int callingUserId = UserHandle.getUserId(callingUid); final long identity = Binder.clearCallingIdentity(); try { diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 244677508894..bd1ebb9a6323 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -118,6 +118,8 @@ <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" /> <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" /> <uses-permission android:name="android.permission.MANAGE_AUTO_FILL" /> + <uses-permission android:name="android.permission.NETWORK_SETTINGS" /> + <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <!-- Permission needed to rename bugreport notifications (so they're not shown as Shell) --> <uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" /> <!-- Permission needed to hold a wakelock in dumpstate.cpp (drop_root_user()) --> diff --git a/packages/Shell/res/values-hi/strings.xml b/packages/Shell/res/values-hi/strings.xml index 6992240e33f9..c82284c68c6f 100644 --- a/packages/Shell/res/values-hi/strings.xml +++ b/packages/Shell/res/values-hi/strings.xml @@ -17,31 +17,31 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="3701846017049540910">"शेल"</string> - <string name="bugreport_notification_channel" msgid="2574150205913861141">"बग रिपोर्ट"</string> - <string name="bugreport_in_progress_title" msgid="4311705936714972757">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g> जेनरेट की जा रही है"</string> - <string name="bugreport_finished_title" msgid="4429132808670114081">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g> कैप्चर की गई"</string> - <string name="bugreport_updating_title" msgid="4423539949559634214">"बग रिपोर्ट में विवरण जोड़े जा रहे हैं"</string> + <string name="bugreport_notification_channel" msgid="2574150205913861141">"गड़बड़ी की रिपोर्ट"</string> + <string name="bugreport_in_progress_title" msgid="4311705936714972757">"गड़बड़ी की रिपोर्ट <xliff:g id="ID">#%d</xliff:g> तैयार की जा रही है"</string> + <string name="bugreport_finished_title" msgid="4429132808670114081">"गड़बड़ी की रिपोर्ट <xliff:g id="ID">#%d</xliff:g> कैप्चर की गई"</string> + <string name="bugreport_updating_title" msgid="4423539949559634214">"गड़बड़ी की रिपोर्ट में पूरी जानकारी जोड़ी जा रही है"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"कृपया प्रतीक्षा करें…"</string> - <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"बग रिपोर्ट थोड़ी ही देर में फ़ोन पर दिखाई देगी"</string> - <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"अपनी बग रिपोर्ट साझा करना चुनें"</string> - <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"अपनी बग रिपोर्ट शेयर करने के लिए टैप करें"</string> - <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"किसी स्क्रीनशॉट के बिना अपनी बग रिपोर्ट साझा करना चुनें या स्क्रीनशॉट पूरा होने तक इंतज़ार करें"</string> - <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"अपनी बग रिपोर्ट को बिना स्क्रीनशॉट साझा करने हेतु टैप करें या स्क्रीनशॉट पूरा होने की प्रतीक्षा करें"</string> - <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"अपनी बग रिपोर्ट को बिना स्क्रीनशॉट साझा करने हेतु टैप करें या स्क्रीनशॉट पूरा होने की प्रतीक्षा करें"</string> - <string name="bugreport_confirm" msgid="5917407234515812495">"बग रिपोर्ट में सिस्टम की विभिन्न लॉग फ़ाइलों का डेटा शामिल होता है, जिसमें ऐसा डेटा शामिल हो सकता है जिसे आप संवेदनशील मानते हैं (जैसे कि ऐप्लिकेशन का उपयोग और स्थान डेटा). बग रिपोर्ट केवल अपने विश्वसनीय लोगों और ऐप्लिकेशन से साझा करें."</string> + <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"गड़बड़ी की रिपोर्ट थोड़ी ही देर में फ़ोन पर दिखाई देगी"</string> + <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"अपनी गड़बड़ी की रिपोर्ट शेयर करने के लिए टैप करें"</string> + <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"अपनी गड़बड़ी की रिपोर्ट शेयर करने के लिए टैप करें"</string> + <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"स्क्रीनशॉट के बिना अपनी गड़बड़ी की रिपोर्ट शेयर करना चुनें या स्क्रीनशॉट पूरा होने तक इंतज़ार करें"</string> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"अपनी गड़बड़ी की रिपोर्ट को बिना स्क्रीनशॉट के शेयर करने के लिए टैप करें या स्क्रीनशॉट पूरा होने की इंतज़ार करें"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"अपनी गड़बड़ी की रिपोर्ट को बिना स्क्रीनशॉट के शेयर करने के लिए टैप करें या स्क्रीनशॉट पूरा होने की इंतज़ार करें"</string> + <string name="bugreport_confirm" msgid="5917407234515812495">"गड़बड़ी की रिपोर्ट में सिस्टम की अलग-अलग लॉग फ़ाइलों का डेटा शामिल होता है, जिसमें ऐसा डेटा शामिल हो सकता है जिसे आप संवेदनशील मानते हैं (जैसे कि ऐप्लिकेशन का उपयोग और स्थान डेटा). गड़बड़ी की रिपोर्ट केवल अपने भरोसेमंद लोगों और ऐप्लिकेशन से साझा करें."</string> <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"फिर से ना दिखाएं"</string> - <string name="bugreport_storage_title" msgid="5332488144740527109">"बग रिपोर्ट"</string> - <string name="bugreport_unreadable_text" msgid="586517851044535486">"बग रिपोर्ट फ़ाइल नहीं पढ़ी जा सकी"</string> - <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"बग रिपोर्ट को ज़िप फ़ाइल में नहीं जोड़ा जा सका"</string> + <string name="bugreport_storage_title" msgid="5332488144740527109">"गड़बड़ी की रिपोर्ट"</string> + <string name="bugreport_unreadable_text" msgid="586517851044535486">"गड़बड़ी की रिपोर्ट फ़ाइल नहीं पढ़ी जा सकी"</string> + <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"गड़बड़ी की रिपोर्ट को ज़िप फ़ाइल में नहीं जोड़ा जा सका"</string> <string name="bugreport_unnamed" msgid="2800582406842092709">"अनामांकित"</string> <string name="bugreport_info_action" msgid="2158204228510576227">"विवरण"</string> <string name="bugreport_screenshot_action" msgid="8677781721940614995">"स्क्रीनशॉट"</string> <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"स्क्रीनशॉट सफलतापूर्वक लिया गया."</string> <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"स्क्रीनशॉट नहीं लिया जा सका."</string> - <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g> के विवरण"</string> + <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"गड़बड़ी की रिपोर्ट <xliff:g id="ID">#%d</xliff:g> की पूरी जानकारी"</string> <string name="bugreport_info_name" msgid="4414036021935139527">"फ़ाइल नाम"</string> - <string name="bugreport_info_title" msgid="2306030793918239804">"बग शीर्षक"</string> - <string name="bugreport_info_description" msgid="5072835127481627722">"बग सारांश"</string> + <string name="bugreport_info_title" msgid="2306030793918239804">"गड़बड़ी का शीर्षक"</string> + <string name="bugreport_info_description" msgid="5072835127481627722">"गड़बड़ी का सारांश"</string> <string name="save" msgid="4781509040564835759">"सहेजें"</string> - <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"बग रिपोर्ट साझा करें"</string> + <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"गड़बड़ी की रिपोर्ट शेयर करें"</string> </resources> diff --git a/packages/Shell/res/values-mr/strings.xml b/packages/Shell/res/values-mr/strings.xml index 7e6643607c37..7cab9d7b6307 100644 --- a/packages/Shell/res/values-mr/strings.xml +++ b/packages/Shell/res/values-mr/strings.xml @@ -17,31 +17,31 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="3701846017049540910">"शेल"</string> - <string name="bugreport_notification_channel" msgid="2574150205913861141">"दोष अहवाल"</string> - <string name="bugreport_in_progress_title" msgid="4311705936714972757">"दोष अहवाल <xliff:g id="ID">#%d</xliff:g> तयार केला जात आहे"</string> - <string name="bugreport_finished_title" msgid="4429132808670114081">"दोष अहवाल <xliff:g id="ID">#%d</xliff:g> कॅप्चर केला"</string> + <string name="bugreport_notification_channel" msgid="2574150205913861141">"बग रीपोर्ट"</string> + <string name="bugreport_in_progress_title" msgid="4311705936714972757">"बग रीपोर्ट <xliff:g id="ID">#%d</xliff:g> तयार केला जात आहे"</string> + <string name="bugreport_finished_title" msgid="4429132808670114081">"बग रीपोर्ट <xliff:g id="ID">#%d</xliff:g> कॅप्चर केला"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"दोष अहवालामध्ये तपशील जोडत आहे"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"कृपया प्रतीक्षा करा..."</string> - <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"फोनवर दोष अहवाल लवकरच दिसेल"</string> - <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"आपला दोष अहवाल शेअर करण्यासाठी निवडा"</string> - <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"आपला दोष अहवाल सामायिक करण्यासाठी टॅप करा"</string> - <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"आपला दोष अहवाल स्क्रीनशॉटशिवाय शेअर करण्यासाठी टॅप करा किंवा स्क्रीनशॉट पूर्ण होण्याची प्रतीक्षा करा"</string> - <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"स्क्रीनशॉट शिवाय आपला दोष अहवाल सामायिक करण्यासाठी टॅप करा किंवा समाप्त करण्यासाठी स्क्रीनशॉटची प्रतीक्षा करा"</string> - <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"स्क्रीनशॉट शिवाय आपला दोष अहवाल सामायिक करण्यासाठी टॅप करा किंवा समाप्त करण्यासाठी स्क्रीनशॉटची प्रतीक्षा करा"</string> - <string name="bugreport_confirm" msgid="5917407234515812495">"दोष अहवालांमध्ये आपण संवेदनशील (अॅप-वापर आणि स्थान डेटा यासारखा) डेटा म्हणून विचार करता त्या डेटाच्या समावेशासह सिस्टीमच्या विविध लॉग फायलींमधील डेटा असतो. ज्या लोकांवर आणि अॅपवर आपला विश्वास आहे केवळ त्यांच्यासह हा दोष अहवाल सामायिक करा."</string> + <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"फोनवर बग रीपोर्ट लवकरच दिसेल"</string> + <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"आपला बग रीपोर्ट शेअर करण्यासाठी निवडा"</string> + <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"आपला बग रीपोर्ट शेअर करण्यासाठी टॅप करा"</string> + <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"आपला बग रीपोर्ट स्क्रीनशॉटशिवाय शेअर करण्यासाठी टॅप करा किंवा स्क्रीनशॉट पूर्ण होण्याची प्रतीक्षा करा"</string> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"स्क्रीनशॉट शिवाय आपला बग रीपोर्ट शेअर करण्यासाठी टॅप करा किंवा समाप्त करण्यासाठी स्क्रीनशॉटची प्रतीक्षा करा"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"स्क्रीनशॉट शिवाय आपला बग रीपोर्ट शेअर करण्यासाठी टॅप करा किंवा समाप्त करण्यासाठी स्क्रीनशॉटची प्रतीक्षा करा"</string> + <string name="bugreport_confirm" msgid="5917407234515812495">"बग रीपोर्टांमध्ये आपण संवेदनशील (अॅप-वापर आणि स्थान डेटा यासारखा) डेटा म्हणून विचार करता त्या डेटाच्या समावेशासह सिस्टीमच्या विविध लॉग फायलींमधील डेटा असतो. ज्या लोकांवर आणि अॅपवर आपला विश्वास आहे केवळ त्यांच्यासह हा बग रीपोर्ट शेअर करा."</string> <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"पुन्हा दर्शवू नका"</string> - <string name="bugreport_storage_title" msgid="5332488144740527109">"दोष अहवाल"</string> - <string name="bugreport_unreadable_text" msgid="586517851044535486">"दोष अहवाल फाईल वाचणे शक्य झाले नाही"</string> - <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"झिप फाईल मध्ये दोष अहवाल तपशील जोडणे शक्य झाले नाही"</string> + <string name="bugreport_storage_title" msgid="5332488144740527109">"बग रीपोर्ट"</string> + <string name="bugreport_unreadable_text" msgid="586517851044535486">"बग रीपोर्ट फाईल वाचणे शक्य झाले नाही"</string> + <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"झिप फाईल मध्ये बग रीपोर्ट तपशील जोडणे शक्य झाले नाही"</string> <string name="bugreport_unnamed" msgid="2800582406842092709">"अनामित"</string> <string name="bugreport_info_action" msgid="2158204228510576227">"तपशील"</string> <string name="bugreport_screenshot_action" msgid="8677781721940614995">"स्क्रीनशॉट"</string> <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"स्क्रीनशॉट यशस्वीरित्या घेतला."</string> <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"स्क्रीनशॉट घेणे शक्य झाले नाही."</string> - <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"दोष अहवाल <xliff:g id="ID">#%d</xliff:g> तपशील"</string> + <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"बग रीपोर्ट <xliff:g id="ID">#%d</xliff:g> तपशील"</string> <string name="bugreport_info_name" msgid="4414036021935139527">"फाईलनाव"</string> <string name="bugreport_info_title" msgid="2306030793918239804">"दोष शीर्षक"</string> <string name="bugreport_info_description" msgid="5072835127481627722">"दोष सारांश"</string> - <string name="save" msgid="4781509040564835759">"जतन करा"</string> - <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"दोष अहवाल सामायिक करा"</string> + <string name="save" msgid="4781509040564835759">"सेव्ह करा"</string> + <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"बग रीपोर्ट शेअर करा"</string> </resources> diff --git a/packages/Shell/res/values-te/strings.xml b/packages/Shell/res/values-te/strings.xml index 8db9b889dea7..bed7367cbaec 100644 --- a/packages/Shell/res/values-te/strings.xml +++ b/packages/Shell/res/values-te/strings.xml @@ -28,7 +28,7 @@ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"స్క్రీన్షాట్ లేకుండా మీ బగ్ నివేదికను భాగస్వామ్యం చేయడానికి ఎంచుకోండి లేదా స్క్రీన్షాట్ ముగిసేదాకా వేచి ఉండండి"</string> <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"స్క్రీన్షాట్ లేకుండా మీ బగ్ నివే. భాగ. చేయడానికి నొక్కండి లేదా స్క్రీన్షాట్ ముగిసేదాకా వేచి ఉండండి"</string> <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"స్క్రీన్షాట్ లేకుండా మీ బగ్ నివే. భాగ. చేయడానికి నొక్కండి లేదా స్క్రీన్షాట్ ముగిసేదాకా వేచి ఉండండి"</string> - <string name="bugreport_confirm" msgid="5917407234515812495">"బగ్ నివేదికల్లో మీరు గోప్యమైనదిగా పరిగణించే (అనువర్తన వినియోగం మరియు స్థాన డేటా వంటి) డేటాతో సహా సిస్టమ్కు సంబంధించిన విభిన్న లాగ్ ఫైల్ల డేటా ఉంటుంది. బగ్ నివేదికలను మీరు విశ్వసించే అనువర్తనాలు మరియు వ్యక్తులతో మాత్రమే భాగస్వామ్యం చేయండి."</string> + <string name="bugreport_confirm" msgid="5917407234515812495">"బగ్ నివేదికల్లో మీరు గోప్యమైనదిగా పరిగణించే (యాప్ వినియోగం మరియు స్థాన డేటా వంటి) డేటాతో సహా సిస్టమ్కు సంబంధించిన విభిన్న లాగ్ ఫైల్ల డేటా ఉంటుంది. బగ్ నివేదికలను మీరు విశ్వసించే యాప్లు మరియు వ్యక్తులతో మాత్రమే షేర్ చేయండి."</string> <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"మళ్లీ చూపవద్దు"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"బగ్ నివేదికలు"</string> <string name="bugreport_unreadable_text" msgid="586517851044535486">"బగ్ నివేదిక ఫైల్ను చదవడం సాధ్యపడలేదు"</string> diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 71cb3ff9f0fe..75e919990f01 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -108,6 +108,7 @@ <uses-permission android:name="com.android.alarm.permission.SET_ALARM" /> <!-- Keyguard --> + <uses-permission android:name="com.android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" /> <uses-permission android:name="android.permission.CONTROL_KEYGUARD" /> <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginActivity.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginActivity.java deleted file mode 100644 index 925214e3ab3a..000000000000 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginActivity.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package com.android.systemui.plugins; - -import android.app.Activity; -import android.content.Context; -import android.content.res.Resources; -import android.os.Bundle; - -import com.android.systemui.plugins.annotations.ProvidesInterface; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * A PluginActivity is an activity that replaces another full activity (e.g. RecentsActivity) - * at runtime within the sysui process. - */ -@ProvidesInterface(version = PluginActivity.VERSION) -public abstract class PluginActivity extends Activity implements Plugin { - - public static final int VERSION = 1; - - public static final String ACTION_RECENTS = "com.android.systemui.action.PLUGIN_RECENTS"; - - private Context mSysuiContext; - private boolean mSettingActionBar; - - @Override - public final void onCreate(Context sysuiContext, Context pluginContext) { - mSysuiContext = sysuiContext; - super.attachBaseContext(pluginContext); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Theme theme = getClass().getDeclaredAnnotation(Theme.class); - if (theme != null && theme.value() != 0) { - setTheme(theme.value()); - } - mSettingActionBar = true; - getActionBar(); - mSettingActionBar = false; - } - - @Override - public Resources getResources() { - return mSettingActionBar ? mSysuiContext.getResources() : super.getResources(); - } - - @Override - protected void attachBaseContext(Context newBase) { - mSysuiContext = newBase; - } - - @Override - public void onDestroy() { - super.onDestroy(); - } - - public Context getSysuiContext() { - return mSysuiContext; - } - - public Context getPluginContext() { - return getBaseContext(); - } - - /** - * Since PluginActivities are declared as services instead of activities (since they - * are plugins), they can't have a theme attached to them. Instead a PluginActivity - * can annotate itself with @Theme to specify the resource of the style it wants - * to be themed with. - */ - @Retention(RetentionPolicy.RUNTIME) - public @interface Theme { - int value(); - } -} diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginDependency.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginDependency.java index db2e3765d2d0..25ce3ddf8169 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginDependency.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginDependency.java @@ -21,11 +21,6 @@ public class PluginDependency { public static final int VERSION = 1; static DependencyProvider sProvider; - /** - * Allows a plugin to get a hold of static dependencies if they have declared dependence - * on their interface. For one-shot plugins this will only work during onCreate and will - * not work afterwards. - */ public static <T> T get(Plugin p, Class<T> cls) { return sProvider.get(p, cls); } diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java index 5243228121c6..56a3ee3a28f7 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavBarButtonProvider.java @@ -46,7 +46,8 @@ public interface NavBarButtonProvider extends Plugin { void setVertical(boolean vertical); - void setCarMode(boolean carMode); + default void setCarMode(boolean carMode) { + } void setDarkIntensity(float intensity); } diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_esim_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_esim_area.xml index 8cbd94bd0cb4..db508c91e0de 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_esim_area.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_esim_area.xml @@ -25,8 +25,7 @@ android:id="@+id/keyguard_disable_esim" android:visibility="gone" android:text="@string/disable_carrier_button_text" - style="?android:attr/buttonBarButtonStyle" + style="@style/Keyguard.TextView" android:textAppearance="?android:attr/textAppearanceMedium" android:textSize="@dimen/kg_status_line_font_size" - android:textColor="?android:attr/textColorSecondary" android:textAllCaps="@bool/kg_use_all_caps" /> diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml index 7291cd44c8ac..29376ce01e4f 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml @@ -45,7 +45,9 @@ android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false" - android:paddingTop="@dimen/keyguard_security_view_margin" + android:paddingTop="@dimen/keyguard_security_view_top_margin" + android:paddingStart="@dimen/keyguard_security_view_lateral_margin" + android:paddingEnd="@dimen/keyguard_security_view_lateral_margin" android:gravity="center"> </com.android.keyguard.KeyguardSecurityViewFlipper> </com.android.keyguard.KeyguardSecurityContainer> diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml index e5c8d7108980..3d364e906724 100644 --- a/packages/SystemUI/res-keyguard/values-ca/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml @@ -71,7 +71,7 @@ <string name="kg_sim_unlock_progress_dialog_message" msgid="4471738151810900114">"S\'està desbloquejant la targeta SIM…"</string> <string name="kg_invalid_sim_pin_hint" msgid="3057533256729513335">"Escriu un PIN que tingui entre 4 i 8 números."</string> <string name="kg_invalid_sim_puk_hint" msgid="6003602401368264144">"El codi PUK ha de tenir 8 números o més."</string> - <string name="kg_invalid_puk" msgid="5399287873762592502">"Torna a introduir el codi PUK correcte. Si ho intentes diverses vegades, es desactivarà la SIM de manera permanent."</string> + <string name="kg_invalid_puk" msgid="5399287873762592502">"Torna a introduir el codi PUK correcte. Si ho intentes diverses vegades, es desactivarà la SIM permanentment."</string> <string name="kg_invalid_confirm_pin_hint" product="default" msgid="5672736555427444330">"Els codis PIN no coincideixen"</string> <string name="kg_login_too_many_attempts" msgid="6604574268387867255">"Has intentat dibuixar el patró massa vegades"</string> <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8637788033282252027">"Has escrit el PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string> diff --git a/packages/SystemUI/res-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml index 348af67bf64e..4f37570e3472 100644 --- a/packages/SystemUI/res-keyguard/values-gl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml @@ -105,7 +105,7 @@ <string name="kg_password_puk_failed" msgid="1331621440873439974">"Produciuse un erro ao tentar desbloquear a tarxeta SIM co código PUK."</string> <string name="kg_pin_accepted" msgid="7637293533973802143">"Código válido"</string> <string name="keyguard_carrier_default" msgid="4274828292998453695">"Non hai servizo."</string> - <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"Cambia o método de entrada"</string> + <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"Cambia o método de introdución"</string> <string name="airplane_mode" msgid="3807209033737676010">"Modo avión"</string> <string name="kg_prompt_reason_restart_pattern" msgid="7246972020562621506">"É necesario o padrón despois do reinicio do dispositivo"</string> <string name="kg_prompt_reason_restart_pin" msgid="6303592361322290145">"É necesario o PIN despois do reinicio do dispositivo"</string> diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml index 97d628bdd6ff..5e9bf3c9e1ae 100644 --- a/packages/SystemUI/res-keyguard/values-hi/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml @@ -34,7 +34,7 @@ <string name="keyguard_plugged_in_charging_fast" msgid="8869226755413795173">"तेज़ी से चार्ज हो रही है"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="6637043106038550407">"धीरे चार्ज हो रही है"</string> <string name="keyguard_low_battery" msgid="9218432555787624490">"अपना चार्जर कनेक्ट करें."</string> - <string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"अनलॉक करने के लिए मेनू दबाएं."</string> + <string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"लॉक खोलने के लिए मेन्यू दबाएं."</string> <string name="keyguard_network_locked_message" msgid="6743537524631420759">"नेटवर्क लॉक किया हुआ है"</string> <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"कोई SIM कार्ड नहीं है"</string> <string name="keyguard_missing_sim_message" product="tablet" msgid="4550152848200783542">"टैबलेट में कोई SIM कार्ड नहीं है."</string> @@ -64,8 +64,8 @@ <string name="kg_sim_lock_instructions_esim" msgid="4957650659201013804">"मोबाइल सेवा के बिना डिवाइस का उपयोग करने के लिए eSIM अक्षम करें."</string> <string name="kg_pin_instructions" msgid="4069609316644030034">"पिन डालें"</string> <string name="kg_password_instructions" msgid="136952397352976538">"पासवर्ड डालें"</string> - <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"SIM अब काम नहीं करेगा. जारी रखने के लिए PUK कोड डालें. ज़्यादा जानकारी के लिए अपनी मोबाइल और इंटरनेट सेवा देने वाली कंपनी से संपर्क करें."</string> - <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" का SIM अब काम नहीं करेगा. जारी रखने के लिए PUK कोड डालें. ज़्यादा जानकारी के लिए अपनी मोबाइल और इंटरनेट सेवा देने वाली कंपनी से संपर्क करें."</string> + <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"सिम अब काम नहीं करेगा. जारी रखने के लिए PUK कोड डालें. ज़्यादा जानकारी के लिए अपनी मोबाइल और इंटरनेट सेवा देने वाली कंपनी से संपर्क करें."</string> + <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" का सिम अब काम नहीं करेगा. जारी रखने के लिए PUK कोड डालें. ज़्यादा जानकारी के लिए अपनी मोबाइल और इंटरनेट सेवा देने वाली कंपनी से संपर्क करें."</string> <string name="kg_puk_enter_pin_hint" msgid="3137789674920391087">"मनचाहा पिन कोड डालें"</string> <string name="kg_enter_confirm_pin_hint" msgid="3089485999116759671">"मनचाहे पिन कोड की पुष्टि करें"</string> <string name="kg_sim_unlock_progress_dialog_message" msgid="4471738151810900114">"SIM कार्ड अनलॉक हो रहा है…"</string> @@ -81,10 +81,10 @@ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="3921998703529189931">"आपने फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश की है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल कोशिशों के बाद, इस फ़ोन को रीसेट कर दिया जाएगा, जिससे इसका सारा डेटा हट जाएगा."</string> <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="4694232971224663735">"आपने टैबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से कोशिश की है. इस टैबलेट को रीसेट कर दिया जाएगा, जिससे इसका सारा डेटा हट जाएगा."</string> <string name="kg_failed_attempts_now_wiping" product="default" msgid="2365964340830006961">"आपने फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से कोशिश की है. इस फ़ोन को रीसेट कर दिया जाएगा, जिससे इसका सारा डेटा हट जाएगा."</string> - <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="1365418870560228936">"आपने टैबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश की है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल कोशिशों के बाद, इस उपयोगकर्ता को निकाल दिया जाएगा, जिससे सभी उपयोगकर्ता डेटा हट जाएगा."</string> - <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="2151286957817486128">"आपने फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश की है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल कोशिशों के बाद, इस उपयोगकर्ता को निकाल दिया जाएगा, जिससे सभी उपयोगकर्ता डेटा हट जाएगा."</string> - <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="5464020754932560928">"आपने टैबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से कोशिश की है. इस उपयोगकर्ता को निकाल दिया जाएगा, जिससे सभी उपयोगकर्ता डेटा हट जाएगा."</string> - <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="6171564974118059">"आपने फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से कोशिश की है. इस उपयोगकर्ता को निकाल दिया जाएगा, जिससे सभी उपयोगकर्ता डेटा हट जाएगा."</string> + <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="1365418870560228936">"आपने टैबलेट का लॉक खोलने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश की है. <xliff:g id="NUMBER_1">%2$d</xliff:g> बार और गलत कोशिश करने पर, इस उपयोगकर्ता को निकाल दिया जाएगा, जिससे सभी उपयोगकर्ता डेटा मिट जाएगा."</string> + <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="2151286957817486128">"आपने फ़ोन का लॉक खोलने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश की है. <xliff:g id="NUMBER_1">%2$d</xliff:g> बार और गलत कोशिश करने पर, इस उपयोगकर्ता को निकाल दिया जाएगा, जिससे सभी उपयोगकर्ता डेटा मिट जाएगा."</string> + <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="5464020754932560928">"आपने टैबलेट का लॉक खोलने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से कोशिश की है. इस उपयोगकर्ता को निकाल दिया जाएगा, जिससे सभी उपयोगकर्ता डेटा हट जाएगा."</string> + <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="6171564974118059">"आपने फ़ोन का लॉक खोलने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से कोशिश की है. इस उपयोगकर्ता को निकाल दिया जाएगा, जिससे सभी उपयोगकर्ता डेटा हट जाएगा."</string> <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="9154513795928824239">"आपने टैबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश की है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल कोशिशों के बाद, कार्य प्रोफ़ाइल को निकाल दिया जाएगा, जिससे सभी प्रोफ़ाइल डेटा हट जाएगा."</string> <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="2162434417489128282">"आपने फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से कोशिश की है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल कोशिशों के बाद, कार्य प्रोफ़ाइल को निकाल दिया जाएगा, जिससे सभी प्रोफ़ाइल डेटा हट जाएगा."</string> <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="8966727588974691544">"आपने टैबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से कोशिश की है. कार्य प्रोफ़ाइल को निकाल दिया जाएगा, जिससे सभी प्रोफ़ाइल डेटा हट जाएगा."</string> @@ -105,7 +105,7 @@ <string name="kg_password_puk_failed" msgid="1331621440873439974">"SIM PUK की कार्यवाही विफल रही!"</string> <string name="kg_pin_accepted" msgid="7637293533973802143">"कोड स्वीकार किया गया!"</string> <string name="keyguard_carrier_default" msgid="4274828292998453695">"कोई सेवा नहीं."</string> - <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"इनपुट पद्धति बदलें"</string> + <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"इनपुट का तरीका बदलें"</string> <string name="airplane_mode" msgid="3807209033737676010">"हवाई जहाज़ मोड"</string> <string name="kg_prompt_reason_restart_pattern" msgid="7246972020562621506">"डिवाइस फिर से चालू होने के बाद पैटर्न ज़रूरी है"</string> <string name="kg_prompt_reason_restart_pin" msgid="6303592361322290145">"डिवाइस फिर से चालू होने के बाद पिन ज़रूरी है"</string> diff --git a/packages/SystemUI/res-keyguard/values-mr/strings.xml b/packages/SystemUI/res-keyguard/values-mr/strings.xml index 596d41a11df4..7fcc7b63f350 100644 --- a/packages/SystemUI/res-keyguard/values-mr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-mr/strings.xml @@ -58,7 +58,7 @@ <string name="kg_wrong_password" msgid="4580683060277329277">"चुकीचा संकेतशब्द"</string> <string name="kg_wrong_pin" msgid="4785660766909463466">"चुकीचा पिन"</string> <string name="kg_too_many_failed_attempts_countdown" msgid="527455490371878356">"<xliff:g id="NUMBER">%d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string> - <string name="kg_pattern_instructions" msgid="5547646893001491340">"आपला पॅटर्न काढा"</string> + <string name="kg_pattern_instructions" msgid="5547646893001491340">"तुमचा पॅटर्न काढा"</string> <string name="kg_sim_pin_instructions" msgid="6389000973113699187">"सिम पिन एंटर करा"</string> <string name="kg_sim_pin_instructions_multi" msgid="1643757228644271861">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" साठी सिम पिन एंटर करा"</string> <string name="kg_sim_lock_instructions_esim" msgid="4957650659201013804">"मोबाइल सेवांशिवाय डीव्हाइस वापरण्यासाठी eSIM बंद करा."</string> diff --git a/packages/SystemUI/res-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml index 96d124d0bf0c..358d0224928f 100644 --- a/packages/SystemUI/res-keyguard/values-pa/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml @@ -34,7 +34,7 @@ <string name="keyguard_plugged_in_charging_fast" msgid="8869226755413795173">"ਤੇਜ਼ੀ ਨਾਲ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="6637043106038550407">"ਹੌਲੀ-ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string> <string name="keyguard_low_battery" msgid="9218432555787624490">"ਆਪਣਾ ਚਾਰਜਰ ਕਨੈਕਟ ਕਰੋ।"</string> - <string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"ਅਨਲੌਕ ਕਰਨ ਲਈ \"ਮੀਨੂ\" ਦਬਾਓ।"</string> + <string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"ਅਨਲੌਕ ਕਰਨ ਲਈ \'ਮੀਨੂ\' ਦਬਾਓ।"</string> <string name="keyguard_network_locked_message" msgid="6743537524631420759">"ਨੈੱਟਵਰਕ ਲੌਕ ਕੀਤਾ ਗਿਆ"</string> <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"ਕੋਈ SIM ਕਾਰਡ ਮੌਜੂਦ ਨਹੀਂ"</string> <string name="keyguard_missing_sim_message" product="tablet" msgid="4550152848200783542">"ਟੈਬਲੈੱਟ ਵਿੱਚ ਕੋਈ SIM ਕਾਰਡ ਮੌਜੂਦ ਨਹੀਂ।"</string> diff --git a/packages/SystemUI/res-keyguard/values-sw320dp/dimens.xml b/packages/SystemUI/res-keyguard/values-sw320dp/dimens.xml index 2c209e244816..38d2ecc3ddb5 100644 --- a/packages/SystemUI/res-keyguard/values-sw320dp/dimens.xml +++ b/packages/SystemUI/res-keyguard/values-sw320dp/dimens.xml @@ -19,7 +19,8 @@ --> <resources> - <!-- Height of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) --> + <!-- Height of the sliding KeyguardSecurityContainer + (includes 2x keyguard_security_view_top_margin) --> <dimen name="keyguard_security_height">345dp</dimen> </resources> diff --git a/packages/SystemUI/res-keyguard/values-sw360dp/dimens.xml b/packages/SystemUI/res-keyguard/values-sw360dp/dimens.xml index 38658caeb443..90c4795d1e56 100644 --- a/packages/SystemUI/res-keyguard/values-sw360dp/dimens.xml +++ b/packages/SystemUI/res-keyguard/values-sw360dp/dimens.xml @@ -20,6 +20,6 @@ <resources> <!-- Height of the sliding KeyguardSecurityContainer (includes 2x - keyguard_security_view_margin) --> + keyguard_security_view_top_margin) --> <dimen name="keyguard_security_height">400dp</dimen> </resources> diff --git a/packages/SystemUI/res-keyguard/values-sw540dp-port/dimens.xml b/packages/SystemUI/res-keyguard/values-sw540dp-port/dimens.xml index de3106f9571b..9ea04dc72ba9 100644 --- a/packages/SystemUI/res-keyguard/values-sw540dp-port/dimens.xml +++ b/packages/SystemUI/res-keyguard/values-sw540dp-port/dimens.xml @@ -19,6 +19,6 @@ --> <resources> <!-- Height of the sliding KeyguardSecurityContainer - (includes 2x keyguard_security_view_margin) --> + (includes 2x keyguard_security_view_top_margin) --> <dimen name="keyguard_security_height">500dp</dimen> </resources> diff --git a/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml b/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml index 9e788bec49cd..4ae7cb97e1a2 100644 --- a/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml +++ b/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml @@ -23,7 +23,7 @@ <dimen name="kg_status_line_font_size">16sp</dimen> <!-- Margin around the various security views --> - <dimen name="keyguard_security_view_margin">12dp</dimen> + <dimen name="keyguard_security_view_top_margin">12dp</dimen> <!-- Overload default clock widget parameters --> <dimen name="widget_big_font_size">100dp</dimen> diff --git a/packages/SystemUI/res-keyguard/values-sw720dp/dimens.xml b/packages/SystemUI/res-keyguard/values-sw720dp/dimens.xml index 7eb63d7b100a..9157822db960 100644 --- a/packages/SystemUI/res-keyguard/values-sw720dp/dimens.xml +++ b/packages/SystemUI/res-keyguard/values-sw720dp/dimens.xml @@ -18,10 +18,8 @@ --> <resources> - <!-- Width of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) --> - <dimen name="keyguard_security_width">420dp</dimen> - - <!-- Height of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) --> + <!-- Height of the sliding KeyguardSecurityContainer + (includes 2x keyguard_security_view_top_margin) --> <dimen name="keyguard_security_height">420dp</dimen> <dimen name="widget_big_font_size">100dp</dimen> diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml index a721dd0609dc..bcac07295cce 100644 --- a/packages/SystemUI/res-keyguard/values/dimens.xml +++ b/packages/SystemUI/res-keyguard/values/dimens.xml @@ -22,17 +22,20 @@ <!-- Size of the generic status lines keyguard's status view --> <dimen name="kg_status_line_font_size">14sp</dimen> - <!-- Width of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) --> - <dimen name="keyguard_security_width">320dp</dimen> + <!-- Maximum width of the sliding KeyguardSecurityContainer --> + <dimen name="keyguard_security_width">420dp</dimen> - <!-- Height of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) --> + <!-- Height of the sliding KeyguardSecurityContainer + (includes 2x keyguard_security_view_top_margin) --> <dimen name="keyguard_security_height">400dp</dimen> - <!-- Max Height of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) --> + <!-- Max Height of the sliding KeyguardSecurityContainer + (includes 2x keyguard_security_view_top_margin) --> <dimen name="keyguard_security_max_height">450dp</dimen> <!-- Margin around the various security views --> - <dimen name="keyguard_security_view_margin">8dp</dimen> + <dimen name="keyguard_security_view_top_margin">8dp</dimen> + <dimen name="keyguard_security_view_lateral_margin">36dp</dimen> <!-- EmergencyCarrierArea overlap - amount to overlap the emergency button and carrier text. Should be 0 on devices with plenty of room (e.g. tablets) --> diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml index 589f1c16935b..b0f7d2810a3d 100644 --- a/packages/SystemUI/res-keyguard/values/strings.xml +++ b/packages/SystemUI/res-keyguard/values/strings.xml @@ -133,7 +133,10 @@ <!-- Message shown when user enters wrong PIN --> <string name="kg_wrong_pin">Wrong PIN</string> <!-- Countdown message shown after too many failed unlock attempts --> - <string name="kg_too_many_failed_attempts_countdown">Try again in <xliff:g id="number">%d</xliff:g> seconds.</string> + <plurals name="kg_too_many_failed_attempts_countdown"> + <item quantity="one">Try again in 1 second.</item> + <item quantity="other">Try again in <xliff:g id="number">%d</xliff:g> seconds.</item> + </plurals> <!-- Instructions for using the pattern unlock screen --> <string name="kg_pattern_instructions">Draw your pattern</string> <!-- Instructions for using the SIM PIN unlock screen --> diff --git a/packages/SystemUI/res/layout/battery_percentage_view.xml b/packages/SystemUI/res/layout/battery_percentage_view.xml index deb494fdefbc..59c0957d98cb 100644 --- a/packages/SystemUI/res/layout/battery_percentage_view.xml +++ b/packages/SystemUI/res/layout/battery_percentage_view.xml @@ -26,4 +26,5 @@ android:textColor="?android:attr/textColorPrimary" android:gravity="center_vertical|start" android:paddingEnd="@dimen/battery_level_padding_start" + android:importantForAccessibility="no" /> diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml index bc290129f545..dde2db2f484f 100644 --- a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml +++ b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml @@ -20,10 +20,7 @@ android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginLeft="@dimen/car_fullscreen_user_pod_margin_side" - android:layout_marginRight="@dimen/car_fullscreen_user_pod_margin_side" - android:gravity="center" - android:layout_weight="1" > + android:gravity="center" > <ImageView android:id="@+id/user_avatar" android:layout_gravity="center" @@ -31,10 +28,13 @@ android:layout_height="@dimen/car_fullscreen_user_pod_image_avatar_height" /> <TextView android:id="@+id/user_name" - android:layout_width="wrap_content" + android:layout_width="@dimen/car_fullscreen_user_pod_width" android:layout_height="wrap_content" android:layout_marginTop="@dimen/car_fullscreen_user_pod_margin_above_text" android:textSize="@dimen/car_fullscreen_user_pod_text_size" android:textColor="@color/qs_user_detail_name" + android:ellipsize="end" + android:singleLine="true" + android:gravity="center_horizontal" android:layout_gravity="center_horizontal" /> </LinearLayout> diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml index 8c556801cf9b..99d010f2ac2b 100644 --- a/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml +++ b/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml @@ -18,7 +18,8 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_gravity="center"> + android:gravity="center" + android:layout_gravity="center" > <!-- car_fullscreen_user_pods will be dynamically added here. --> </LinearLayout> diff --git a/packages/SystemUI/res/layout/car_qs_panel.xml b/packages/SystemUI/res/layout/car_qs_panel.xml index 4f7fa15921f8..4cb0fd5fecfb 100644 --- a/packages/SystemUI/res/layout/car_qs_panel.xml +++ b/packages/SystemUI/res/layout/car_qs_panel.xml @@ -18,17 +18,18 @@ android:id="@+id/quick_settings_container" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@drawable/car_qs_background_primary" + android:background="@color/car_qs_background_primary" android:orientation="vertical" - android:elevation="4dp"> + android:elevation="4dp" + android:theme="@android:style/Theme"> - <include layout="@layout/car_status_bar_header" /> - <include layout="@layout/car_qs_footer" /> + <include layout="@layout/car_status_bar_header"/> + <include layout="@layout/car_qs_footer"/> - <include android:id="@+id/qs_detail" layout="@layout/car_qs_detail" /> - - <com.android.systemui.qs.QSPanel - android:id="@+id/quick_settings_panel" + <com.android.systemui.statusbar.car.UserGridView + android:id="@+id/user_grid" android:layout_width="match_parent" - android:layout_height="0dp"/> + android:layout_height="wrap_content" + android:layout_marginLeft="@dimen/car_margin" + android:layout_marginRight="@dimen/car_margin" /> </LinearLayout> diff --git a/packages/SystemUI/res/layout/global_actions_item.xml b/packages/SystemUI/res/layout/global_actions_item.xml index e3a488c20c3f..0d735e7fff33 100644 --- a/packages/SystemUI/res/layout/global_actions_item.xml +++ b/packages/SystemUI/res/layout/global_actions_item.xml @@ -25,8 +25,8 @@ android:minHeight="92dp" android:gravity="center" android:orientation="vertical" - android:paddingEnd="8dip" - android:paddingStart="8dip"> + android:paddingEnd="0dip" + android:paddingStart="0dip"> <ImageView android:id="@*android:id/icon" diff --git a/packages/SystemUI/res/layout/global_actions_wrapped.xml b/packages/SystemUI/res/layout/global_actions_wrapped.xml index ec357d252a5c..43aa8abe6b66 100644 --- a/packages/SystemUI/res/layout/global_actions_wrapped.xml +++ b/packages/SystemUI/res/layout/global_actions_wrapped.xml @@ -9,11 +9,12 @@ android:theme="@style/qs_theme" android:clipChildren="false"> + <!-- Global actions is right-aligned to be physically near power button --> <LinearLayout android:id="@android:id/list" android:layout_width="@dimen/global_actions_panel_width" android:layout_height="wrap_content" - android:layout_gravity="top|end" + android:layout_gravity="top|right" android:gravity="center" android:orientation="vertical" android:padding="12dp" diff --git a/packages/SystemUI/res/layout/navigation_layout.xml b/packages/SystemUI/res/layout/navigation_layout.xml index 53f5dfe1acbe..3e6079451c74 100644 --- a/packages/SystemUI/res/layout/navigation_layout.xml +++ b/packages/SystemUI/res/layout/navigation_layout.xml @@ -21,8 +21,8 @@ android:layout_height="match_parent" android:layout_marginStart="@dimen/rounded_corner_content_padding" android:layout_marginEnd="@dimen/rounded_corner_content_padding" - android:paddingStart="8dp" - android:paddingEnd="8dp"> + android:paddingStart="@dimen/nav_content_padding" + android:paddingEnd="@dimen/nav_content_padding"> <com.android.systemui.statusbar.phone.NearestTouchFrame android:id="@+id/nav_buttons" diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml index 849bea49a62c..2cf3e4ac3f19 100644 --- a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml +++ b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml @@ -37,6 +37,7 @@ android:ellipsize="marquee" android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="?android:attr/textColorPrimary" + android:textDirection="locale" android:singleLine="true" /> <com.android.systemui.BatteryMeterView android:id="@+id/battery" diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index a99fb6cdcfce..8296a1c50eea 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Die rekenaar se RSA-sleutel-vingerafdruk is:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Laat altyd toe van hierdie rekenaar af"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB-ontfouting word nie toegelaat nie"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Die gebruiker wat tans by hierdie toestel aangemeld is, kan nie USB-ontfouting aanskakel nie. Skakel na die primêre gebruiker toe oor om hierdie kenmerk te gebruik."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zoem om skerm te vul"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Strek om skerm te vul"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Stoor tans skermkiekie..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Kom meer te wete"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Jy is gekoppel aan <xliff:g id="VPN_APP">%1$s</xliff:g>, wat jou netwerkaktiwiteit, insluitend e-posse, programme en webwerwe, kan monitor."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Maak VPN-instellings oop"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Maak vertroude eiebewyse oop"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Jou administrateur het netwerkloglêers aangeskakel wat verkeer op jou toestel monitor.\n\nKontak jou administrateur vir meer inligting."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Hierdie program het nie kennisgewingkategorieë nie"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Kennisgewings van hierdie program af kan nie afgeskakel word nie"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 uit <xliff:g id="NUMBER_1">%d</xliff:g> kennisgewingkategorieë van hierdie program</item> - <item quantity="one">1 uit <xliff:g id="NUMBER_0">%d</xliff:g> kennisgewingkategorie van hierdie program</item> + <item quantity="other">1 uit <xliff:g id="NUMBER_1">%s</xliff:g> kennisgewingkategorieë van hierdie program</item> + <item quantity="one">1 uit <xliff:g id="NUMBER_0">%s</xliff:g> kennisgewingkategorie van hierdie program</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d minuut</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Batterygebruik"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Batterybespaarder is nie beskikbaar wanneer gelaai word nie"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Batterybespaarder"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Batterybespaarder is nie beskikbaar wanneer gelaai word nie"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Batterybespaarder"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Verminder werkverrigting en agtergronddata"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Knoppie <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimeer"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Maak toe"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Sleep af om toe te maak"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Prent op prent-kieslys"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Kieslys"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in beeld-in-beeld"</string> <string name="pip_notification_message" msgid="5619512781514343311">"As jy nie wil hê dat <xliff:g id="NAME">%s</xliff:g> hierdie kenmerk moet gebruik nie, tik om instellings oop te maak en skakel dit af."</string> <string name="pip_play" msgid="1417176722760265888">"Speel"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Kieslys"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g>-program"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Opletberigte"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Battery"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Skermkiekies"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Algemene boodskappe"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Berging"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Programme wat op die agtergrond loop"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Tik vir besonderhede oor battery- en datagebruik"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Skakel mobiele data af?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Instellings kan nie jou antwoord verifieer nie omdat \'n program \'n toestemmingversoek verberg."</string> </resources> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index a7b04c4cf749..a256ac205a6b 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"የኮምፒውተሩ RSA ቁልፍ ጣት አሻራ ይሄ ነው፦\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"ሁልጊዜ ከዚህ ኮምፒውተር ፍቀድ"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"የዩኤስቢ እርማት አይፈቀድም"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"አሁን ወደዚህ መሣሪያ የገባው ተጠቃሚ የዩኤስቢ እርማትን ማብራት አይችልም። ይህን ባህሪ ለመጠቀም ወደ ዋና ተጠቃሚ ይቀይሩ።"</string> <string name="compat_mode_on" msgid="6623839244840638213">"ማያ እንዲሞላ አጉላ"</string> <string name="compat_mode_off" msgid="4434467572461327898">"ማያ ለመሙለት ሳብ"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"ቅጽበታዊ ገጽ እይታ በማስቀመጥ ላይ..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"የበለጠ ለመረዳት"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"እርስዎ ኢሜይሎችን፣ መተግበሪያዎችን እና ድር ጣቢያዎችንም ጨምሮ የግል የአውታረ መረብ እንቅስቃሴዎን መከታተል ከሚችለው <xliff:g id="VPN_APP">%1$s</xliff:g> ጋር ተገናኝተዋል።"</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"የቪፒኤን ቅንብሮችን ይክፈቱ"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"የታመኑ ምስክርነቶችን ክፈት"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"የእርስዎ አስተዳዳሪ የአውታረ መረብ ምዝግብ ማስታወሻ መያዝን አብርተዋል፣ ይህም በመሣሪያዎ ላይ ያለውን ትራፊክ ይከታተላል።\n\nተጨማሪ መረጃ ለማግኘት አስተዳዳሪዎን ያነጋግሩ።"</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"ይህ መተግበሪያ የማሳወቂያ ምድቦች የሉትም"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"ከዚህ መተግበሪያ የሚመጡ ማሳወቂያዎች ሊጠፉ አይችሉም"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 ከ<xliff:g id="NUMBER_1">%d</xliff:g> የማሳወቂያ ምድቦች ከዚህ መተግበሪያ</item> - <item quantity="other">1 <xliff:g id="NUMBER_1">%d</xliff:g> የማሳወቂያ ምድቦች ከዚህ መተግበሪያ</item> + <item quantity="one">1 ከ<xliff:g id="NUMBER_1">%s</xliff:g> የማሳወቂያ ምድቦች ከዚህ መተግበሪያ</item> + <item quantity="other">1 <xliff:g id="NUMBER_1">%s</xliff:g> የማሳወቂያ ምድቦች ከዚህ መተግበሪያ</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>፣ <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="other"> %d ደቂቃዎች</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"የባትሪ አጠቃቀም"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"ኃይል በሚሞላበት ጊዜ ባትሪ ቆጣቢ አይገኝም"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"ባትሪ ቆጣቢ"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"ኃይል በሚሞላበት ጊዜ ባትሪ ቆጣቢ አይገኝም"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"የባትሪ ኃይል ቆጣቢ"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"አፈጻጸምን እና የጀርባ ውሂብን ይቀንሳል"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"አዝራር <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"መነሻ"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"አሳንስ"</string> <string name="pip_phone_close" msgid="8416647892889710330">"ዝጋ"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ለማሰናበት ወደ ታች ይጎትቱ"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"በስዕል ምናሌ ውስጥ ያለ ስዕል"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"ምናሌ"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> በስዕል-ላይ-ስዕል ውስጥ ነው"</string> <string name="pip_notification_message" msgid="5619512781514343311">"<xliff:g id="NAME">%s</xliff:g> ይህን ባህሪ እንዲጠቀም ካልፈለጉ ቅንብሮችን ለመክፈት መታ ያድርጉና ያጥፉት።"</string> <string name="pip_play" msgid="1417176722760265888">"አጫውት"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"ምናሌ"</string> <string name="tuner_app" msgid="3507057938640108777">"የ<xliff:g id="APP">%1$s</xliff:g> መተግበሪያ"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"ማንቂያዎች"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"ባትሪ"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"ቅጽበታዊ ገጽ እይታዎች"</string> <string name="notification_channel_general" msgid="4525309436693914482">"አጠቃላይ መልዕክቶች"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"ማከማቻ"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"በጀርባ ውስጥ የሚያሄዱ መተግበሪያዎች"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"በባትሪ እና ውሂብ አጠቃቀም ላይ ዝርዝሮችን ለማግኘት መታ ያድርጉ"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"የተንቀሳቃሽ ስልክ ውሂብ ይጥፋ?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"አንድ መተግበሪያ የፍቃድ ጥያቄ እያገደ ስለሆነ ቅንብሮች ጥያቄዎን ማረጋገጥ አይችሉም።"</string> </resources> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 3632fe02d9d8..bcf58d4b33d0 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -68,8 +68,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"الملف المرجعي الرئيسي لـ RSA في هذا الكمبيوتر هو:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"السماح دائمًا من هذا الكمبيوتر"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"لا يُسمح بتصحيح أخطاء USB"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"لا يمكن للمستخدم الذي يسجّل دخوله حاليًا إلى هذا الجهاز تشغيل تصحيح أخطاء USB. لاستخدام هذه الميزة، يمكنك التبديل إلى المستخدم الأساسي."</string> <string name="compat_mode_on" msgid="6623839244840638213">"تكبير/تصغير لملء الشاشة"</string> <string name="compat_mode_off" msgid="4434467572461327898">"توسيع بملء الشاشة"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"جارٍ حفظ لقطة الشاشة..."</string> @@ -465,8 +464,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"مزيد من المعلومات"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"لقد اتصلت بتطبيق <xliff:g id="VPN_APP">%1$s</xliff:g>، الذي يمكن أن يراقب نشاط الشبكة، بما في ذلك رسائل البريد الإلكتروني والتطبيقات والمواقع الإلكترونية."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"فتح إعدادات الشبكة الافتراضية الخاصة (VPN)"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"فتح بيانات الاعتماد الموثوق بها"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"شغَّل المشرف ميزة تسجيل بيانات الشبكة، والتي يتم من خلالها مراقبة حركة البيانات على جهازك.\n\nللحصول على المزيد من المعلومات، اتصل بالمشرف."</string> @@ -566,12 +564,12 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"لا يحتوي هذا التطبيق على فئات إشعار"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"لا يمكن إيقاف الإشعارات من هذا التطبيق"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="zero">1 من إجمالي <xliff:g id="NUMBER_1">%d</xliff:g> فئة إشعار من هذا التطبيق</item> - <item quantity="two">1 من إجمالي فئتي إشعار (<xliff:g id="NUMBER_1">%d</xliff:g>) من هذا التطبيق</item> - <item quantity="few">1 من إجمالي <xliff:g id="NUMBER_1">%d</xliff:g> فئات إشعار من هذا التطبيق</item> - <item quantity="many">1 من إجمالي <xliff:g id="NUMBER_1">%d</xliff:g> فئة إشعار من هذا التطبيق</item> - <item quantity="other">1 من إجمالي <xliff:g id="NUMBER_1">%d</xliff:g> فئة إشعار من هذا التطبيق</item> - <item quantity="one">1 من إجمالي <xliff:g id="NUMBER_0">%d</xliff:g> فئة إشعار من هذا التطبيق</item> + <item quantity="zero">1 من إجمالي <xliff:g id="NUMBER_1">%s</xliff:g> فئة إشعار من هذا التطبيق</item> + <item quantity="two">1 من إجمالي فئتي إشعار (<xliff:g id="NUMBER_1">%s</xliff:g>) من هذا التطبيق</item> + <item quantity="few">1 من إجمالي <xliff:g id="NUMBER_1">%s</xliff:g> فئات إشعار من هذا التطبيق</item> + <item quantity="many">1 من إجمالي <xliff:g id="NUMBER_1">%s</xliff:g> فئة إشعار من هذا التطبيق</item> + <item quantity="other">1 من إجمالي <xliff:g id="NUMBER_1">%s</xliff:g> فئة إشعار من هذا التطبيق</item> + <item quantity="one">1 من إجمالي <xliff:g id="NUMBER_0">%s</xliff:g> فئة إشعار من هذا التطبيق</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>، <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -611,8 +609,8 @@ <item quantity="one">دقيقة واحدة</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"استخدام البطارية"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"وضع توفير شحن البطارية غير متاح أثناء الشحن."</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"توفير شحن البطارية"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"توفير شحن البطارية غير متاح أثناء الشحن"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"توفير شحن البطارية"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"لخفض مستوى الأداء وبيانات الخلفية"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"الزر <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -752,7 +750,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"تصغير"</string> <string name="pip_phone_close" msgid="8416647892889710330">"إغلاق"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"اسحب لأسفل للإلغاء"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"قائمة صورة داخل صورة"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"القائمة"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> يظهر في صورة داخل صورة"</string> <string name="pip_notification_message" msgid="5619512781514343311">"إذا كنت لا تريد أن يستخدم <xliff:g id="NAME">%s</xliff:g> هذه الميزة، فانقر لفتح الإعدادات، ثم أوقِف تشغيل هذه الميزة."</string> <string name="pip_play" msgid="1417176722760265888">"تشغيل"</string> @@ -780,8 +778,7 @@ <string name="tuner_menu" msgid="191640047241552081">"القائمة"</string> <string name="tuner_app" msgid="3507057938640108777">"تطبيق <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"التنبيهات"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"البطارية"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"لقطات الشاشة"</string> <string name="notification_channel_general" msgid="4525309436693914482">"رسائل عامة"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"سعة التخزين"</string> @@ -802,4 +799,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"التطبيقات التي تعمل في الخلفية"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"انقر للحصول على تفاصيل حول البطارية واستخدام البيانات"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"هل تريد إيقاف تشغيل بيانات الجوال؟"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"لا يمكن للإعدادات التحقق من ردك لأن هناك تطبيقًا يحجب طلب الإذن."</string> </resources> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index a20df383d54e..9e4946649973 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Kompüterin RSA barmaq izi: \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Bu kompüterdən həmişə icazə verilsin"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB debaq prosesinə icazə verilmir"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Hazırda bu cihaza daxil olmuş istifadəçi USB sazlama prosesini aktiv edə bilməz. Bu funksiyadan istifadə etmək üçün əsas istifadəçi hesaba daxil olmalıdır."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Ekranı doldurmaq üçün yaxınlaşdır"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Ekranı doldurmaq üçün uzat"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Skrinşot yadda saxlanılır..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Ətraflı məlumat"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"<xliff:g id="VPN_APP">%1$s</xliff:g> tətbiqinə qoşulmusunuz və o, e-məktublar, tətbiq və veb saytlar daxil olmaqla şəbəkə fəaliyyətinizə nəzarət edə bilər."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" ("</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN ayarlarını açın"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Etibarlı kredensialları açın"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Admin, cihazdakı trafikə nəzarət edən şəbəkə loqlarını aktiv etdi.\n\nƏtraflı məlumat üçün administrator ilə əlaqə saxlayın."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Bu tətbiqin bildiriş kateqoriyası yoxdur"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Bu tətbiqin bildirişləri deaktiv edilə bilməz"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">Bu tətbiqin <xliff:g id="NUMBER_1">%d</xliff:g> bildiriş kateqoriyasından 1 kanal</item> - <item quantity="one">Bu tətbiqin <xliff:g id="NUMBER_0">%d</xliff:g> bildiriş kateqoriyasından 1 kanal</item> + <item quantity="other">Bu tətbiqin <xliff:g id="NUMBER_1">%s</xliff:g> bildiriş kateqoriyasından 1 kanal</item> + <item quantity="one">Bu tətbiqin <xliff:g id="NUMBER_0">%s</xliff:g> bildiriş kateqoriyasından 1 kanal</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d dəqiqə</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Batareya istifadəsi"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Enerji Qənaəti doldurulma zamanı əlçatan deyil"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Enerji Qənaəti"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Batareya qənaəti doldurulma zamanı əlçatan deyil"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Batareya qənaəti"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Performansı azaldır və arxa fon datasını məhdudlaşdırır"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Düymə <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Əsas səhifə"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Kiçildin"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Bağlayın"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Rədd etmək üçün aşağı çəkin"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Şəkil-içində-şəkil menyusu"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menyu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> şəkil içində şəkildədir"</string> <string name="pip_notification_message" msgid="5619512781514343311">"<xliff:g id="NAME">%s</xliff:g> tətbiqinin bu funksiyadan istifadə etməyini istəmirsinizsə, ayarları açmaq və deaktiv etmək üçün klikləyin."</string> <string name="pip_play" msgid="1417176722760265888">"Oxudun"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menyu"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> tətbiqi"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Siqnallar"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Batareya"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Skrinşotlar"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Ümumi Mesajlar"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Yaddaş"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Arxa fonda işləyən tətbiqlər"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Batareya və data istifadəsi haqqında ətraflı məlumat üçün klikləyin"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Mobil data söndürülsün?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Tətbiq icazə sorğusunu gizlətdiyi üçün Ayarlar cavabınızı doğrulaya bilməz."</string> </resources> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index 57a3af109852..bf2ff90f2080 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -65,8 +65,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Digitalni otisak RSA ključa ovog računara je:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Uvek dozvoli sa ovog računara"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Otklanjanje grešaka na USB-u nije dozvoljeno"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Korisnik koji je trenutno prijavljen na ovaj uređaj ne može da uključi otklanjanje grešaka na USB-u. Da biste koristili ovu funkciju, prebacite na primarnog korisnika."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zumiraj na celom ekranu"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Razvuci na ceo ekran"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Čuvanje snimka ekrana..."</string> @@ -459,8 +458,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Saznajte više"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Povezani ste sa aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>, koja može da nadgleda aktivnosti na mreži, uključujući imejlove, aplikacije i veb-sajtove."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Otvori podešavanja VPN-a"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Otvorite pouzdane akreditive"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administrator je uključio evidentiranje mreže, koje prati saobraćaj na uređaju.\n\nKontaktirajte administratora za više informacija."</string> @@ -560,9 +558,9 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Ova aplikacija nema kategorije obaveštenja"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Obaveštenja iz ove aplikacije ne mogu da se isključe"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorije obaveštenja za ovu aplikaciju</item> - <item quantity="few">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorije obaveštenja za ovu aplikaciju</item> - <item quantity="other">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorija obaveštenja za ovu aplikaciju</item> + <item quantity="one">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorije obaveštenja za ovu aplikaciju</item> + <item quantity="few">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorije obaveštenja za ovu aplikaciju</item> + <item quantity="other">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorija obaveštenja za ovu aplikaciju</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -593,8 +591,8 @@ <item quantity="other">%d minuta</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Potrošnja baterije"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Ušteda baterije nije dostupna tokom punjenja"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Ušteda baterije"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Ušteda baterije nije dostupna tokom punjenja"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Ušteda baterije"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Smanjuje performanse i pozadinske podatke"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Dugme <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Taster Početna"</string> @@ -734,7 +732,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Umanji"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Zatvori"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Prevucite nadole da biste odbili"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Meni Slika u slici"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Meni"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> je slika u slici"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Ako ne želite da <xliff:g id="NAME">%s</xliff:g> koristi ovu funkciju, dodirnite da biste otvorili podešavanja i isključili je."</string> <string name="pip_play" msgid="1417176722760265888">"Pusti"</string> @@ -762,8 +760,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Meni"</string> <string name="tuner_app" msgid="3507057938640108777">"Aplikacija <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Obaveštenja"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Baterija"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Snimci ekrana"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Opšte poruke"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Memorijski prostor"</string> @@ -784,4 +781,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Aplikacije pokrenute u pozadini"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Dodirnite za detalje o bateriji i potrošnji podataka"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Želite da onemogućite mobilne podatke?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Podešavanja ne mogu da verifikuju vaš odgovor jer aplikacija skriva zahtev za dozvolu."</string> </resources> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index 707ffb5cd22e..9006a5ea61fd 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -66,8 +66,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Адбiтак ключа RSA на гэтым камп\'ютары:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Заўсёды дазваляць з гэтага камп\'ютара"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Адладка USB не дапускаецца"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Карыстальнік, які зараз увайшоў у гэту прыладу, не можа ўключыць адладку USB. Каб выкарыстоўваць гэту функцыю, пераключыцеся на асноўнага карыстальніка."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Павял. на ўвесь экран"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Расцягн. на ўвесь экран"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Захаванне скрыншота..."</string> @@ -463,8 +462,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Даведацца больш"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Вы падключаны да праграмы <xliff:g id="VPN_APP">%1$s</xliff:g>, якая можа сачыць за вашай сеткавай дзейнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" ,"</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Адкрыйце налады VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Адкрыць давераныя ўліковыя даныя"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Ваш адміністратар уключыў вядзенне журнала сеткі, з дапамогай якога адсочваецца трафік на вашай прыладзе.\n\nДля атрымання дадатковай інфармацыі звярніцеся да адміністратара."</string> @@ -564,10 +562,10 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"У гэтай праграме няма катэгорый апавяшчэнняў"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Апавяшчэнні ад гэтай праграмы нельга адключыць"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 з <xliff:g id="NUMBER_1">%d</xliff:g> катэгорыі апавяшчэнняў у гэтай праграме</item> - <item quantity="few">1 з <xliff:g id="NUMBER_1">%d</xliff:g> катэгорый апавяшчэнняў у гэтай праграме</item> - <item quantity="many">1 з <xliff:g id="NUMBER_1">%d</xliff:g> катэгорый апавяшчэнняў у гэтай праграме</item> - <item quantity="other">1 з <xliff:g id="NUMBER_1">%d</xliff:g> катэгорыі апавяшчэнняў у гэтай праграме</item> + <item quantity="one">1 з <xliff:g id="NUMBER_1">%s</xliff:g> катэгорыі апавяшчэнняў у гэтай праграме</item> + <item quantity="few">1 з <xliff:g id="NUMBER_1">%s</xliff:g> катэгорый апавяшчэнняў у гэтай праграме</item> + <item quantity="many">1 з <xliff:g id="NUMBER_1">%s</xliff:g> катэгорый апавяшчэнняў у гэтай праграме</item> + <item quantity="other">1 з <xliff:g id="NUMBER_1">%s</xliff:g> катэгорыі апавяшчэнняў у гэтай праграме</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -601,8 +599,8 @@ <item quantity="other">%d хвіліны</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Выкарыстанне зараду"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Эканомія зараду акумулятара недаступная падчас зарадкі"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Эканомія зараду"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Эканомія зараду акумулятара недаступная падчас зарадкі"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Эканомія зараду акумулятара"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Памяншае прадукцыйнасць і фонавую перадачу даных"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Кнопка <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -742,7 +740,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Згарнуць"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Закрыць"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Перацягніце ўніз, каб адхіліць"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Меню \"Відарыс у відарысе\""</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Меню"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> з’яўляецца відарысам у відарысе"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Калі вы не хочаце, каб праграма <xliff:g id="NAME">%s</xliff:g> выкарыстоўвала гэту функцыю, дакраніцеся, каб адкрыць налады і адключыць яе."</string> <string name="pip_play" msgid="1417176722760265888">"Прайграць"</string> @@ -770,8 +768,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Меню"</string> <string name="tuner_app" msgid="3507057938640108777">"Праграма <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Абвесткi"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Акумулятар"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Здымкі экрана"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Агульныя паведамленні"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Захоўванне"</string> @@ -792,4 +789,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Праграмы, якія працуюць у фонавым рэжыме"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Дакраніцеся, каб даведацца пра выкарыстанне трафіка і акумулятара"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Выключыць мабільную перадачу даных?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Праграма хавае запыт на дазвол, таму ваш адказ немагчыма спраўдзіць у Наладах."</string> </resources> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 9c72f8209798..e64354da081f 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Отпечатъкът на RSA ключа на компютъра е:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Винаги да се разрешава от този компютър"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Отстраняването на грешки през USB не е разрешено"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Потребителят, който понастоящем е влязъл в това устройство, не може да включи функцията за отстраняване на грешки през USB. За да я използвате, превключете към основния потребител."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Мащаб – запълва екрана"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Разпъване – запълва екрана"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Екранната снимка се запазва..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Научете повече"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Установена е връзка с приложението <xliff:g id="VPN_APP">%1$s</xliff:g>, което може да наблюдава активността ви в мрежата, вкл. имейли, приложения и уебсайтове."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Отваряне на настройките за VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Отваряне на надеждните идентификационни данни"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Администраторът ви е включил функцията за регистриране на мрежовата активност, която следи трафика на устройството ви.\n\nЗа повече информация се свържете с администратора си."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"За това приложение няма категории на известията"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Известията от това приложение не могат да бъдат изключени"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 от <xliff:g id="NUMBER_1">%d</xliff:g> категории известия от това приложение</item> - <item quantity="one">1 от <xliff:g id="NUMBER_0">%d</xliff:g> категория известия от това приложение</item> + <item quantity="other">1 от <xliff:g id="NUMBER_1">%s</xliff:g> категории известия от това приложение</item> + <item quantity="one">1 от <xliff:g id="NUMBER_0">%s</xliff:g> категория известия от това приложение</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"„<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>“, „<xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>“"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d минута</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Ползв. на батерията"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Режимът за запазване на батерията не е налице при зареждане"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Режим за запазване на батерията"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Режимът за запазване на батерията не работи при зареждане"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Режим за запазване на батерията"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Намалява ефективността и данните на заден план"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Бутон „<xliff:g id="NAME">%1$s</xliff:g>“"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Начало"</string> @@ -616,7 +614,7 @@ <string name="keyboard_key_insert" msgid="8530501581636082614">"Insert"</string> <string name="keyboard_key_num_lock" msgid="5052537581246772117">"Num Lock"</string> <string name="keyboard_key_numpad_template" msgid="8729216555174634026">"Цифрова клавиатура – <xliff:g id="NAME">%1$s</xliff:g>"</string> - <string name="keyboard_shortcut_group_system" msgid="6472647649616541064">"Системни"</string> + <string name="keyboard_shortcut_group_system" msgid="6472647649616541064">"Системни настройки"</string> <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Начало"</string> <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Скорошни"</string> <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Назад"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Намаляване"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Затваряне"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Преместете надолу с плъзгане, за да отхвърлите"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Меню за режима „Картина в картината“"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Меню"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> е в режима „Картина в картината“"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Ако не искате <xliff:g id="NAME">%s</xliff:g> да използва тази функция, докоснете, за да отворите настройките, и я изключете."</string> <string name="pip_play" msgid="1417176722760265888">"Пускане"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Меню"</string> <string name="tuner_app" msgid="3507057938640108777">"Приложение <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Сигнали"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Батерия"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Екранни снимки"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Общи съобщения"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Хранилище"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Приложения, работещи на заден план"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Докоснете за информация относно използването на батерията и преноса на данни"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Да се изключат ли мобилните данни?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"От Настройки не може да се получи потвърждение за отговора ви, защото заявката за разрешение се прикрива от приложение."</string> </resources> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index f8b245ffb4af..b97a64851547 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -64,10 +64,9 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"কম্পিউটারের RSA কী আঙ্গুলের ছাপ হল:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"এই কম্পিউটার থেকে সর্বদা অনুমতি দিন"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB ডিবাগিং অনুমোদিত নয়"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ব্যবহারকারী এখন এই ডিভাইসে সাইন-ইন করেছেন তাই USB ডিবাগিং চালু করা যাবে না। এই বৈশিষ্ট্যটি ব্যবহার করতে, প্রাথমিক ব্যবহারকারীতে পাল্টে নিন।"</string> <string name="compat_mode_on" msgid="6623839244840638213">"স্ক্রীণ পূরণ করতে জুম করুন"</string> - <string name="compat_mode_off" msgid="4434467572461327898">"পূর্ণ স্ক্রীণে প্রসারিত করুন"</string> + <string name="compat_mode_off" msgid="4434467572461327898">"ফুল স্ক্রিন করুন"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"স্ক্রীনশট সংরক্ষণ করা হচ্ছে..."</string> <string name="screenshot_saving_title" msgid="8242282144535555697">"স্ক্রীনশট সংরক্ষণ করা হচ্ছে..."</string> <string name="screenshot_saving_text" msgid="2419718443411738818">"স্ক্রীনশট সংরক্ষণ করা হচ্ছে৷"</string> @@ -78,8 +77,8 @@ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"সঞ্চয়স্থান সীমিত থাকায় স্ক্রীনশটটি সংরক্ষণ করা যাবে না৷"</string> <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"এই অ্যাপ বা আপনার প্রতিষ্ঠান স্ক্রিনশট নেওয়ার অনুমতি দেয়নি"</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB ফাইল স্থানান্তরের বিকল্পগুলি"</string> - <string name="use_mtp_button_title" msgid="4333504413563023626">"একটি মিডিয়া প্লেয়ার হিসাবে মাউন্ট করুন (MTP)"</string> - <string name="use_ptp_button_title" msgid="7517127540301625751">"একটি ক্যামেরা হিসাবে মাউন্ট করুন (PTP)"</string> + <string name="use_mtp_button_title" msgid="4333504413563023626">"একটি মিডিয়া প্লেয়ার হিসেবে মাউন্ট করুন (MTP)"</string> + <string name="use_ptp_button_title" msgid="7517127540301625751">"একটি ক্যামেরা হিসেবে মাউন্ট করুন (PTP)"</string> <string name="installer_cd_button_title" msgid="2312667578562201583">"Mac এর জন্য Android এর ফাইল স্তানান্তর অ্যাপ্লিকেশান ইনস্টল করুন"</string> <string name="accessibility_back" msgid="567011538994429120">"ফিরুন"</string> <string name="accessibility_home" msgid="8217216074895377641">"হোম"</string> @@ -260,10 +259,10 @@ <string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> সেটিংস"</string> <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"স্ক্রীন স্বয়ংক্রিয়ভাবে ঘুরে যাবে৷"</string> <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"ভূদৃশ্য সজ্জাতে স্ক্রিন লক করা আছে৷"</string> - <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"প্রতিকৃতি সজ্জাতে স্ক্রিন লক করা আছে৷"</string> + <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"পোর্ট্রেট অবস্থায় স্ক্রিন লক করা আছে৷"</string> <string name="accessibility_rotation_lock_off_changed" msgid="8134601071026305153">"স্ক্রিন এখন স্বয়ংক্রিয়ভাবে ঘুরবে।"</string> <string name="accessibility_rotation_lock_on_landscape_changed" msgid="3135965553707519743">"এখন ভূদৃশ্য সজ্জাতে স্ক্রিন লক হয়েছে।"</string> - <string name="accessibility_rotation_lock_on_portrait_changed" msgid="8922481981834012126">"এখন প্রতিকৃতি সজ্জাতে স্ক্রিন লক হয়েছে।"</string> + <string name="accessibility_rotation_lock_on_portrait_changed" msgid="8922481981834012126">"এখন পোর্ট্রেট অবস্থায় স্ক্রিন লক হয়েছে।"</string> <string name="dessert_case" msgid="1295161776223959221">"ডেজার্ট কেস"</string> <string name="start_dreams" msgid="5640361424498338327">"স্ক্রীন সেভার"</string> <string name="ethernet_label" msgid="7967563676324087464">"ইথারনেট"</string> @@ -280,7 +279,7 @@ <string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"স্বতঃ-ঘূর্ণায়মান স্ক্রিন"</string> <string name="accessibility_quick_settings_rotation_value" msgid="8187398200140760213">"<xliff:g id="ID_1">%s</xliff:g> মোড"</string> <string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"ঘূর্ণন লক করা হয়েছে"</string> - <string name="quick_settings_rotation_locked_portrait_label" msgid="5102691921442135053">"প্রতিকৃতি"</string> + <string name="quick_settings_rotation_locked_portrait_label" msgid="5102691921442135053">"পোর্ট্রেট"</string> <string name="quick_settings_rotation_locked_landscape_label" msgid="8553157770061178719">"ভূদৃশ্য"</string> <string name="quick_settings_ime_label" msgid="7073463064369468429">"ইনপুট পদ্ধতি"</string> <string name="quick_settings_location_label" msgid="5011327048748762257">"অবস্থান"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"আরো জানুন"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"আপনি <xliff:g id="VPN_APP">%1$s</xliff:g> এ সংযুক্ত হয়েছেন, যা ইমেল, অ্যাপ এবং ওয়েবসাইটগুলি সহ আপনার নেটওয়ার্ক কার্যকলাপ নিরীক্ষণ করবে৷"</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN সেটিংস খুলুন"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"বিশ্বস্ত শংসাপত্রগুলি খুলুন"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"আপনার প্রশাসক নেটওয়ার্ক লগিং চালু করেছেন, যা আপনার ডিভাইসের ট্রাফিক নিরীক্ষণ করে।\n\nআরো তথ্যের জন্য আপনার প্রশাসকের সাথে যোগাযোগ করুন।"</string> @@ -479,7 +477,7 @@ <string name="hidden_notifications_setup" msgid="41079514801976810">"সেট আপ"</string> <string name="zen_mode_and_condition" msgid="4462471036429759903">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="volume_zen_end_now" msgid="6930243045593601084">"এখনই বন্ধ করুন"</string> - <string name="accessibility_volume_expand" msgid="5946812790999244205">"প্রসারিত করুন"</string> + <string name="accessibility_volume_expand" msgid="5946812790999244205">"বড় করুন"</string> <string name="accessibility_volume_collapse" msgid="3609549593031810875">"সঙ্কুচিত করুন"</string> <string name="screen_pinning_title" msgid="3273740381976175811">"স্ক্রিন পিন করা হয়েছে"</string> <string name="screen_pinning_description" msgid="8909878447196419623">"এটি আপনি আনপিন না করা পর্যন্ত এটিকে প্রদর্শিত করবে৷ আনপিন করতে ফিরুন এবং ওভারভিউ স্পর্শ করে ধরে থাকুন।"</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"এই অ্যাপটিতে বিজ্ঞপ্তির বিভাগ নেই"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"এই অ্যাপ থেকে আসা বিজ্ঞপ্তি বন্ধ করা যাবে না"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">এই অ্যাপের <xliff:g id="NUMBER_1">%d</xliff:g>টি বিজ্ঞপ্তির বিভাগের মধ্যে ১টি</item> - <item quantity="other">এই অ্যাপের <xliff:g id="NUMBER_1">%d</xliff:g>টি বিজ্ঞপ্তির বিভাগের মধ্যে ১টি</item> + <item quantity="one">এই অ্যাপের <xliff:g id="NUMBER_1">%s</xliff:g>টি বিজ্ঞপ্তির বিভাগের মধ্যে ১টি</item> + <item quantity="other">এই অ্যাপের <xliff:g id="NUMBER_1">%s</xliff:g>টি বিজ্ঞপ্তির বিভাগের মধ্যে ১টি</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="other">%d মিনিট</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"ব্যাটারির ব্যবহার"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"চার্জ করার সময় ব্যাটারি সেভার উপলব্ধ নয়"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"ব্যাটারি সেভার"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"চার্জ করার সময় ব্যাটারি সেভার কাজ করে না"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"ব্যাটারি সেভার"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"কার্য-সম্পাদনা ও পশ্চাদপট ডেটাকে কমিয়ে দেয়"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g> বোতাম"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"হোম"</string> @@ -635,7 +633,7 @@ <string name="tuner_full_zen_title" msgid="4540823317772234308">"ভলিউম নিয়ন্ত্রণ সহ দেখান"</string> <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"বিরক্ত করবেন না"</string> <string name="volume_dnd_silent" msgid="4363882330723050727">"ভলিউম বোতামের শর্টকাট"</string> - <string name="volume_up_silent" msgid="7141255269783588286">"ভলিউম বাড়ানোর মাধ্যেমে \'বিরক্ত করবেন না\' থেকে প্রস্থান করুন"</string> + <string name="volume_up_silent" msgid="7141255269783588286">"ভলিউম বাড়ানোর মাধ্যেমে \'বিরক্ত করবেন না\' থেকে বেরিয়ে আসুন"</string> <string name="battery" msgid="7498329822413202973">"ব্যাটারি"</string> <string name="clock" msgid="7416090374234785905">"ঘড়ি"</string> <string name="headset" msgid="4534219457597457353">"হেডসেট"</string> @@ -646,7 +644,7 @@ <string name="accessibility_data_saver_off" msgid="8841582529453005337">"ডেটা সেভার বন্ধ আছে"</string> <string name="switch_bar_on" msgid="1142437840752794229">"চালু আছে"</string> <string name="switch_bar_off" msgid="8803270596930432874">"বন্ধ আছে"</string> - <string name="nav_bar" msgid="1993221402773877607">"নেভিগেশন দন্ড"</string> + <string name="nav_bar" msgid="1993221402773877607">"নেভিগেশন বার"</string> <string name="nav_bar_layout" msgid="3664072994198772020">"লেআউট"</string> <string name="left_nav_bar_button_type" msgid="8555981238887546528">"অতিরিক্ত বাঁদিকের বোতামের ধরণ"</string> <string name="right_nav_bar_button_type" msgid="2481056627065649656">"অতিরিক্ত ডানদিকের বোতামের ধরণ"</string> @@ -659,7 +657,7 @@ </string-array> <string-array name="nav_bar_layouts"> <item msgid="8077901629964902399">"সাধারণ"</item> - <item msgid="8256205964297588988">"নিবিড়"</item> + <item msgid="8256205964297588988">"অবিস্তৃত"</item> <item msgid="8719936228094005878">"বাঁদিক ঘেঁষা"</item> <item msgid="586019486955594690">"ডানদিক ঘেঁষা"</item> </string-array> @@ -724,11 +722,11 @@ <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ক্রম বা সেটিংস সম্পাদনা করুন৷"</string> <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>টির মধ্যে <xliff:g id="ID_1">%1$d</xliff:g> নং পৃষ্ঠা"</string> <string name="tuner_lock_screen" msgid="5755818559638850294">"লক স্ক্রিন"</string> - <string name="pip_phone_expand" msgid="5889780005575693909">"প্রসারিত করুন"</string> + <string name="pip_phone_expand" msgid="5889780005575693909">"বড় করুন"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"ছোটো করুন"</string> <string name="pip_phone_close" msgid="8416647892889710330">"বন্ধ করুন"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"খারিজ করতে নিচের দিকে টেনে আনুন"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"পিকচার ইন পিকচার মেনু"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"মেনু"</string> <string name="pip_notification_title" msgid="3204024940158161322">"ছবির-মধ্যে-ছবি তে <xliff:g id="NAME">%s</xliff:g> আছেন"</string> <string name="pip_notification_message" msgid="5619512781514343311">"<xliff:g id="NAME">%s</xliff:g> কে এই বৈশিষ্ট্যটি ব্যবহার করতে দিতে না চাইলে ট্যাপ করে সেটিংসে গিয়ে সেটি বন্ধ করে দিন।"</string> <string name="pip_play" msgid="1417176722760265888">"চালান"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"মেনু"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> অ্যাপ"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"সতর্কতাগুলি"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"ব্যাটারি"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"স্ক্রীনশটস"</string> <string name="notification_channel_general" msgid="4525309436693914482">"সাধারণ বার্তাগুলি"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"সঞ্চয়স্থান"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"পটভূমিতে অ্যাপ চালু আছে"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"ব্যাটারি এবং ডেটার ব্যবহারের বিশদ বিবরণের জন্য ট্যাপ করুন"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"মোবাইল ডেটা বন্ধ করবেন?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"একটি অ্যাপ কোনও অনুমোদনের অনুরোধকে ঢেকে দিচ্ছে, তাই সেটিংস থেকে আপনার প্রতিক্রিয়া যাচাই করা যাচ্ছে না।"</string> </resources> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index e6a754525120..6c6eb36b05c2 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -65,8 +65,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"RSA otisak prsta za otključavanje računara je: \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Uvijek dozvoli sa ovog računara"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Otklanjanje grešaka putem uređaja spojenog na USB nije dozvoljeno"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Korisnik koji je trenutno prijavljen na ovaj uređaj ne može uključiti opciju za otklanjanje grešaka koristeći USB. Da koristite tu funkciju, prebacite se na primarnog korisnika."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Uvećaj prikaz na ekran"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Razvuci prikaz na ekran"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Spašavanje snimka ekrana..."</string> @@ -459,8 +458,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Saznajte više"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Povezani ste s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>, koja može pratiti vašu aktivnost na mreži, uključujući e-poruke i web lokacije."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Otvorite postavke VPN mreže"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Otvorite pouzdane akreditive"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Vaš administrator je uključio zapisivanje na mreži, čime se prati saobraćaj na vašem uređaju.\n\nZa više informacija, obratite se administratoru."</string> @@ -562,9 +560,9 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Ova aplikacija nema kategorije obavještenja"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Obavještenja iz ove aplikacije nije moguće isključiti"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorije obavještenja iz ove aplikacije</item> - <item quantity="few">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorije obavještenja iz ove aplikacije</item> - <item quantity="other">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorija obavještenja iz ove aplikacije</item> + <item quantity="one">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorije obavještenja iz ove aplikacije</item> + <item quantity="few">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorije obavještenja iz ove aplikacije</item> + <item quantity="other">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorija obavještenja iz ove aplikacije</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -595,8 +593,8 @@ <item quantity="other">%d minuta</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Potrošnja baterije"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Ušteda baterije je isključena prilikom punjenja"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Ušteda baterije"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Ušteda baterije je isključena za vrijeme punjenja"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Ušteda baterije"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Ograničava rad i prijenos podataka u pozadini"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Dugme <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Tipka za početak"</string> @@ -630,7 +628,7 @@ <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Nazad"</string> <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Obavještenja"</string> <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Prečice tastature"</string> - <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Promijeni način unosa"</string> + <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Promjena načina unosa"</string> <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikacije"</string> <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Pomoć"</string> <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Preglednik"</string> @@ -736,7 +734,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Umanji"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Zatvori"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Povucite prema dolje da odbacite"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Meni za način rada Slika u slici"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Meni"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> je u načinu priakza Slika u slici"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Ako ne želite da <xliff:g id="NAME">%s</xliff:g> koristi ovu funkciju, dodirnite da otvorite postavke i isključite je."</string> <string name="pip_play" msgid="1417176722760265888">"Reproduciraj"</string> @@ -764,8 +762,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Meni"</string> <string name="tuner_app" msgid="3507057938640108777">"Aplikacija <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozorenja"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Baterija"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Snimci ekrana"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Opće poruke"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Pohrana"</string> @@ -786,4 +783,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Aplikacije koje rade u pozadini"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Dodirnite za detalje o potrošnji baterije i prijenosa podataka"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Želite li isključiti prijenos mobilnih podataka?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Postavke ne mogu potvrditi vaš odgovor jer aplikacija zaklanja zahtjev za odobrenje."</string> </resources> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index 2778c3918d2a..e5612394b28d 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"L\'empremta digital de la clau de l\'RSA de l\'equip és:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Dona sempre permís des d\'aquest equip"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"No es permet la depuració USB"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"L\'usuari que té iniciada la sessió al dispositiu en aquest moment no pot activar la depuració per USB. Per utilitzar aquesta funció, cal canviar a l\'usuari principal."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zoom per omplir pantalla"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Estira per omplir pant."</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"S\'està desant captura de pantalla..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Més informació"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Estàs connectat a <xliff:g id="VPN_APP">%1$s</xliff:g>, que pot supervisar la teva activitat a la xarxa, com els correus electrònics, les aplicacions i els llocs web."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Obre la configuració de la VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Obre les credencials de confiança"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"L\'administrador ha activat el registre de xarxa, que supervisa el trànsit del teu dispositiu.\n\nPer obtenir més informació, contacta amb l\'administrador."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Aquesta aplicació no té categories de notificació"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Les notificacions d\'aquesta aplicació no es poden desactivar"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 de <xliff:g id="NUMBER_1">%d</xliff:g> categories de notificació d\'aquesta aplicació</item> - <item quantity="one">1 de <xliff:g id="NUMBER_0">%d</xliff:g> categoria de notificació d\'aquesta aplicació</item> + <item quantity="other">1 de <xliff:g id="NUMBER_1">%s</xliff:g> categories de notificació d\'aquesta aplicació</item> + <item quantity="one">1 de <xliff:g id="NUMBER_0">%s</xliff:g> categoria de notificació d\'aquesta aplicació</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d minut</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Ús de la bateria"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"La funció Estalvi de bateria no està disponible durant la càrrega"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Estalvi de bateria"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"La funció Estalvi de bateria no està disponible durant la càrrega"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Estalvi de bateria"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Redueix el rendiment i les dades en segon pla"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Botó <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Inici"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimitza"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Tanca"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arrossega cap avall per ignorar-ho"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Menú per a Pantalla en pantalla"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menú"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> està en pantalla en pantalla"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Si no vols que <xliff:g id="NAME">%s</xliff:g> utilitzi aquesta funció, toca per obrir la configuració i desactiva-la."</string> <string name="pip_play" msgid="1417176722760265888">"Reprodueix"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menú"</string> <string name="tuner_app" msgid="3507057938640108777">"Aplicació <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Bateria"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Captures de pantalla"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Missatges generals"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Emmagatzematge"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Aplicacions que s\'estan executant en segon pla"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Toca per obtenir informació sobre l\'ús de dades i de bateria"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Vols desactivar les dades mòbils?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Com que hi ha una aplicació que oculta una sol·licitud de permís, no es pot verificar la teva resposta des de la configuració."</string> </resources> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index f1092aa1be25..697eda8f3bb1 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -66,8 +66,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Digitální otisk RSA počítače je:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Vždy povolit z tohoto počítače"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Ladění USB není povoleno"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Uživatel aktuálně přihlášený k tomuto zařízení nemůže zapnout ladění USB. Chcete-li tuto funkci použít, přepněte na primárního uživatele."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Přiblížit na celou obrazovku"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Na celou obrazovku"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Ukládání snímku obrazovky..."</string> @@ -463,8 +462,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Další informace"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Jste připojeni k aplikaci <xliff:g id="VPN_APP">%1$s</xliff:g>, která může sledovat vaši aktivitu v síti, včetně e-mailů, aplikací a webů."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Otevřít nastavení VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Otevřít důvěryhodná oprávnění"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administrátor zapnul protokolování sítě, které monitoruje síťový provoz v zařízení.\n\nDalší informace vám poskytne administrátor."</string> @@ -564,10 +562,10 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Tato aplikace nemá kategorie oznámení"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Oznámení této aplikace nelze vypnout"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="few">1 ze <xliff:g id="NUMBER_1">%d</xliff:g> kategorií oznámení z této aplikace</item> - <item quantity="many">1 z <xliff:g id="NUMBER_1">%d</xliff:g> kategorie oznámení z této aplikace</item> - <item quantity="other">1 z <xliff:g id="NUMBER_1">%d</xliff:g> kategorií oznámení z této aplikace</item> - <item quantity="one">1 z <xliff:g id="NUMBER_0">%d</xliff:g> kategorie oznámení z této aplikace</item> + <item quantity="few">1 ze <xliff:g id="NUMBER_1">%s</xliff:g> kategorií oznámení z této aplikace</item> + <item quantity="many">1 z <xliff:g id="NUMBER_1">%s</xliff:g> kategorie oznámení z této aplikace</item> + <item quantity="other">1 z <xliff:g id="NUMBER_1">%s</xliff:g> kategorií oznámení z této aplikace</item> + <item quantity="one">1 z <xliff:g id="NUMBER_0">%s</xliff:g> kategorie oznámení z této aplikace</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -601,8 +599,8 @@ <item quantity="one">%d minuta</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Využití baterie"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Spořič baterie při nabíjení není k dispozici."</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Spořič baterie"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Spořič baterie při nabíjení není k dispozici"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Spořič baterie"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Omezuje výkon a data na pozadí"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Tlačítko <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -742,7 +740,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalizovat"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Zavřít"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Nápovědu zavřete přetažením dolů"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Nabídka režimu obraz v obraze"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Nabídka"</string> <string name="pip_notification_title" msgid="3204024940158161322">"Aplikace <xliff:g id="NAME">%s</xliff:g> je v režimu obraz v obraze"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Pokud nechcete, aby aplikace <xliff:g id="NAME">%s</xliff:g> tuto funkci používala, klepnutím otevřete nastavení a funkci vypněte."</string> <string name="pip_play" msgid="1417176722760265888">"Přehrát"</string> @@ -770,8 +768,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Nabídka"</string> <string name="tuner_app" msgid="3507057938640108777">"Aplikace <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozornění"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Baterie"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Snímky obrazovek"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Všeobecné zprávy"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Úložiště"</string> @@ -792,4 +789,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Aplikace běžící na pozadí"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Klepnutím zobrazíte podrobnosti o využití baterie a dat"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Vypnout mobilní data?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Žádost o oprávnění je blokována jinou aplikací. Nastavení proto vaši odpověď nemůže ověřit."</string> </resources> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index c2a0fa2147ab..2f7ffdf23e5a 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Fingeraftrykket for computerens RSA-nøgle er:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Tillad altid fra denne computer"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB-fejlretning er ikke tilladt"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Den bruger, der i øjeblikket er logget ind på denne enhed, kan ikke aktivere USB-fejlretning. Skift til den primære bruger for at bruge denne funktion."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zoom til fuld skærm"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Stræk til fuld skærm"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Gemmer screenshot..."</string> @@ -256,7 +255,7 @@ <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> underretning mere i gruppen.</item> <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> underretninger mere i gruppen.</item> </plurals> - <string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Underretningsindstillinger"</string> + <string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Indstillinger for underretninger"</string> <string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Indstillinger for <xliff:g id="APP_NAME">%s</xliff:g>"</string> <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skærmen roterer automatisk."</string> <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Skærmen er nu låst i liggende retning."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Få flere oplysninger"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Du har forbindelse til <xliff:g id="VPN_APP">%1$s</xliff:g>, som kan overvåge din netværksaktivitet, bl.a. e-mails, apps og websites."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Åbn VPN-indstillinger"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Åbn pålidelige loginoplysninger"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Din administrator har aktiveret netværksregistrering, som overvåger trafik på din enhed.\n\nKontakt din administrator for at få flere oplysninger."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Denne app har ingen underretningskategorier"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Underretninger fra denne app kan ikke deaktiveres"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 ud af <xliff:g id="NUMBER_1">%d</xliff:g> underretningskategori fra denne app</item> - <item quantity="other">1 ud af <xliff:g id="NUMBER_1">%d</xliff:g> underretningskategorier fra denne app</item> + <item quantity="one">1 ud af <xliff:g id="NUMBER_1">%s</xliff:g> underretningskategori fra denne app</item> + <item quantity="other">1 ud af <xliff:g id="NUMBER_1">%s</xliff:g> underretningskategorier fra denne app</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="other">%d minutter</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Batteriforbrug"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Batterisparefunktionen er ikke tilgængelig under opladning"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Batterisparefunktion"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Batterisparefunktionen er ikke tilgængelig under opladning"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Batterisparefunktion"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reducerer ydeevne og baggrundsdata"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g>-knap"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimer"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Luk"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Træk nedad for at afvise"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Menu for integreret billede"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> vises som integreret billede"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Hvis du ikke ønsker, at <xliff:g id="NAME">%s</xliff:g> skal benytte denne funktion, kan du åbne indstillingerne og deaktivere den."</string> <string name="pip_play" msgid="1417176722760265888">"Afspil"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menu"</string> <string name="tuner_app" msgid="3507057938640108777">"Appen <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Underretninger"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Batteri"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Generelle meddelelser"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Lagerplads"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Apps, der kører i baggrunden"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Tryk for at se oplysninger om batteri- og dataforbrug"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Vil du deaktivere mobildata?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Indstillinger kan ikke bekræfte dit svar, da en app dækker for en anmodning om tilladelse."</string> </resources> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 4ae58ca5598f..46dcf3e7b4cc 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Der Fingerabdruck des RSA-Schlüssels für diesen Computer lautet: \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Von diesem Computer immer zulassen"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB-Debugging nicht zulässig"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Der momentan auf diesem Gerät angemeldete Nutzer kann das USB-Debugging nicht aktivieren. Um diese Funktion verwenden zu können, wechsle zum primären Nutzer."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zoom auf Bildschirmgröße"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Auf Bildschirmgröße anpassen"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Screenshot wird gespeichert..."</string> @@ -461,8 +460,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Weitere Informationen"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Du bist mit <xliff:g id="VPN_APP">%1$s</xliff:g> verbunden. Die VPN-App kann deine Netzwerkaktivitäten (E-Mails, Apps und Websites) erfassen."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN-Einstellungen öffnen"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Vertrauenswürdige Anmeldedaten öffnen"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Dein Administrator hat die Netzwerkprotokollierung aktiviert. Damit wird der Verkehr auf deinem Gerät erfasst.\n\nWeitere Informationen erhältst du von deinem Administrator."</string> @@ -562,8 +560,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Diese App hat keine Benachrichtigungskategorien"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Benachrichtigungen von dieser App können nicht deaktiviert werden"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 von <xliff:g id="NUMBER_1">%d</xliff:g> Benachrichtigungskategorien von dieser App</item> - <item quantity="one">1 von <xliff:g id="NUMBER_0">%d</xliff:g> Benachrichtigungskategorie von dieser App</item> + <item quantity="other">1 von <xliff:g id="NUMBER_1">%s</xliff:g> Benachrichtigungskategorien von dieser App</item> + <item quantity="one">1 von <xliff:g id="NUMBER_0">%s</xliff:g> Benachrichtigungskategorie von dieser App</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -591,8 +589,8 @@ <item quantity="one">%d Minute</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Akkunutzung"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Der Energiesparmodus ist beim Aufladen nicht verfügbar."</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Energiesparmodus"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Der Energiesparmodus ist beim Aufladen nicht verfügbar"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Energiesparmodus"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduzierung der Leistung und Hintergrunddaten"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Taste <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Pos1"</string> @@ -732,7 +730,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimieren"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Schließen"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Zum Schließen nach unten ziehen"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Menü \"Bild im Bild\""</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menü"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ist in Bild im Bild"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Wenn du nicht möchtest, dass <xliff:g id="NAME">%s</xliff:g> diese Funktion verwendet, tippe, um die Einstellungen zu öffnen und die Funktion zu deaktivieren."</string> <string name="pip_play" msgid="1417176722760265888">"Wiedergeben"</string> @@ -760,8 +758,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menü"</string> <string name="tuner_app" msgid="3507057938640108777">"App \"<xliff:g id="APP">%1$s</xliff:g>\""</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Warnmeldungen"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Akku"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Nachrichten"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Speicher"</string> @@ -782,4 +779,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Apps, die im Hintergrund ausgeführt werden"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Für Details zur Akku- und Datennutzung tippen"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Mobile Daten deaktivieren?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Deine Eingabe wird von \"Einstellungen\" nicht erkannt, weil die Berechtigungsanfrage von einer App verdeckt wird."</string> </resources> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index a7e1a833c3f4..92a0976f06db 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -51,8 +51,8 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"Έγινε σύνδεση μέσω Bluetooth"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Ρύθμιση μεθόδων εισαγωγής"</string> <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Φυσικό πληκτρολόγιο"</string> - <string name="usb_device_permission_prompt" msgid="834698001271562057">"Να επιτρέπεται στο <xliff:g id="APPLICATION">%1$s</xliff:g> η πρόσβαση στη συσκευή USB;"</string> - <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Να επιτρέπεται στο <xliff:g id="APPLICATION">%1$s</xliff:g> η πρόσβαση στο αξεσουάρ USB;"</string> + <string name="usb_device_permission_prompt" msgid="834698001271562057">"Να επιτρέπεται στην εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> η πρόσβαση στη συσκευή USB;"</string> + <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Να επιτρέπεται στην εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> η πρόσβαση στο αξεσουάρ USB;"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Άνοιγμα του <xliff:g id="ACTIVITY">%1$s</xliff:g> κατά τη σύνδεση αυτής της συσκευής USB;"</string> <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"Άνοιγμα του <xliff:g id="ACTIVITY">%1$s</xliff:g> κατά τη σύνδεση αυτού του αξεσουάρ USB;"</string> <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Δεν έχετε εφαρμογή που να συνεργάζεται με το αξεσουάρ USB. Για περισσότερα: <xliff:g id="URL">%1$s</xliff:g>"</string> @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Το μοναδικό χαρακτηριστικό του κλειδιού RSA είναι:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Να επιτρέπεται πάντα από αυτόν τον υπολογιστή"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Δεν επιτρέπεται ο εντοπισμός σφαλμάτων USB"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Ο χρήστης που είναι συνδεδεμένος αυτήν τη στιγμή σε αυτήν τη συσκευή δεν μπορεί να ενεργοποιήσει τον εντοπισμό σφαλμάτων USB. Για να χρησιμοποιήσετε αυτήν τη λειτουργία, κάντε εναλλαγή στον κύριο χρήστη."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Ζουμ σε πλήρη οθόνη"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Προβoλή σε πλήρη οθ."</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Αποθήκ. στιγμιότυπου οθόνης..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Μάθετε περισσότερα"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Έχετε συνδεθεί στην εφαρμογή <xliff:g id="VPN_APP">%1$s</xliff:g>, η οποία μπορεί να παρακολουθεί τη δραστηριότητα δικτύου σας, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστοτόπων."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Άνοιγμα Ρυθμίσεων VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Άνοιγμα αξιόπιστων διαπιστευτηρίων"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Ο διαχειριστής σας έχει ενεργοποιήσει την καταγραφή δικτύου, η οποία παρακολουθεί την επισκεψιμότητα στη συσκευή σας.\n\nΓια περισσότερες πληροφορίες, επικοινωνήστε με τον διαχειριστή σας."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Αυτή η εφαρμογή δεν διαθέτει κατηγορίες ειδοποιήσεων"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Οι ειδοποιήσεις από αυτήν την εφαρμογή δεν μπορούν να απενεργοποιηθούν"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 από <xliff:g id="NUMBER_1">%d</xliff:g> κατηγορίες ειδοποιήσεων από αυτή την εφαρμογή</item> - <item quantity="one">1 από <xliff:g id="NUMBER_0">%d</xliff:g> κατηγορία ειδοποιήσεων από αυτή την εφαρμογή</item> + <item quantity="other">1 από <xliff:g id="NUMBER_1">%s</xliff:g> κατηγορίες ειδοποιήσεων από αυτή την εφαρμογή</item> + <item quantity="one">1 από <xliff:g id="NUMBER_0">%s</xliff:g> κατηγορία ειδοποιήσεων από αυτή την εφαρμογή</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d λεπτό</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Χρήση της μπαταρίας"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Η εξοικονόμηση μπαταρίας δεν είναι διαθέσιμη κατά τη διάρκεια της φόρτισης"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Εξοικονόμηση μπαταρίας"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Η Εξοικονόμηση μπαταρίας δεν είναι διαθέσιμη κατά τη διάρκεια της φόρτισης"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Εξοικονόμηση μπαταρίας"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Μειώνει την απόδοση και τα δεδομένα παρασκηνίου"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Κουμπί <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Ελαχιστοποίηση"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Κλείσιμο"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Σύρετε προς τα κάτω για παράβλεψη"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Μενού λειτουργίας Picture in picture"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Μενού"</string> <string name="pip_notification_title" msgid="3204024940158161322">"Η λειτουργία picture-in-picture είναι ενεργή σε <xliff:g id="NAME">%s</xliff:g>."</string> <string name="pip_notification_message" msgid="5619512781514343311">"Εάν δεν θέλετε να χρησιμοποιείται αυτή η λειτουργία από την εφαρμογή <xliff:g id="NAME">%s</xliff:g>, πατήστε για να ανοίξετε τις ρυθμίσεις και απενεργοποιήστε την."</string> <string name="pip_play" msgid="1417176722760265888">"Αναπαραγωγή"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Μενού"</string> <string name="tuner_app" msgid="3507057938640108777">"Εφαρμογή <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Ειδοποιήσεις"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Μπαταρία"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Στιγμιότυπα οθόνης"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Γενικά μηνύματα"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Αποθηκευτικός χώρος"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Εφαρμογές που εκτελούνται στο παρασκήνιο"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Πατήστε για λεπτομέρειες σχετικά με τη χρήση μπαταρίας και δεδομένων"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Απενεργοποίηση δεδομένων κινητής τηλεφωνίας;"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Επειδή μια εφαρμογή αποκρύπτει ένα αίτημα άδειας, δεν είναι δυνατή η επαλήθευση της απάντησής σας από τις Ρυθμίσεις."</string> </resources> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index 6d0eebef2a4c..fe17a2d8bc0c 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"The computer\'s RSA key fingerprint is:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Always allow from this computer"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB debugging not allowed"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"The user currently signed in to this device can\'t turn on USB debugging. To use this feature, switch to the primary user."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zoom to fill screen"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Stretch to fill screen"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Saving screenshot…"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Find out more"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"You\'re connected to <xliff:g id="VPN_APP">%1$s</xliff:g>, which can monitor your network activity, including emails, apps and websites."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Open VPN settings"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Open trusted credentials"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Your admin has turned on network logging, which monitors traffic on your device.\n\nFor more information, contact your admin."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"This app doesn\'t have notification categories"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Notifications from this app can\'t be turned off"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 out of <xliff:g id="NUMBER_1">%d</xliff:g> notification categories from this app</item> - <item quantity="one">1 out of <xliff:g id="NUMBER_0">%d</xliff:g> notification category from this app</item> + <item quantity="other">1 out of <xliff:g id="NUMBER_1">%s</xliff:g> notification categories from this app</item> + <item quantity="one">1 out of <xliff:g id="NUMBER_0">%s</xliff:g> notification category from this app</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d minute</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Battery usage"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Battery Saver not available during charging"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Battery Saver"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Battery Saver not available during charging"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Battery Saver"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduces performance and background data"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Button <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimise"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Close"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Drag down to dismiss"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Picture in picture menu"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string> <string name="pip_notification_message" msgid="5619512781514343311">"If you don\'t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string> <string name="pip_play" msgid="1417176722760265888">"Play"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menu"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> app"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Battery"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string> <string name="notification_channel_general" msgid="4525309436693914482">"General Messages"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Apps running in background"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Tap for details on battery and data usage"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Turn off mobile data?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Because an app is obscuring a permission request, Settings can’t verify your response."</string> </resources> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index eb01ff688ae3..1ff0ee402a27 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"The computer\'s RSA key fingerprint is:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Always allow from this computer"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB debugging not allowed"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"The user currently signed in to this device can\'t turn on USB debugging. To use this feature, switch to the primary user."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zoom to fill screen"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Stretch to fill screen"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Saving screenshot…"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Find out more"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"You\'re connected to <xliff:g id="VPN_APP">%1$s</xliff:g>, which can monitor your network activity, including emails, apps and websites."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Open VPN settings"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Open trusted credentials"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Your admin has turned on network logging, which monitors traffic on your device.\n\nFor more information, contact your admin."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"This app doesn\'t have notification categories"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Notifications from this app can\'t be turned off"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 out of <xliff:g id="NUMBER_1">%d</xliff:g> notification categories from this app</item> - <item quantity="one">1 out of <xliff:g id="NUMBER_0">%d</xliff:g> notification category from this app</item> + <item quantity="other">1 out of <xliff:g id="NUMBER_1">%s</xliff:g> notification categories from this app</item> + <item quantity="one">1 out of <xliff:g id="NUMBER_0">%s</xliff:g> notification category from this app</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d minute</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Battery usage"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Battery Saver not available during charging"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Battery Saver"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Battery Saver not available during charging"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Battery Saver"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduces performance and background data"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Button <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimise"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Close"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Drag down to dismiss"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Picture in picture menu"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string> <string name="pip_notification_message" msgid="5619512781514343311">"If you don\'t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string> <string name="pip_play" msgid="1417176722760265888">"Play"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menu"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> app"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Battery"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string> <string name="notification_channel_general" msgid="4525309436693914482">"General Messages"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Apps running in background"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Tap for details on battery and data usage"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Turn off mobile data?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Because an app is obscuring a permission request, Settings can’t verify your response."</string> </resources> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 6d0eebef2a4c..fe17a2d8bc0c 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"The computer\'s RSA key fingerprint is:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Always allow from this computer"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB debugging not allowed"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"The user currently signed in to this device can\'t turn on USB debugging. To use this feature, switch to the primary user."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zoom to fill screen"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Stretch to fill screen"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Saving screenshot…"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Find out more"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"You\'re connected to <xliff:g id="VPN_APP">%1$s</xliff:g>, which can monitor your network activity, including emails, apps and websites."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Open VPN settings"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Open trusted credentials"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Your admin has turned on network logging, which monitors traffic on your device.\n\nFor more information, contact your admin."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"This app doesn\'t have notification categories"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Notifications from this app can\'t be turned off"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 out of <xliff:g id="NUMBER_1">%d</xliff:g> notification categories from this app</item> - <item quantity="one">1 out of <xliff:g id="NUMBER_0">%d</xliff:g> notification category from this app</item> + <item quantity="other">1 out of <xliff:g id="NUMBER_1">%s</xliff:g> notification categories from this app</item> + <item quantity="one">1 out of <xliff:g id="NUMBER_0">%s</xliff:g> notification category from this app</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d minute</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Battery usage"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Battery Saver not available during charging"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Battery Saver"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Battery Saver not available during charging"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Battery Saver"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduces performance and background data"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Button <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimise"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Close"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Drag down to dismiss"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Picture in picture menu"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string> <string name="pip_notification_message" msgid="5619512781514343311">"If you don\'t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string> <string name="pip_play" msgid="1417176722760265888">"Play"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menu"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> app"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Battery"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string> <string name="notification_channel_general" msgid="4525309436693914482">"General Messages"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Apps running in background"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Tap for details on battery and data usage"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Turn off mobile data?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Because an app is obscuring a permission request, Settings can’t verify your response."</string> </resources> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 6d0eebef2a4c..fe17a2d8bc0c 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"The computer\'s RSA key fingerprint is:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Always allow from this computer"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB debugging not allowed"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"The user currently signed in to this device can\'t turn on USB debugging. To use this feature, switch to the primary user."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zoom to fill screen"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Stretch to fill screen"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Saving screenshot…"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Find out more"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"You\'re connected to <xliff:g id="VPN_APP">%1$s</xliff:g>, which can monitor your network activity, including emails, apps and websites."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Open VPN settings"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Open trusted credentials"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Your admin has turned on network logging, which monitors traffic on your device.\n\nFor more information, contact your admin."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"This app doesn\'t have notification categories"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Notifications from this app can\'t be turned off"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 out of <xliff:g id="NUMBER_1">%d</xliff:g> notification categories from this app</item> - <item quantity="one">1 out of <xliff:g id="NUMBER_0">%d</xliff:g> notification category from this app</item> + <item quantity="other">1 out of <xliff:g id="NUMBER_1">%s</xliff:g> notification categories from this app</item> + <item quantity="one">1 out of <xliff:g id="NUMBER_0">%s</xliff:g> notification category from this app</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d minute</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Battery usage"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Battery Saver not available during charging"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Battery Saver"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Battery Saver not available during charging"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Battery Saver"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduces performance and background data"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Button <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimise"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Close"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Drag down to dismiss"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Picture in picture menu"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string> <string name="pip_notification_message" msgid="5619512781514343311">"If you don\'t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string> <string name="pip_play" msgid="1417176722760265888">"Play"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menu"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> app"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Battery"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string> <string name="notification_channel_general" msgid="4525309436693914482">"General Messages"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Apps running in background"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Tap for details on battery and data usage"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Turn off mobile data?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Because an app is obscuring a permission request, Settings can’t verify your response."</string> </resources> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index 27980eedfbfd..39af7ec7550a 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -556,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"This app doesn\'t have notification categories"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Notifications from this app can\'t be turned off"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 out of <xliff:g id="NUMBER_1">%d</xliff:g> notification categories from this app</item> - <item quantity="one">1 out of <xliff:g id="NUMBER_0">%d</xliff:g> notification category from this app</item> + <item quantity="other">1 out of <xliff:g id="NUMBER_1">%s</xliff:g> notification categories from this app</item> + <item quantity="one">1 out of <xliff:g id="NUMBER_0">%s</xliff:g> notification category from this app</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -585,8 +585,8 @@ <item quantity="one">%d minute</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Battery usage"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Battery Saver not available during charging"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Battery Saver"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Battery saver not available during charging"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Battery saver"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduces performance and background data"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Button <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -726,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimize"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Close"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Drag down to dismiss"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Picture in picture menu"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string> <string name="pip_notification_message" msgid="5619512781514343311">"If you don\'t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string> <string name="pip_play" msgid="1417176722760265888">"Play"</string> @@ -775,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Apps running in background"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Tap for details on battery and data usage"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Turn off mobile data?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Because an app is obscuring a permission request, Settings can’t verify your response."</string> </resources> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index b7e0f72fef0f..8db0a9961453 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"La huella digital de tu clave RSA es:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Permitir siempre desde esta computadora"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"No tienes permitida la depuración por USB"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"El usuario al que accediste en este dispositivo no puede activar la depuración por USB. Para usar esta función, debes cambiar al usuario principal."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zoom para ocupar la pantalla"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Estirar p/ ocupar la pantalla"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Guardando captura de pantalla"</string> @@ -459,8 +458,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Más información"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Estás conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>, que puede controlar la actividad de tu red, incluidos los correos electrónicos, las apps y los sitios web."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Abrir configuración de VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Abrir credenciales de confianza"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Tu administrador activó el registro de red, que controla el tráfico en tu dispositivo.\n\nComunícate con él para obtener más información."</string> @@ -560,8 +558,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Esta app no tiene categorías de notificación"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"No es posible desactivar las notificaciones de esta app"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 de <xliff:g id="NUMBER_1">%d</xliff:g> categorías de notificación de esta app</item> - <item quantity="one">1 de <xliff:g id="NUMBER_0">%d</xliff:g> categoría de notificación de esta app</item> + <item quantity="other">1 de <xliff:g id="NUMBER_1">%s</xliff:g> categorías de notificación de esta app</item> + <item quantity="one">1 de <xliff:g id="NUMBER_0">%s</xliff:g> categoría de notificación de esta app</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -589,8 +587,8 @@ <item quantity="one">%d minuto</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Uso de la batería"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Ahorro de batería no está disponible durante la carga"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Ahorro de batería"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"El Ahorro de batería no está disponible durante la carga"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Ahorro de batería"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduce el rendimiento y el uso de datos en segundo plano"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Botón <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Página principal"</string> @@ -730,7 +728,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Cerrar"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arrastra hacia abajo para descartar"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Menú de Imagen en imagen"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menú"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> está en modo de imagen en imagen"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Si no quieres que <xliff:g id="NAME">%s</xliff:g> use esta función, presiona para abrir la configuración y desactivarla."</string> <string name="pip_play" msgid="1417176722760265888">"Reproducir"</string> @@ -758,8 +756,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menú"</string> <string name="tuner_app" msgid="3507057938640108777">"App de <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Batería"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de pantalla"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Mensajes generales"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Almacenamiento"</string> @@ -780,4 +777,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Apps que se ejecutan en segundo plano"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Presiona para obtener información sobre el uso de datos y de la batería"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"¿Deseas desactivar los datos móviles?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Como una app está bloqueando una solicitud de permiso, Configuración no puede verificar tu respuesta."</string> </resources> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 0a24d92cc050..0ce8e9a9285c 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -34,14 +34,14 @@ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificaciones"</string> <string name="battery_low_title" msgid="6456385927409742437">"Nivel de batería bajo"</string> <string name="battery_low_percent_format" msgid="2900940511201380775">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> de batería"</string> - <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> de batería. La función de ahorro de energía está activada."</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> de batería. La función de ahorro de batería está activada."</string> <string name="invalid_charger" msgid="4549105996740522523">"No se admite la carga por USB.\nUtiliza solo el cargador proporcionado."</string> <string name="invalid_charger_title" msgid="3515740382572798460">"No se admite la carga por USB."</string> <string name="invalid_charger_text" msgid="5474997287953892710">"Utiliza solo el cargador proporcionado."</string> <string name="battery_low_why" msgid="4553600287639198111">"Ajustes"</string> <string name="battery_saver_confirmation_title" msgid="5299585433050361634">"¿Activar ahorro de batería?"</string> <string name="battery_saver_confirmation_ok" msgid="7507968430447930257">"Activar"</string> - <string name="battery_saver_start_action" msgid="5576697451677486320">"Activar ahorro de energía"</string> + <string name="battery_saver_start_action" msgid="5576697451677486320">"Activar ahorro de batería"</string> <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Ajustes"</string> <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string> <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Girar pantalla automáticamente"</string> @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"La huella digital de tu clave RSA es:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Permitir siempre desde este ordenador"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Depuración USB no permitida"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"El usuario con el que se ha iniciado sesión en este dispositivo no puede activar la depuración USB. Para utilizar esta función, inicia sesión con la cuenta de usuario principal."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zoom para ajustar"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Expandir para ajustar"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Guardando captura..."</string> @@ -459,8 +458,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Más información"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Te has conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>, que puede controlar tu actividad de red, como los correos electrónicos, las aplicaciones y los sitios web."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Abrir ajustes de VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Abrir credenciales de confianza"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Tu administrador ha activado el registro de la red para supervisar el tráfico en tu dispositivo.\n\nPonte en contacto con él para obtener más información."</string> @@ -560,8 +558,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Esta aplicación no tiene categorías de notificación"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"No se pueden desactivar las notificaciones de esta aplicación"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 de <xliff:g id="NUMBER_1">%d</xliff:g> categorías de notificación de esta aplicación</item> - <item quantity="one">1 de <xliff:g id="NUMBER_0">%d</xliff:g> categoría de notificación de esta aplicación</item> + <item quantity="other">1 de <xliff:g id="NUMBER_1">%s</xliff:g> categorías de notificación de esta aplicación</item> + <item quantity="one">1 de <xliff:g id="NUMBER_0">%s</xliff:g> categoría de notificación de esta aplicación</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -589,8 +587,8 @@ <item quantity="one">%d minuto</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Uso de la batería"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Ahorro de batería no disponible mientras se carga el dispositivo"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Ahorro de batería"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"La función Ahorro de batería no está disponible mientras se carga el dispositivo"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Ahorro de batería"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduce el rendimiento y los datos en segundo plano"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Botón <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Inicio"</string> @@ -730,7 +728,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Cerrar"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arrastra hacia abajo para ignorar"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Menú del modo Imagen en imagen"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menú"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> está en imagen en imagen"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Si no quieres que <xliff:g id="NAME">%s</xliff:g> utilice esta función, toca la notificación para abrir los ajustes y desactivarla."</string> <string name="pip_play" msgid="1417176722760265888">"Reproducir"</string> @@ -758,8 +756,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menú"</string> <string name="tuner_app" msgid="3507057938640108777">"Aplicación <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Batería"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de pantalla"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Mensajes generales"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Almacenamiento"</string> @@ -780,4 +777,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Aplicaciones que se están ejecutando en segundo plano"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Toca para ver información detallada sobre el uso de datos y de la batería"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"¿Desactivar los datos móviles?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Una aplicación está bloqueando una solicitud de permiso, por lo que Ajustes no puede verificar tu respuesta."</string> </resources> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index 0ef25323cb07..efb83655b46d 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Arvuti RSA-võtme sõrmejälg:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Luba alati sellest arvutist"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB-silumine pole lubatud"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Sellesse seadmesse praegu sisse logitud kasutaja ei saa USB-silumist sisse lülitada. Selle funktsiooni kasutamiseks vahetage peamisele kasutajale."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Suumi ekraani täitmiseks"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Venita ekraani täitmiseks"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Kuvatõmmise salvestamine ..."</string> @@ -459,8 +458,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Lisateave"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Olete ühendatud rakendusega <xliff:g id="VPN_APP">%1$s</xliff:g>, mis saab jälgida teie võrgutegevusi, sh meile, rakendusi ja veebisaite."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN-i seadete avamine"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Ava usaldusväärsed mandaadid"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Teie administraator on sisse lülitanud võrgu logimise funktsiooni, mis jälgib teie seadmes liiklust.\n\nLisateabe saamiseks võtke ühendust administraatoriga."</string> @@ -560,8 +558,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Sellel rakendusel ei ole märguannete kategooriaid"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Selle rakenduse märguandeid ei saa välja lülitada"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 <xliff:g id="NUMBER_1">%d</xliff:g>-st märguannete kategooriast sellelt rakenduselt</item> - <item quantity="one">1 <xliff:g id="NUMBER_0">%d</xliff:g>-st märguannete kategooriast sellelt rakenduselt</item> + <item quantity="other">1 <xliff:g id="NUMBER_1">%s</xliff:g>-st märguannete kategooriast sellelt rakenduselt</item> + <item quantity="one">1 <xliff:g id="NUMBER_0">%s</xliff:g>-st märguannete kategooriast sellelt rakenduselt</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -589,8 +587,8 @@ <item quantity="one">%d minut</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Akukasutus"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Akusäästja pole laadimise ajal saadaval"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Akusäästja"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Akusäästja pole laadimise ajal saadaval"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Akusäästja"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Vähendab jõudlust ja taustaandmeid"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Nupp <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Avaekraan"</string> @@ -730,7 +728,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimeeri"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Sule"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Loobumiseks lohistage alla"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Menüü Pilt pildis"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menüü"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> on režiimis Pilt pildis"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Kui te ei soovi, et rakendus <xliff:g id="NAME">%s</xliff:g> seda funktsiooni kasutaks, puudutage seadete avamiseks ja lülitage see välja."</string> <string name="pip_play" msgid="1417176722760265888">"Esita"</string> @@ -758,8 +756,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menüü"</string> <string name="tuner_app" msgid="3507057938640108777">"Rakendus <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Teatised"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Aku"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Ekraanipildid"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Üldised sõnumid"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Salvestusruum"</string> @@ -780,4 +777,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Rakendusi käitatakse taustal"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Aku ja andmekasutuse üksikasjade nägemiseks puudutage"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Kas lülitada mobiilne andmeside välja?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Seaded ei saa teie vastust kinnitada, sest rakendus varjab loataotlust."</string> </resources> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index ebbdf87c568e..b922f1a4ce55 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Ordenagailuaren RSA gakoaren hatz-marka hau da:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Onartu beti ordenagailu honetatik"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Ez da onartzen USB arazketa"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Gailu honetan saioa hasita duen erabiltzaileak ezin du aktibatu USB arazketa. Eginbide hori erabiltzeko, aldatu erabiltzaile nagusira."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Handiagotu pantaila betetzeko"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Luzatu pantaila betetzeko"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Pantaila-argazkia gordetzen…"</string> @@ -459,8 +458,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Informazio gehiago"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"<xliff:g id="VPN_APP">%1$s</xliff:g> aplikaziora konektatuta zaude eta hark sareko jarduerak gainbegira ditzake, mezu elektronikoak, aplikazioak eta webguneak barne."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Ireki VPN ezarpenak"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Ireki kredentzial fidagarriak"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administratzaileak sare-erregistroak aktibatu ditu; horrela, zure gailuko trafikoa gainbegira dezake.\n\nInformazio gehiago lortzeko, jarri administratzailearekin harremanetan."</string> @@ -560,8 +558,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Aplikazio honek ez du jakinarazpen-kategoriarik"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Ezin dira desaktibatu aplikazio honen jakinarazpenak"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">Aplikazio honen 1/<xliff:g id="NUMBER_1">%d</xliff:g> jakinarazpen-kategoria</item> - <item quantity="one">Aplikazio honen 1/<xliff:g id="NUMBER_0">%d</xliff:g> jakinarazpen-kategoria</item> + <item quantity="other">Aplikazio honen 1/<xliff:g id="NUMBER_1">%s</xliff:g> jakinarazpen-kategoria</item> + <item quantity="one">Aplikazio honen 1/<xliff:g id="NUMBER_0">%s</xliff:g> jakinarazpen-kategoria</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -589,8 +587,8 @@ <item quantity="one">%d minutu</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Bateriaren erabilera"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Bateria-aurrezlea ez dago erabilgarri gailua kargatzen ari denean"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Bateria-aurrezlea"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Bateria-aurrezlea ez dago erabilgarri gailua kargatzen ari denean"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Bateria-aurrezlea"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Errendimendua eta atzeko planoko datuen erabilera murrizten ditu"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g> botoia"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Hasiera"</string> @@ -730,7 +728,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizatu"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Itxi"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Baztertzeko, arrastatu behera"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Pantaila txiki gainjarriaren menua"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menua"</string> <string name="pip_notification_title" msgid="3204024940158161322">"Pantaila txiki gainjarrian dago <xliff:g id="NAME">%s</xliff:g>"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Ez baduzu nahi <xliff:g id="NAME">%s</xliff:g> zerbitzuak eginbide hori erabiltzea, sakatu hau ezarpenak ireki eta aukera desaktibatzeko."</string> <string name="pip_play" msgid="1417176722760265888">"Erreproduzitu"</string> @@ -758,8 +756,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menua"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> aplikazioa"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Abisuak"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Bateria"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Pantaila-argazkiak"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Mezu orokorrak"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Memoria"</string> @@ -780,4 +777,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Aplikazioak exekutatzen ari dira atzeko planoan"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Sakatu bateria eta datuen erabilerari buruzko xehetasunak ikusteko"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Datu-konexioa desaktibatu nahi duzu?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Aplikazio bat baimen-eskaera oztopatzen ari denez, ezarpenek ezin dute egiaztatu erantzuna."</string> </resources> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 58a5946ba70e..b3e1b4ec8239 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"اثر انگشت کلید RSA رایانه: \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"همیشه از این رایانه انجام شود"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"اشکالزدایی USB مجاز نیست"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"کاربری که درحال حاضر در این دستگاه وارد سیستم شده است نمیتواند اشکالزدایی USB را روشن کند. برای استفاده از این قابلیت، به کاربر اصلی تغییر وضعیت دهید."</string> <string name="compat_mode_on" msgid="6623839244840638213">"بزرگنمایی برای پر کردن صفحه"</string> <string name="compat_mode_off" msgid="4434467572461327898">"گسترده کردن برای پر کردن صفحه"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"در حال ذخیره عکس صفحهنمایش..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"بیشتر بدانید"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"به <xliff:g id="VPN_APP">%1$s</xliff:g> وصل شدهاید، که میتواند فعالیت شبکه شما را (ازجمله رایانامهها، برنامهها و وبسایتها) کنترل کند."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"باز کردن تنظیمات VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"باز کردن اعتبارنامه مورداعتماد"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"سرپرست سیستم شما گزارشگیری شبکه را (که بر ترافیک دستگاهتان نظارت میکند) روشن کرده است.\n\nبرای اطلاعات بیشتر، با سرپرست خود تماس بگیرید."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"این برنامه دسته اعلان ندارد"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"نمیتوان اعلانهای این برنامه را خاموش کرد"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">۱ از <xliff:g id="NUMBER_1">%d</xliff:g> دسته اعلان این برنامه</item> - <item quantity="other">۱ از <xliff:g id="NUMBER_1">%d</xliff:g> دسته اعلان این برنامه</item> + <item quantity="one">۱ از <xliff:g id="NUMBER_1">%s</xliff:g> دسته اعلان این برنامه</item> + <item quantity="other">۱ از <xliff:g id="NUMBER_1">%s</xliff:g> دسته اعلان این برنامه</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>، <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="other">%d دقیقه</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"مصرف باتری"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"هنگام شارژ شدن، «بهینهسازی باتری» در دسترس نیست"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"بهینهسازی باتری"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"«بهینهسازی باتری» در هنگام شارژ شدن در دسترس نیست"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"بهینهسازی باتری"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"عملکرد و اطلاعات پسزمینه را کاهش میدهد"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"دکمه <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"ابتدا"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"کوچک کردن"</string> <string name="pip_phone_close" msgid="8416647892889710330">"بستن"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"برای نپذیرفتن، به پایین بکشید"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"منوی تصویر در تصویر"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"منو"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> درحالت تصویر در تصویر است"</string> <string name="pip_notification_message" msgid="5619512781514343311">"اگر نمیخواهید <xliff:g id="NAME">%s</xliff:g> از این قابلیت استفاده کند، با ضربه زدن، تنظیمات را باز کنید و آن را خاموش کنید."</string> <string name="pip_play" msgid="1417176722760265888">"پخش"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"منو"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> برنامه"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"هشدارها"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"باتری"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"عکسهای صفحهنمایش"</string> <string name="notification_channel_general" msgid="4525309436693914482">"پیامهای عمومی"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"فضای ذخیرهسازی"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"برنامههایی که در پسزمینه اجرا میشوند"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"برای جزئیات مربوط به مصرف باتری و داده، ضربه بزنید"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"داده شبکه تلفن همراه خاموش شود؟"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"چون برنامهای درحال ایجاد تداخل در درخواست مجوز است، «تنظیمات» نمیتواند پاسخ شما را تأیید کند."</string> </resources> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 3469a23cc518..61f03b56aa09 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Tietokoneen RSA-avaintunnistetiedosto on:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Salli aina tällä tietokoneella"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB-vianetsintää ei sallita"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Laitteelle tällä hetkellä kirjautunut käyttäjä ei voi ottaa USB-vianetsintää käyttöön. Vaihda käyttäjäksi ensisijainen käyttäjä, jotta voit käyttää tätä ominaisuutta."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zoomaa koko näyttöön"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Venytä koko näyttöön"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Tallennetaan kuvakaappausta..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Lisätietoja"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Olet yhteydessä sovellukseen <xliff:g id="VPN_APP">%1$s</xliff:g>, joka voi valvoa verkkotoimintaasi, esimerkiksi sähköposteja, sovelluksia ja verkkosivustoja."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Avaa VPN-asetukset"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Avaa luotetut todennustiedot"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Järjestelmänvalvoja on ottanut käyttöön verkkolokitietojen tallentamisen. Sen avulla seurataan laitteellasi tapahtuvaa liikennettä.\n\nPyydä lisätietoja järjestelmänvalvojalta."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Tällä sovelluksella ei ole ilmoitusluokkia."</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Tämän sovelluksen ilmoituksia ei voi poistaa käytöstä."</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">Tämä sovellus: 1/<xliff:g id="NUMBER_1">%d</xliff:g> ilmoitusluokkaa</item> - <item quantity="one">Tämä sovellus: 1/<xliff:g id="NUMBER_0">%d</xliff:g> ilmoitusluokkaa</item> + <item quantity="other">Tämä sovellus: 1/<xliff:g id="NUMBER_1">%s</xliff:g> ilmoitusluokkaa</item> + <item quantity="one">Tämä sovellus: 1/<xliff:g id="NUMBER_0">%s</xliff:g> ilmoitusluokkaa</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d minuutti</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Akun käyttö"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Virransäästö ei ole käytettävissä latauksen aikana."</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Virransäästö"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Virransäästö ei ole käytettävissä latauksen aikana."</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Virransäästö"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Rajoittaa suorituskykyä ja taustatiedonsiirtoa."</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Painike <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Pienennä"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Sulje"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Hylkää vetämällä alas."</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Kuva kuvassa ‑valikko"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Valikko"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> on kuva kuvassa ‑tilassa"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Jos et halua, että <xliff:g id="NAME">%s</xliff:g> voi käyttää tätä ominaisuutta, avaa asetukset napauttamalla ja poista se käytöstä."</string> <string name="pip_play" msgid="1417176722760265888">"Toista"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Valikko"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> sovellus"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Ilmoitukset"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Akku"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Kuvakaappaukset"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Yleiset viestit"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Tallennustila"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Sovelluksia käynnissä taustalla"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Katso lisätietoja akun ja datan käytöstä napauttamalla"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Poistetaanko mobiilidata käytöstä?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Sovellus peittää käyttöoikeuspyynnön, joten Asetukset ei voi vahvistaa valintaasi."</string> </resources> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index a4f5712af523..8c384f3caf6b 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Empreinte numérique de la clé RSA de l\'ordinateur : \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Toujours autoriser sur cet ordinateur"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Débogage USB non autorisé"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"L\'utilisateur actuellement connecté sur cet appareil ne peut pas activer le débogage USB. Pour utiliser cette fonctionnalité, l\'utilisateur principal doit se connecter."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zoomer pour remplir l\'écran"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Étirer pour remplir l\'écran"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Enregistrement capture écran…"</string> @@ -270,8 +269,8 @@ <string name="start_dreams" msgid="5640361424498338327">"Écran de veille"</string> <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Ne pas déranger"</string> - <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Priorités seulement"</string> - <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"Alarmes uniquement"</string> + <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Prioritaires seulement"</string> + <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"Alarmes seulement"</string> <string name="quick_settings_dnd_none_label" msgid="5025477807123029478">"Aucune interruption"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> appareils)"</string> @@ -373,7 +372,7 @@ <string name="interruption_level_none_with_warning" msgid="5114872171614161084">"Aucune interruption : le son des lecteurs d\'écran sera également désactivé."</string> <string name="interruption_level_none" msgid="6000083681244492992">"Aucune interruption"</string> <string name="interruption_level_priority" msgid="6426766465363855505">"Priorités seulement"</string> - <string name="interruption_level_alarms" msgid="5226306993448328896">"Alarmes uniquement"</string> + <string name="interruption_level_alarms" msgid="5226306993448328896">"Alarmes seulement"</string> <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Aucune\ninterruption"</string> <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priorités\nuniquement"</string> <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarmes\nuniquement"</string> @@ -459,8 +458,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"En savoir plus"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Vous êtes connecté à <xliff:g id="VPN_APP">%1$s</xliff:g>, qui peut contrôler votre activité réseau, y compris les courriels, les applications et les sites Web."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Ouvrir les paramètres RPV"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Ouvrir les authentifiants de confiance"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Votre administrateur a activé la journalisation réseau, qui surveille le trafic sur votre appareil.\n\nPour en savoir plus, communiquez avec lui."</string> @@ -560,8 +558,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Cette application n\'a pas de catégories de notification"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Les notifications de cette application ne peuvent pas être désactivées"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 catégorie de notification sur <xliff:g id="NUMBER_1">%d</xliff:g> provenant de cette application</item> - <item quantity="other">1 catégorie de notification sur <xliff:g id="NUMBER_1">%d</xliff:g> provenant de cette application</item> + <item quantity="one">1 catégorie de notification sur <xliff:g id="NUMBER_1">%s</xliff:g> provenant de cette application</item> + <item quantity="other">1 catégorie de notification sur <xliff:g id="NUMBER_1">%s</xliff:g> provenant de cette application</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -589,8 +587,8 @@ <item quantity="other">%d minutes</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Utilisation de la pile"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Le mode Économie d\'énergie n\'est pas accessible pendant la charge"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Économie d\'énergie"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Le mode Économie d\'énergie n\'est pas accessible pendant la recharge"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Économie d\'énergie"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Réduit les performances et les données en arrière-plan"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Bouton <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Accueil"</string> @@ -730,7 +728,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Réduire"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Fermer"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Faire glisser vers le bas pour ignorer"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Menu d\'incrustation d\'image"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> est en mode d\'incrustation d\'image"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Si vous ne voulez pas que <xliff:g id="NAME">%s</xliff:g> utilise cette fonctionnalité, touchez l\'écran pour ouvrir les paramètres, puis désactivez-la."</string> <string name="pip_play" msgid="1417176722760265888">"Lire"</string> @@ -758,8 +756,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menu"</string> <string name="tuner_app" msgid="3507057938640108777">"Application <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Pile"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Saisies d\'écran"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Messages généraux"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Stockage"</string> @@ -780,4 +777,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Applications qui fonctionnent en arrière-plan"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Touchez pour afficher des détails sur l\'utilisation de la pile et des données"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Désactiver les données cellulaires?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Une application obscurcit une demande d\'autorisation, alors Paramètres ne peut pas vérifier votre réponse."</string> </resources> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index cb8f6bcc5379..3e910721737b 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Empreinte numérique de la clé RSA de l\'ordinateur : \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Toujours autoriser sur cet ordinateur"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Débogage USB non autorisé"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"L\'utilisateur actuellement connecté sur cet appareil ne peut pas activer le débogage USB. Pour utiliser cette fonctionnalité, l\'utilisateur principal doit se connecter."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zoomer pour remplir l\'écran"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Étirer pour remplir l\'écran"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Enregistrement capture écran…"</string> @@ -459,8 +458,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"En savoir plus"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Vous êtes connecté à <xliff:g id="VPN_APP">%1$s</xliff:g>, qui peut contrôler votre activité sur le réseau, y compris les e-mails, les applications et les sites Web."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Ouvrir les paramètres VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Ouvrir les certificats de confiance"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Votre administrateur a activé la journalisation réseau, qui surveille le trafic sur votre appareil.\n\nPour en savoir plus, contactez-le."</string> @@ -560,8 +558,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Cette application n\'a pas de catégories de notification"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Impossible de désactiver les notifications de cette application"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 catégorie de notification sur <xliff:g id="NUMBER_1">%d</xliff:g> provenant de cette application</item> - <item quantity="other">1 catégorie de notification sur <xliff:g id="NUMBER_1">%d</xliff:g> provenant de cette application</item> + <item quantity="one">1 catégorie de notification sur <xliff:g id="NUMBER_1">%s</xliff:g> provenant de cette application</item> + <item quantity="other">1 catégorie de notification sur <xliff:g id="NUMBER_1">%s</xliff:g> provenant de cette application</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -589,8 +587,8 @@ <item quantity="other">%d minutes</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Utilisation batterie"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"L\'économiseur de batterie n\'est pas disponible lorsque l\'appareil est en charge."</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Économiseur de batterie"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"L\'économiseur de batterie n\'est pas disponible lorsque l\'appareil est en charge"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Économiseur de batterie"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Limite les performances et les données en arrière-plan."</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Bouton <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Accueil"</string> @@ -730,7 +728,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Réduire"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Fermer"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Faire glisser vers le bas pour ignorer"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Menu Picture-in-picture"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> est en mode Picture-in-picture"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Si vous ne voulez pas que l\'application <xliff:g id="NAME">%s</xliff:g> utilise cette fonctionnalité, appuyez ici pour ouvrir les paramètres et la désactiver."</string> <string name="pip_play" msgid="1417176722760265888">"Lecture"</string> @@ -758,8 +756,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menu"</string> <string name="tuner_app" msgid="3507057938640108777">"Application <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Batterie"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Captures d\'écran"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Nouveaux messages"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Espace de stockage"</string> @@ -780,4 +777,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Applications en cours d\'exécution en arrière-plan"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Appuyer pour obtenir des informations sur l\'utilisation de la batterie et des données"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Désactiver les données mobiles ?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"L\'application Paramètres ne peut pas valider votre réponse, car une application masque la demande d\'autorisation."</string> </resources> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index 01167e043c06..70ee57a159d6 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -43,7 +43,7 @@ <string name="battery_saver_confirmation_ok" msgid="7507968430447930257">"Activar"</string> <string name="battery_saver_start_action" msgid="5576697451677486320">"Activar o aforro de batería"</string> <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Configuración"</string> - <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string> + <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wifi"</string> <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Xirar pantalla automaticamente"</string> <string name="status_bar_settings_mute_label" msgid="554682549917429396">"APAGAR"</string> <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string> @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"A impresión dixital da clave de RSA do ordenador é:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Permitir sempre desde este ordenador"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Non se permite a depuración por USB"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"O usuario coa sesión iniciada actualmente neste dispositivo non pode activar a depuración por USB. Para utilizar esta función, cambia ao usuario principal."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Ampliar ata ocupar todo"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Estirar ata ocupar todo"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Gardando captura de pantalla…"</string> @@ -253,7 +252,7 @@ <string name="gps_notification_found_text" msgid="4619274244146446464">"Localización establecida polo GPS"</string> <string name="accessibility_location_active" msgid="2427290146138169014">"Solicitudes de localización activas"</string> <string name="accessibility_clear_all" msgid="5235938559247164925">"Eliminar todas as notificacións."</string> - <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string> + <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"<xliff:g id="NUMBER">%s</xliff:g> máis"</string> <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404"> <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> notificacións máis no grupo.</item> <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> notificación máis no grupo.</item> @@ -459,8 +458,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Máis información"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Estás conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode controlar a túa actividade na rede, mesmo os correos electrónicos, as aplicacións e os sitios web."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Abrir configuración da VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Abrir credenciais de confianza"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"O administrador activou o rexistro na rede, que controla o tráfico do teu dispositivo.\n\nPara obter máis información, contacta co administrador."</string> @@ -560,8 +558,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Esta aplicación non ten categorías de notificacións"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Non se poden desactivar as notificacións desta aplicación"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 de <xliff:g id="NUMBER_1">%d</xliff:g> categorías de notificacións desta aplicación</item> - <item quantity="one">1 de <xliff:g id="NUMBER_0">%d</xliff:g> categoría de notificación desta aplicación</item> + <item quantity="other">1 de <xliff:g id="NUMBER_1">%s</xliff:g> categorías de notificacións desta aplicación</item> + <item quantity="one">1 de <xliff:g id="NUMBER_0">%s</xliff:g> categoría de notificación desta aplicación</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -589,8 +587,8 @@ <item quantity="one">%d minuto</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Uso de batería"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"A función de aforro da batería non está dispoñible durante a carga"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Aforro de batería"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"A función Aforro de batería non está dispoñible durante a carga"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Aforro de batería"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduce o rendemento e os datos en segundo plano"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Botón <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Inicio"</string> @@ -624,7 +622,7 @@ <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Volver"</string> <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificacións"</string> <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Atallos de teclado"</string> - <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Cambiar de método de entrada"</string> + <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Cambiar de método de introdución"</string> <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicacións"</string> <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Asistente"</string> <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string> @@ -730,7 +728,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Pechar"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arrastra cara abaixo para ignorar"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Menú de pantalla superposta"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menú"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> está na pantalla superposta"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Se non queres que <xliff:g id="NAME">%s</xliff:g> utilice esta función, toca a configuración para abrir as opcións e desactivar a función."</string> <string name="pip_play" msgid="1417176722760265888">"Reproducir"</string> @@ -758,14 +756,13 @@ <string name="tuner_menu" msgid="191640047241552081">"Menú"</string> <string name="tuner_app" msgid="3507057938640108777">"Aplicación <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Batería"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de pantalla"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Mensaxes xerais"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Almacenamento"</string> <string name="instant_apps" msgid="6647570248119804907">"Aplicacións instantáneas"</string> <string name="instant_apps_message" msgid="8116608994995104836">"As aplicacións instantáneas non precisan instalación."</string> - <string name="app_info" msgid="6856026610594615344">"Información de aplicacións"</string> + <string name="app_info" msgid="6856026610594615344">"Info. da aplicación"</string> <string name="go_to_web" msgid="1106022723459948514">"Acceder á web"</string> <string name="mobile_data" msgid="7094582042819250762">"Datos móbiles"</string> <string name="wifi_is_off" msgid="1838559392210456893">"A wifi está desactivada"</string> @@ -780,4 +777,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Aplicacións que se executan en segundo plano"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Toca para obter información sobre o uso de datos e a batería"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Queres desactivar os datos móbiles?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Dado que unha aplicación se superpón sobre unha solicitude de permiso, a configuración non pode verificar a túa resposta."</string> </resources> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 70b108cfb1d4..431f75c269a7 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -43,12 +43,12 @@ <string name="battery_saver_confirmation_ok" msgid="7507968430447930257">"ચાલુ કરો"</string> <string name="battery_saver_start_action" msgid="5576697451677486320">"બૅટરી સેવર ચાલુ કરો"</string> <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"સેટિંગ્સ"</string> - <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string> + <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"વાઇ-ફાઇ"</string> <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"સ્ક્રીનને આપમેળે ફેરવો"</string> <string name="status_bar_settings_mute_label" msgid="554682549917429396">"મ્યૂટ કરો"</string> <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"સ્વતઃ"</string> <string name="status_bar_settings_notifications" msgid="397146176280905137">"સૂચનાઓ"</string> - <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth ટિથર કર્યું"</string> + <string name="bluetooth_tethered" msgid="7094101612161133267">"બ્લૂટૂથ ટિથર કર્યું"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ઇનપુટ પદ્ધતિઓ સેટ કરો"</string> <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ભૌતિક કીબોર્ડ"</string> <string name="usb_device_permission_prompt" msgid="834698001271562057">"<xliff:g id="APPLICATION">%1$s</xliff:g> એપ્લિકેશનને USB ઉપકરણ અૅક્સેસ કરવાની મંજૂરી આપીએ?"</string> @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"કમ્પ્યુટરની RSA મુખ્ય ફિંગરપ્રિંટ આ છે:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"હંમેશા આ કમ્પ્યુટરથી મંજૂરી આપો"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB ડીબગિંગની મંજૂરી નથી"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"હાલમાં આ ઉપકરણમાં સાઇન ઇન થયેલ વપરાશકર્તા USB ડિબગીંગ ચાલુ કરી શકતા નથી. આ સુવિધાનો ઉપયોગ કરવા માટે પ્રાથમિક વપરાશકર્તા પર સ્વિચ કરો."</string> <string name="compat_mode_on" msgid="6623839244840638213">"સ્ક્રીન ભરવા માટે ઝૂમ કરો"</string> <string name="compat_mode_off" msgid="4434467572461327898">"સ્ક્રીન ભરવા માટે ખેંચો"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"સ્ક્રીનશોટ સાચવી રહ્યું છે…"</string> @@ -101,7 +100,7 @@ <string name="cancel" msgid="6442560571259935130">"રદ કરો"</string> <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"સુસંગતતા ઝૂમ બટન."</string> <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"નાનીથી મોટી સ્ક્રીન પર ઝૂમ કરો."</string> - <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth કનેક્ટ થયું."</string> + <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"બ્લૂટૂથ કનેક્ટ થયું."</string> <string name="accessibility_bluetooth_disconnected" msgid="7416648669976870175">"બ્લૂટૂથ ડિસ્કનેક્ટ થયું."</string> <string name="accessibility_no_battery" msgid="358343022352820946">"બૅટરી નથી."</string> <string name="accessibility_battery_one_bar" msgid="7774887721891057523">"બૅટરી એક બાર."</string> @@ -151,12 +150,12 @@ <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string> <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"રોમિંગ"</string> <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string> - <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string> + <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"વાઇ-ફાઇ"</string> <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM નથી."</string> <string name="accessibility_cell_data" msgid="5326139158682385073">"મોબાઇલ ડેટા"</string> <string name="accessibility_cell_data_on" msgid="5927098403452994422">"મોબાઇલ ડેટા ચાલુ છે"</string> <string name="accessibility_cell_data_off" msgid="443267573897409704">"મોબાઇલ ડેટા બંધ છે"</string> - <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth ટિથરિંગ."</string> + <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"બ્લૂટૂથ ટિથરિંગ."</string> <string name="accessibility_airplane_mode" msgid="834748999790763092">"એરપ્લેન મોડ."</string> <string name="accessibility_vpn_on" msgid="5993385083262856059">"VPN ચાલુ છે."</string> <string name="accessibility_no_sims" msgid="3957997018324995781">"કોઈ સિમ કાર્ડ નથી."</string> @@ -206,13 +205,13 @@ <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"ખલેલ પાડશો નહીં બંધ."</string> <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"ખલેલ પાડશો નહીં બંધ કર્યું."</string> <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"ખલેલ પાડશો નહીં ચાલુ કર્યું."</string> - <string name="accessibility_quick_settings_bluetooth" msgid="6341675755803320038">"Bluetooth."</string> - <string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"Bluetooth બંધ."</string> - <string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"Bluetooth ચાલુ."</string> - <string name="accessibility_quick_settings_bluetooth_connecting" msgid="6953242966685343855">"Bluetooth કનેક્ટ કરી રહ્યું છે."</string> - <string name="accessibility_quick_settings_bluetooth_connected" msgid="4306637793614573659">"Bluetooth કનેક્ટ થયું."</string> - <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="2730003763480934529">"Bluetooth બંધ કરી."</string> - <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="8722351798763206577">"Bluetooth ચાલુ કર્યું."</string> + <string name="accessibility_quick_settings_bluetooth" msgid="6341675755803320038">"બ્લૂટૂથ."</string> + <string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"બ્લૂટૂથ બંધ."</string> + <string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"બ્લૂટૂથ ચાલુ."</string> + <string name="accessibility_quick_settings_bluetooth_connecting" msgid="6953242966685343855">"બ્લૂટૂથ કનેક્ટ કરી રહ્યું છે."</string> + <string name="accessibility_quick_settings_bluetooth_connected" msgid="4306637793614573659">"બ્લૂટૂથ કનેક્ટ થયું."</string> + <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="2730003763480934529">"બ્લૂટૂથ બંધ કરી."</string> + <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="8722351798763206577">"બ્લૂટૂથ ચાલુ કર્યું."</string> <string name="accessibility_quick_settings_location_off" msgid="5119080556976115520">"સ્થાનની જાણ કરવી બંધ."</string> <string name="accessibility_quick_settings_location_on" msgid="5809937096590102036">"સ્થાનની જાણ કરવી ચાલુ."</string> <string name="accessibility_quick_settings_location_changed_off" msgid="8526845571503387376">"સ્થાનની જાણ કરવી બંધ કર્યું."</string> @@ -246,7 +245,7 @@ <string name="data_usage_disabled_dialog" msgid="4919541636934603816">"તમે સેટ કરેલી ડેટા મર્યાદા પહોંચી ગઇ છે. તમે હવે મોબાઇલ ડેટાનો ઉપયોગ નથી કરી રહ્યાં.\n\nજો હવે તમે ફરી શરૂ કરો, તો ડેટા વપરાશ માટે શુલ્ક લાગુ થઇ શકે છે."</string> <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"ફરી શરૂ કરો"</string> <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"કોઈ ઇન્ટરનેટ કનેક્શન નથી"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi કનેક્ટ કર્યું"</string> + <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"વાઇ-ફાઇ કનેક્ટ કર્યું"</string> <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS માટે શોધી રહ્યાં છે"</string> <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS દ્વારા સ્થાન સેટ કરાયું"</string> <string name="accessibility_location_active" msgid="2427290146138169014">"સ્થાન વિનંતીઓ સક્રિય"</string> @@ -271,9 +270,9 @@ <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"ફક્ત પ્રાધાન્યતા"</string> <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"ફક્ત એલાર્મ્સ"</string> <string name="quick_settings_dnd_none_label" msgid="5025477807123029478">"સાવ શાંતિ"</string> - <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> - <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> ઉપકરણો)"</string> - <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth બંધ"</string> + <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"બ્લૂટૂથ"</string> + <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"બ્લૂટૂથ (<xliff:g id="NUMBER">%d</xliff:g> ઉપકરણો)"</string> + <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"બ્લૂટૂથ બંધ"</string> <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"કોઈ જોડી કરેલ ઉપકરણો ઉપલબ્ધ નથી"</string> <string name="quick_settings_brightness_label" msgid="6968372297018755815">"તેજ"</string> <string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"આપમેળે ફેરવો"</string> @@ -293,12 +292,12 @@ <string name="quick_settings_user_label" msgid="5238995632130897840">"હું"</string> <string name="quick_settings_user_title" msgid="4467690427642392403">"વપરાશકર્તા"</string> <string name="quick_settings_user_new_user" msgid="9030521362023479778">"નવો વપરાશકર્તા"</string> - <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string> + <string name="quick_settings_wifi_label" msgid="9135344704899546041">"વાઇ-ફાઇ"</string> <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"કનેક્ટ થયેલ નથી"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"કોઈ નેટવર્ક નથી"</string> - <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi બંધ"</string> - <string name="quick_settings_wifi_on_label" msgid="7607810331387031235">"Wi-Fi ચાલુ"</string> - <string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"કોઈ Wi-Fi નેટવર્ક્સ ઉપલબ્ધ નથી"</string> + <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"વાઇ-ફાઇ બંધ"</string> + <string name="quick_settings_wifi_on_label" msgid="7607810331387031235">"વાઇ-ફાઇ ચાલુ"</string> + <string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"કોઈ વાઇ-ફાઇ નેટવર્ક્સ ઉપલબ્ધ નથી"</string> <string name="quick_settings_cast_title" msgid="7709016546426454729">"કાસ્ટ કરો"</string> <string name="quick_settings_casting" msgid="6601710681033353316">"કાસ્ટ કરી રહ્યાં છે"</string> <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"અનામાંકિત ઉપકરણ"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"વધુ જાણો"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"તમે <xliff:g id="VPN_APP">%1$s</xliff:g> સાથે કનેક્ટ થયાં છો, જે ઇમેઇલ્સ, ઍપ્લિકેશનો અને વેબસાઇટ્સ સહિત તમારી નેટવર્ક પ્રવૃત્તિને મૉનિટર કરી શકે છે."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPNની સેટિંગ્સ ખોલો"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"વિશ્વસનીય ઓળખપત્ર ખોલો"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"તમારા વ્યવસ્થાપકે નેટવર્ક લૉગિંગ ચાલુ કર્યુ છે, જે તમારા ઉપકરણ પર ટ્રાફિકનું નિરીક્ષણ કરે છે.\n\nવધુ માહિતી માટે, તમારા વ્યવસ્થાપકનો સંપર્ક કરો."</string> @@ -496,7 +494,7 @@ <string name="stream_music" msgid="9086982948697544342">"મીડિયા"</string> <string name="stream_alarm" msgid="5209444229227197703">"એલાર્મ"</string> <string name="stream_notification" msgid="2563720670905665031">"સૂચના"</string> - <string name="stream_bluetooth_sco" msgid="2055645746402746292">"Bluetooth"</string> + <string name="stream_bluetooth_sco" msgid="2055645746402746292">"બ્લૂટૂથ"</string> <string name="stream_dtmf" msgid="2447177903892477915">"દ્વિ બહુ ટોન આવર્તન"</string> <string name="stream_accessibility" msgid="301136219144385106">"ઍક્સેસિબિલિટી"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. અનમ્યૂટ કરવા માટે ટૅપ કરો."</string> @@ -541,8 +539,8 @@ <string name="qs_rearrange" msgid="8060918697551068765">"ઝડપી સેટિંગ્સને ફરીથી ગોઠવો"</string> <string name="show_brightness" msgid="6613930842805942519">"ઝડપી સેટિંગ્સમાં તેજ બતાવો"</string> <string name="experimental" msgid="6198182315536726162">"પ્રાયોગિક"</string> - <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth ચાલુ કરવુ છે?"</string> - <string name="enable_bluetooth_message" msgid="9106595990708985385">"તમારા ટેબ્લેટ સાથે કીબોર્ડ કનેક્ટ કરવા માટે, તમારે પહેલાં Bluetooth ચાલુ કરવાની જરૂર પડશે."</string> + <string name="enable_bluetooth_title" msgid="5027037706500635269">"બ્લૂટૂથ ચાલુ કરવુ છે?"</string> + <string name="enable_bluetooth_message" msgid="9106595990708985385">"તમારા ટેબ્લેટ સાથે કીબોર્ડ કનેક્ટ કરવા માટે, તમારે પહેલાં બ્લૂટૂથ ચાલુ કરવાની જરૂર પડશે."</string> <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ચાલુ કરો"</string> <string name="show_silently" msgid="6841966539811264192">"સૂચનાઓ ચુપચાપ બતાવો"</string> <string name="block" msgid="2734508760962682611">"તમામ સૂચનાઓને બ્લૉક કરો"</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"આ ઍપ્લિકેશનમાં સૂચના કૅટેગરી નથી"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"આ ઍપ્લિકેશનની સૂચનાઓ બંધ કરી શકાતી નથી"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">આ ઍપ્લિકેશનમાંની <xliff:g id="NUMBER_1">%d</xliff:g> સૂચના કૅટેગરીમાંથી 1</item> - <item quantity="other">આ ઍપ્લિકેશનમાંની <xliff:g id="NUMBER_1">%d</xliff:g> સૂચના કૅટેગરીમાંથી 1</item> + <item quantity="one">આ ઍપ્લિકેશનમાંની <xliff:g id="NUMBER_1">%s</xliff:g> સૂચના કૅટેગરીમાંથી 1</item> + <item quantity="other">આ ઍપ્લિકેશનમાંની <xliff:g id="NUMBER_1">%s</xliff:g> સૂચના કૅટેગરીમાંથી 1</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="other">%d મિનિટ</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"બૅટરી વપરાશ"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"ચાર્જિંગ દરમિયાન બૅટરી સેવર ઉપલબ્ધ નથી"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"બૅટરી સેવર"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"ચાર્જિંગ દરમિયાન બૅટરી સેવર ઉપલબ્ધ હોતું નથી"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"બૅટરી સેવર"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"પ્રદર્શન અને બૅકગ્રાઉન્ડ ડેટા ઘટાડે છે"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"બટન <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"નાનું કરો"</string> <string name="pip_phone_close" msgid="8416647892889710330">"બંધ કરો"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"છોડી દેવા માટે નીચે ખેંચો"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"ચિત્રમાં ચિત્ર મેનૂ"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"મેનૂ"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ચિત્રમાં-ચિત્રની અંદર છે"</string> <string name="pip_notification_message" msgid="5619512781514343311">"જો તમે નથી ઈચ્છતા કે <xliff:g id="NAME">%s</xliff:g> આ સુવિધાનો ઉપયોગ કરે, તો સેટિંગ્સ ખોલવા માટે ટૅપ કરો અને તે સુવિધાને બંધ કરો."</string> <string name="pip_play" msgid="1417176722760265888">"ચલાવો"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"મેનૂ"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> ઍપ્લિકેશન"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"ચેતવણીઓ"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"બૅટરી"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"સ્ક્રીનશૉટ"</string> <string name="notification_channel_general" msgid="4525309436693914482">"સામાન્ય સંદેશા"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"સ્ટોરેજ"</string> @@ -766,8 +763,8 @@ <string name="app_info" msgid="6856026610594615344">"ઍપ્લિકેશન માહિતી"</string> <string name="go_to_web" msgid="1106022723459948514">"વેબ પર જાઓ"</string> <string name="mobile_data" msgid="7094582042819250762">"મોબાઇલ ડેટા"</string> - <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi બંધ છે"</string> - <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth બંધ છે"</string> + <string name="wifi_is_off" msgid="1838559392210456893">"વાઇ-ફાઇ બંધ છે"</string> + <string name="bt_is_off" msgid="2640685272289706392">"બ્લૂટૂથ બંધ છે"</string> <string name="dnd_is_off" msgid="6167780215212497572">"ખલેલ પાડશો નહીં બંધ છે"</string> <string name="qs_dnd_prompt_auto_rule" msgid="862559028345233052">"ખલેલ પાડશો નહીં એક સ્વચાલિત નિયમ દ્વારા ચાલુ કરાયું હતું (<xliff:g id="ID_1">%s</xliff:g>)."</string> <string name="qs_dnd_prompt_app" msgid="7978037419334156034">"ખલેલ પાડશો નહીં એક ઍપ્લિકેશન દ્વારા ચાલુ કરાયું હતું (<xliff:g id="ID_1">%s</xliff:g>)."</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"પૃષ્ઠભૂમિમાં ચાલી રહેલ ઍપ્લિકેશનો"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"બૅટરી અને ડેટા વપરાશ વિશેની વિગતો માટે ટૅપ કરો"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"મોબાઇલ ડેટા બંધ કરીએ?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"એક ઍપ પરવાનગી વિનંતીને અસ્પષ્ટ કરતી હોવાને કારણે, સેટિંગ્સ તમારા પ્રતિસાદને ચકાસી શકતી નથી."</string> </resources> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index c6be6e0c31ec..9c6d7c4ed47e 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -19,17 +19,17 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="7164937344850004466">"सिस्टम UI"</string> + <string name="app_label" msgid="7164937344850004466">"सिस्टम यूआई"</string> <string name="status_bar_clear_all_button" msgid="7774721344716731603">"साफ़ करें"</string> <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"सूची से निकालें"</string> - <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"ऐप्स की जानकारी"</string> + <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"ऐप की जानकारी"</string> <string name="status_bar_no_recent_apps" msgid="7374907845131203189">"आपकी हाल की स्क्रीन यहां दिखाई देती हैं"</string> <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"हाल ही के ऐप्स खारिज करें"</string> <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759"> - <item quantity="one">स्क्रीन की खास जानकारी</item> - <item quantity="other">स्क्रीन की खास जानकारी</item> + <item quantity="one">%d स्क्रीन की खास जानकारी</item> + <item quantity="other">%d स्क्रीन की खास जानकारी</item> </plurals> - <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"कोई नोटिफ़िकेशन नहीं"</string> + <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"कोई सूचना नहीं है"</string> <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ऑनगोइंग"</string> <string name="status_bar_latest_events_title" msgid="6594767438577593172">"सूचनाएं"</string> <string name="battery_low_title" msgid="6456385927409742437">"बैटरी कम है"</string> @@ -49,7 +49,7 @@ <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"स्वत:"</string> <string name="status_bar_settings_notifications" msgid="397146176280905137">"सूचनाएं"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"ब्लूटूथ टीदर किया गया"</string> - <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"इनपुट पद्धति सेट करें"</string> + <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"इनपुट का तरीका सेट करें"</string> <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"भौतिक कीबोर्ड"</string> <string name="usb_device_permission_prompt" msgid="834698001271562057">"ऐप्स <xliff:g id="APPLICATION">%1$s</xliff:g> को USB डिवाइस तक पहुंचने दें?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"ऐप्स <xliff:g id="APPLICATION">%1$s</xliff:g> को USB सहायक डिवाइस तक पहुंचने दें?"</string> @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"कंप्यूटर का RSA कुंजी फ़िंगरप्रिंट है:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"इस कंप्यूटर से हमेशा अनुमति दें"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB डीबगिंग की अनुमति नहीं है"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"अभी इस डिवाइस में जिस उपयोगकर्ता ने साइन इन किया है, वो USB डीबगिंग चालू नहीं कर सकता. इस सुविधा का इस्तेमाल करने के लिए, प्राथमिक उपयोगकर्ता में बदलें."</string> <string name="compat_mode_on" msgid="6623839244840638213">"स्क्रीन भरने के लिए ज़ूम करें"</string> <string name="compat_mode_off" msgid="4434467572461327898">"स्क्रीन भरने के लिए खींचें"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"स्क्रीनशॉट सहेजा जा रहा है..."</string> @@ -83,10 +82,10 @@ <string name="installer_cd_button_title" msgid="2312667578562201583">"Mac के लिए Android File Transfer ऐप्स इंस्टॉल करें"</string> <string name="accessibility_back" msgid="567011538994429120">"वापस जाएं"</string> <string name="accessibility_home" msgid="8217216074895377641">"होम"</string> - <string name="accessibility_menu" msgid="316839303324695949">"मेनू"</string> + <string name="accessibility_menu" msgid="316839303324695949">"मेन्यू"</string> <string name="accessibility_accessibility_button" msgid="7601252764577607915">"एक्सेस-योग्यता"</string> <string name="accessibility_recent" msgid="5208608566793607626">"खास जानकारी"</string> - <string name="accessibility_search_light" msgid="1103867596330271848">"खोजें"</string> + <string name="accessibility_search_light" msgid="1103867596330271848">"सर्च करें"</string> <string name="accessibility_camera_button" msgid="8064671582820358152">"कैमरा"</string> <string name="accessibility_phone_button" msgid="6738112589538563574">"फ़ोन"</string> <string name="accessibility_voice_assist_button" msgid="487611083884852965">"आवाज़ से डिवाइस का इस्तेमाल"</string> @@ -98,7 +97,7 @@ <string name="voice_assist_label" msgid="3956854378310019854">"आवाज़ से डिवाइस को इस्तेमाल करें"</string> <string name="camera_label" msgid="7261107956054836961">"कैमरा खोलें"</string> <string name="recents_caption_resize" msgid="3517056471774958200">"नया कार्य लेआउट चुनें"</string> - <string name="cancel" msgid="6442560571259935130">"अभी नहीं"</string> + <string name="cancel" msgid="6442560571259935130">"रद्द करें"</string> <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"संगतता ज़ूम बटन."</string> <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"छोटी से बड़ी स्क्रीन पर ज़ूम करें."</string> <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ब्लूटूथ कनेक्ट किया गया."</string> @@ -166,12 +165,12 @@ <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"बैटरी चार्ज हो रही है, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> प्रतिशत."</string> <string name="accessibility_settings_button" msgid="799583911231893380">"सिस्टम सेटिंग."</string> <string name="accessibility_notifications_button" msgid="4498000369779421892">"सूचनाएं."</string> - <string name="accessibility_overflow_action" msgid="5681882033274783311">"सभी नोटिफ़िकेशन देखें"</string> - <string name="accessibility_remove_notification" msgid="3603099514902182350">"नोटिफ़िकेशन साफ़ करें"</string> + <string name="accessibility_overflow_action" msgid="5681882033274783311">"पूरी सूचनाएं देखें"</string> + <string name="accessibility_remove_notification" msgid="3603099514902182350">"सूचना साफ़ करें"</string> <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS सक्षम."</string> <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS प्राप्त करना."</string> <string name="accessibility_tty_enabled" msgid="4613200365379426561">"टेलीटाइपराइटर सक्षम."</string> - <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"रिंगर कंपन."</string> + <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"रिंगर कंपन (वाइब्रेशन)."</string> <string name="accessibility_ringer_silent" msgid="9061243307939135383">"रिंगर मौन."</string> <!-- no translation found for accessibility_casting (6887382141726543668) --> <skip /> @@ -179,11 +178,11 @@ <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> को ख़ारिज करें."</string> <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> खा़रिज कर दिया गया."</string> <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"हाल ही के सभी ऐप्लिकेशन ख़ारिज कर दिए गए."</string> - <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> ऐप्लिकेशन जानकारी खोलें."</string> + <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> ऐप्लिकेशन की जानकारी खोलें."</string> <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> प्रारंभ हो रहा है."</string> <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string> - <string name="accessibility_notification_dismissed" msgid="854211387186306927">"नोटिफ़िकेशन खारिज की गई."</string> - <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"नोटिफ़िकेशन शेड."</string> + <string name="accessibility_notification_dismissed" msgid="854211387186306927">"सूचना खारिज की गई."</string> + <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"सूचना शेड."</string> <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"त्वरित सेटिंग."</string> <string name="accessibility_desc_lock_screen" msgid="5625143713611759164">"लॉक स्क्रीन."</string> <string name="accessibility_desc_settings" msgid="3417884241751434521">"सेटिंग"</string> @@ -218,7 +217,7 @@ <string name="accessibility_quick_settings_location_changed_off" msgid="8526845571503387376">"स्थान रिपोर्टिंग को बंद किया गया."</string> <string name="accessibility_quick_settings_location_changed_on" msgid="339403053079338468">"स्थान रिपोर्टिंग को चालू किया गया."</string> <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"<xliff:g id="TIME">%s</xliff:g> के लिए अलार्म सेट किया गया."</string> - <string name="accessibility_quick_settings_close" msgid="3115847794692516306">"फलक बंद करें."</string> + <string name="accessibility_quick_settings_close" msgid="3115847794692516306">"पैनल बंद करें."</string> <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"अधिक समय."</string> <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"कम समय."</string> <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"फ़्लैशलाइट बंद है."</string> @@ -249,14 +248,14 @@ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"वाई-फ़ाई कनेक्ट किया गया"</string> <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS को खोजा जा रहा है"</string> <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS द्वारा सेट किया गया स्थान"</string> - <string name="accessibility_location_active" msgid="2427290146138169014">"स्थान अनुरोध सक्रिय"</string> + <string name="accessibility_location_active" msgid="2427290146138169014">"स्थान का अनुरोध किया जा रहा है"</string> <string name="accessibility_clear_all" msgid="5235938559247164925">"सभी सूचनाएं साफ़ करें."</string> <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string> <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404"> - <item quantity="one">इसमें <xliff:g id="NUMBER_1">%s</xliff:g> और नोटिफ़िकेशन हैं.</item> - <item quantity="other">इसमें <xliff:g id="NUMBER_1">%s</xliff:g> और नोटिफ़िकेशन हैं.</item> + <item quantity="one">इसमें <xliff:g id="NUMBER_1">%s</xliff:g> और सूचनाएं हैं.</item> + <item quantity="other">इसमें <xliff:g id="NUMBER_1">%s</xliff:g> और सूचनाएं हैं.</item> </plurals> - <string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"नोटिफ़िकेशन सेटिंग"</string> + <string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"सूचना सेटिंग"</string> <string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> सेटिंग"</string> <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"स्क्रीन स्वचालित रूप से घूमेगी."</string> <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"स्क्रीन लैंडस्केप दिशा में लॉक है."</string> @@ -331,9 +330,9 @@ <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC चालू है"</string> <string name="recents_empty_message" msgid="808480104164008572">"हाल ही का कोई आइटम नहीं"</string> <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"आपने सब कुछ साफ़ कर दिया है"</string> - <string name="recents_app_info_button_label" msgid="2890317189376000030">"एप्लिकेशन जानकारी"</string> + <string name="recents_app_info_button_label" msgid="2890317189376000030">"ऐप्लिकेशन की जानकारी"</string> <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"स्क्रीन पिन करना"</string> - <string name="recents_search_bar_label" msgid="8074997400187836677">"खोज"</string> + <string name="recents_search_bar_label" msgid="8074997400187836677">"सर्च"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> प्रारंभ नहीं किया जा सका."</string> <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> को सुरक्षित-मोड में अक्षम किया गया."</string> <string name="recents_stack_action_button_label" msgid="6593727103310426253">"Clear all"</string> @@ -351,23 +350,23 @@ <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"पूर्ण होने में <xliff:g id="CHARGING_TIME">%s</xliff:g> शेष"</string> <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"चार्ज नहीं हो रही है"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"नेटवर्क को\nमॉनीटर किया जा सकता है"</string> - <string name="description_target_search" msgid="3091587249776033139">"खोजें"</string> + <string name="description_target_search" msgid="3091587249776033139">"सर्च करें"</string> <string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए ऊपर स्लाइड करें."</string> <string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए बाएं स्लाइड करें."</string> <string name="zen_priority_introduction" msgid="1149025108714420281">"आपको अलार्म, रिमाइंडर, इवेंट और चुनिंदा कॉल करने वालों के अलावा किसी और तरह से (आवाज़ करके और थरथरा कर ) परेशान नहीं किया जाएगा. आप फिर भी संगीत, वीडियो और गेम सहित अपना चुना हुआ सब कुछ सुन सकते हैं."</string> <string name="zen_alarms_introduction" msgid="4934328096749380201">"आपको अलार्म छोड़कर दूसरी आवाज़ों और कंपनों से परेशान नहीं किया जाएगा. आपको अभी भी संगीत, वीडियो और गेम सहित वह सब कुछ सुनाई देगा जो आपने चलाने के लिए चुना है."</string> - <string name="zen_priority_customize_button" msgid="7948043278226955063">"कस्टमाइज़ करें"</string> - <string name="zen_silence_introduction_voice" msgid="3948778066295728085">"इससे अलार्म, संगीत, वीडियो और गेम सहित सभी आवाज़ें और कंपन अवरुद्ध हो जाते हैं. आप अभी भी फ़ोन काॅल कर सकेंगे."</string> - <string name="zen_silence_introduction" msgid="3137882381093271568">"इससे अलार्म, संगीत, वीडियो और गेम सहित सभी ध्वनियां और कंपन अवरुद्ध हो जाते हैं."</string> + <string name="zen_priority_customize_button" msgid="7948043278226955063">"अपनी पसंद के मुताबिक बनाएं"</string> + <string name="zen_silence_introduction_voice" msgid="3948778066295728085">"इससे अलार्म, संगीत, वीडियो और गेम सहित सभी आवाज़ और कंपन (वाइब्रेशन) रोक दिए जाते हैं. आप तब भी फ़ोन काॅल कर सकेंगे."</string> + <string name="zen_silence_introduction" msgid="3137882381093271568">"इससे अलार्म, संगीत, वीडियो और गेम सहित सभी आवाज़ और कंपन (वाइब्रेशन) रोक दिए जाते हैं."</string> <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string> <string name="speed_bump_explanation" msgid="1288875699658819755">"कम अत्यावश्यक सूचनाएं नीचे दी गई हैं"</string> <string name="notification_tap_again" msgid="7590196980943943842">"खोलने के लिए पुन: टैप करें"</string> <string name="keyguard_unlock" msgid="8043466894212841998">"अनलॉक करने के लिए ऊपर स्वाइप करें"</string> <string name="do_disclosure_generic" msgid="5615898451805157556">"इस डिवाइस का प्रबंधन आपका संगठन करता है"</string> <string name="do_disclosure_with_name" msgid="5640615509915445501">"इस डिवाइस के प्रबंधक <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> हैं"</string> - <string name="phone_hint" msgid="4872890986869209950">"फ़ोन के लिए आइकन से स्वाइप करें"</string> - <string name="voice_hint" msgid="8939888732119726665">"\'आवाज़ से डिवाइस का इस्तेमाल\' आइकन से स्वाइप करें"</string> - <string name="camera_hint" msgid="7939688436797157483">"कैमरे के लिए आइकन से स्वाइप करें"</string> + <string name="phone_hint" msgid="4872890986869209950">"फ़ोन के लिए आइकॉन से स्वाइप करें"</string> + <string name="voice_hint" msgid="8939888732119726665">"\'आवाज़ से डिवाइस का इस्तेमाल\' आइकॉन से स्वाइप करें"</string> + <string name="camera_hint" msgid="7939688436797157483">"कैमरे के लिए आइकॉन से स्वाइप करें"</string> <string name="interruption_level_none_with_warning" msgid="5114872171614161084">"संपूर्ण मौन. इससे स्क्रीन रीडर भी मौन हो जाएंगे."</string> <string name="interruption_level_none" msgid="6000083681244492992">"पूरी तरह शांत"</string> <string name="interruption_level_priority" msgid="6426766465363855505">"केवल प्राथमिकता"</string> @@ -378,9 +377,9 @@ <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"चार्ज हो रहा है (पूरा होने में <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> बाकी)"</string> <string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"तेज़ी से चार्ज हो रहा है (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> में हो जाएगा)"</string> <string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"धीरे चार्ज हो रहा है (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> में पूरा हो जाएगा)"</string> - <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"उपयोगकर्ता स्विच करें"</string> - <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"उपयोगकर्ता स्विच करें, वर्तमान उपयोगकर्ता <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string> - <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"वर्तमान उपयोगकर्ता <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string> + <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"उपयोगकर्ता बदलें"</string> + <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"उपयोगकर्ता बदलें, मौजूदा उपयोगकर्ता <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string> + <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"मौजूदा उपयोगकर्ता <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string> <string name="accessibility_multi_user_switch_quick_contact" msgid="3020367729287990475">"प्रोफ़ाइल दिखाएं"</string> <string name="user_add_user" msgid="5110251524486079492">"उपयोगकर्ता जोड़ें"</string> <string name="user_new_user_name" msgid="426540612051178753">"नया उपयोगकर्ता"</string> @@ -392,18 +391,18 @@ <string name="guest_exit_guest_dialog_remove" msgid="7402231963862520531">"निकालें"</string> <string name="guest_wipe_session_title" msgid="6419439912885956132">"अतिथि, आपका पुन: स्वागत है!"</string> <string name="guest_wipe_session_message" msgid="8476238178270112811">"क्या आप अपना सत्र जारी रखना चाहते हैं?"</string> - <string name="guest_wipe_session_wipe" msgid="5065558566939858884">"पुन: प्रारंभ करें"</string> + <string name="guest_wipe_session_wipe" msgid="5065558566939858884">"फिर से शुरू करें"</string> <string name="guest_wipe_session_dontwipe" msgid="1401113462524894716">"हां, जारी रखें"</string> <string name="guest_notification_title" msgid="1585278533840603063">"अतिथि उपयोगकर्ता"</string> - <string name="guest_notification_text" msgid="335747957734796689">"ऐप्स और डेटा हटाने के लिए, अतिथि उपयोगकर्ता को निकालें"</string> + <string name="guest_notification_text" msgid="335747957734796689">"ऐप और डेटा हटाने के लिए, अतिथि उपयोगकर्ता को निकालें"</string> <string name="guest_notification_remove_action" msgid="8820670703892101990">"अतिथि को निकालें"</string> <string name="user_logout_notification_title" msgid="1453960926437240727">"उपयोगकर्ता को प्रस्थान करवाना"</string> - <string name="user_logout_notification_text" msgid="3350262809611876284">"वर्तमान उपयोगकर्ता से प्रस्थान करें"</string> + <string name="user_logout_notification_text" msgid="3350262809611876284">"मौजूदा उपयोगकर्ता से प्रस्थान करें"</string> <string name="user_logout_notification_action" msgid="1195428991423425062">"उपयोगकर्ता को प्रस्थान करवाएं"</string> <string name="user_add_user_title" msgid="4553596395824132638">"नया उपयोगकर्ता जोड़ें?"</string> - <string name="user_add_user_message_short" msgid="2161624834066214559">"जब आप कोई नया उपयोगकर्ता जोड़ते हैं तो उस व्यक्ति को अपना स्थान सेट करना होता है.\n\nकोई भी उपयोगकर्ता अन्य सभी उपयोगकर्ताओं के लिए ऐप्स अपडेट कर सकता है."</string> + <string name="user_add_user_message_short" msgid="2161624834066214559">"जब आप कोई नया उपयोगकर्ता जोड़ते हैं तो उस व्यक्ति को अपना स्थान सेट करना होता है.\n\nकोई भी उपयोगकर्ता बाकी सभी उपयोगकर्ताओं के लिए ऐप अपडेट कर सकता है."</string> <string name="user_remove_user_title" msgid="4681256956076895559">"उपयोगकर्ता निकालें?"</string> - <string name="user_remove_user_message" msgid="1453218013959498039">"इस उपयोगकर्ता के सभी ऐप्स और डेटा को हटा दिया जाएगा."</string> + <string name="user_remove_user_message" msgid="1453218013959498039">"इस उपयोगकर्ता के सभी ऐप और डेटा को हटा दिया जाएगा."</string> <string name="user_remove_user_remove" msgid="7479275741742178297">"निकालें"</string> <string name="battery_saver_notification_title" msgid="237918726750955859">"बैटरी सेवर चालू है"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"निष्पादन और पृष्ठभूमि डेटा को कम करता है"</string> @@ -411,8 +410,8 @@ <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> आपके स्क्रीन पर प्रदर्शित प्रत्येक सामग्री को कैप्चर करना प्रारंभ कर देगी."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"फिर से न दिखाएं"</string> <string name="clear_all_notifications_text" msgid="814192889771462828">"सभी साफ करें"</string> - <string name="media_projection_action_text" msgid="8470872969457985954">"अब प्रारंभ करें"</string> - <string name="empty_shade_text" msgid="708135716272867002">"कोई नोटिफ़िकेशन नहीं"</string> + <string name="media_projection_action_text" msgid="8470872969457985954">"अब शुरू करें"</string> + <string name="empty_shade_text" msgid="708135716272867002">"कोई सूचना नहीं मिली"</string> <string name="profile_owned_footer" msgid="8021888108553696069">"प्रोफ़ाइल को मॉनीटर किया जा सकता है"</string> <string name="vpn_footer" msgid="2388611096129106812">"नेटवर्क को मॉनीटर किया जा सकता है"</string> <string name="branded_vpn_footer" msgid="2168111859226496230">"नेटवर्क को मॉनिटर किया जा सकता है"</string> @@ -440,11 +439,11 @@ <string name="disable_vpn" msgid="4435534311510272506">"VPN अक्षम करें"</string> <string name="disconnect_vpn" msgid="1324915059568548655">"VPN डिस्कनेक्ट करें"</string> <string name="monitoring_button_view_policies" msgid="100913612638514424">"नीतियां देखें"</string> - <string name="monitoring_description_named_management" msgid="5281789135578986303">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> आपके डिवाइस का प्रबंधन करता है.\n\nआपका व्यवस्थापक सेटिंग, कॉर्पोरेट एक्सेस, ऐप्लिकेशन, आपके डिवाइस से संबद्ध डेटा और आपके डिवाइस की स्थान की जानकारी की निगरानी कर सकता है और उन्हें प्रबंधित कर सकता है.\n\nअधिक जानकारी के लिए, अपने व्यवस्थापक से संपर्क करें."</string> - <string name="monitoring_description_management" msgid="4573721970278370790">"आपका संगठन आपके डिवाइस का प्रबंधन करता है.\n\nआपका व्यवस्थापक सेटिंग, कॉर्पोरेट एक्सेस, ऐप्लिकेशन, आपके डिवाइस से संबद्ध डेटा और आपके डिवाइस की स्थान की जानकारी की निगरानी कर सकता है और उन्हें प्रबंधित कर सकता है.\n\nअधिक जानकारी के लिए, अपने व्यवस्थापक से संपर्क करें."</string> - <string name="monitoring_description_management_ca_certificate" msgid="5202023784131001751">"आपके संगठन ने इस डिवाइस पर एक प्रमाणपत्र प्राधिकरण इंस्टॉल किया है. आपके सुरक्षित नेटवर्क की निगरानी या उसमें बदलाव किया जा सकता है."</string> - <string name="monitoring_description_managed_profile_ca_certificate" msgid="4683248196789897964">"आपके संगठन ने आपकी कार्य प्रोफ़ाइल में एक प्रमाणपत्र प्राधिकरण इंस्टॉल किया है. आपके सुरक्षित नेटवर्क ट्रैफ़िक की निगरानी या उसमें बदलाव किया जा सकता है."</string> - <string name="monitoring_description_ca_certificate" msgid="7886985418413598352">"इस डिवाइस पर एक प्रमाणपत्र प्राधिकरण इंस्टॉल किया गया है. आपके सुरक्षित नेटवर्क ट्रैफ़िक की निगरानी या उसमें बदलाव किया जा सकता है."</string> + <string name="monitoring_description_named_management" msgid="5281789135578986303">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> आपके डिवाइस का प्रबंधन करता है.\n\nआपका एडमिन सेटिंग, कॉर्पोरेट पहुंच, ऐप्लिकेशन, आपके डिवाइस से जुड़े डेटा और आपके डिवाइस की स्थान की जानकारी की निगरानी कर सकता है और उन्हें प्रबंधित कर सकता है.\n\nअधिक जानकारी के लिए, अपने एडमिन से संपर्क करें."</string> + <string name="monitoring_description_management" msgid="4573721970278370790">"आपका संगठन आपके डिवाइस का प्रबंधन करता है.\n\nआपका एडमिन सेटिंग, कॉर्पोरेट पहुंच, ऐप्लिकेशन, आपके डिवाइस से जुड़े डेटा और आपके डिवाइस की स्थान (लोकेशन) की जानकारी की निगरानी कर सकता है और उन्हें प्रबंधित कर सकता है.\n\nअधिक जानकारी के लिए, अपने एडमिन से संपर्क करें."</string> + <string name="monitoring_description_management_ca_certificate" msgid="5202023784131001751">"आपके संगठन ने इस डिवाइस पर एक प्रमाणपत्र अनुमति इंस्टॉल की है. आपके सुरक्षित नेटवर्क पर ट्रेफ़िक की निगरानी या उसमें बदलाव किया जा सकता है."</string> + <string name="monitoring_description_managed_profile_ca_certificate" msgid="4683248196789897964">"आपके संगठन ने आपकी कार्य प्रोफ़ाइल में एक प्रमाणपत्र अनुमति इंस्टॉल की है. आपके सुरक्षित नेटवर्क ट्रैफ़िक की निगरानी या उसमें बदलाव किया जा सकता है."</string> + <string name="monitoring_description_ca_certificate" msgid="7886985418413598352">"इस डिवाइस पर एक प्रमाणपत्र अनुमति इंस्टॉल की है. आपके सुरक्षित नेटवर्क ट्रैफ़िक की निगरानी या उसमें बदलाव किया जा सकता है."</string> <string name="monitoring_description_management_network_logging" msgid="7184005419733060736">"आपके व्यवस्थापक ने नेटवर्क लॉगिंग चालू किया है, जो आपके डिवाइस पर ट्रैफ़िक की निगरानी करता है."</string> <string name="monitoring_description_named_vpn" msgid="7403457334088909254">"आप <xliff:g id="VPN_APP">%1$s</xliff:g> से कनेक्ट हैं, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकते हैं."</string> <string name="monitoring_description_two_named_vpns" msgid="4198511413729213802">"आप <xliff:g id="VPN_APP_0">%1$s</xliff:g> और <xliff:g id="VPN_APP_1">%2$s</xliff:g> से कनेक्ट हैं, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकते हैं."</string> @@ -452,28 +451,27 @@ <string name="monitoring_description_personal_profile_named_vpn" msgid="3133980926929069283">"आपकी व्यक्तिगत प्रोफ़ाइल <xliff:g id="VPN_APP">%1$s</xliff:g> से कनेक्ट है, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है."</string> <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"<xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g> आपका डिवाइस प्रबंधित करता है."</string> <string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> आपका डिवाइस प्रबंधित करने के लिए <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> का उपयोग करता है."</string> - <string name="monitoring_description_do_body" msgid="3639594537660975895">"आपका व्यवस्थापक आपके डिवाइस से जुड़ी सेटिंग, कॉर्पोरेट एक्सेस, ऐप्लिकेशन, डेटा और आपके डिवाइस की स्थान जानकारी की निगरानी और उसका प्रबंधन कर सकता है."</string> + <string name="monitoring_description_do_body" msgid="3639594537660975895">"आपका एडमिन आपके डिवाइस से जुड़ी सेटिंग, कॉर्पोरेट पहुंच, ऐप्लिकेशन, डेटा और आपके डिवाइस की स्थान जानकारी की निगरानी और उसका प्रबंधन कर सकता है."</string> <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string> - <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"अधिक जानें"</string> + <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"ज़्यादा जानें"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"आप <xliff:g id="VPN_APP">%1$s</xliff:g> से कनेक्ट हैं, जो ईमेल, ऐप्लिकेशन और वेबसाइट सहित आपकी नेटवर्क गतिविधि को मॉनिटर कर सकता है."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN सेटिंग खोलें"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"विश्वसनीय क्रेडेंशियल खोलें"</string> - <string name="monitoring_description_network_logging" msgid="7223505523384076027">"आपके व्यवस्थापक ने नेटवर्क लॉग करना चालू कर दिया है, जो आपके डिवाइस पर ट्रैफ़िक की निगरानी करता है.\n\nअधिक जानकारी के लिए अपने व्यवस्थापक से संपर्क करें."</string> + <string name="monitoring_description_network_logging" msgid="7223505523384076027">"आपके एडमिन ने नेटवर्क लॉग करना चालू कर दिया है, जो आपके डिवाइस पर ट्रैफ़िक की निगरानी करता है.\n\nअधिक जानकारी के लिए अपने एडमिन से संपर्क करें."</string> <string name="monitoring_description_vpn" msgid="4445150119515393526">"आपने किसी ऐप को VPN कनेक्शन सेट करने की अनुमति दी है.\n\nयह ऐप ईमेल, ऐप्स और सुरक्षित वेबसाइटों सहित आपके डिवाइस और नेटवर्क की गतिविधि की निगरानी कर सकता है."</string> - <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> आपकी कार्य प्रोफ़ाइल को प्रबंधित करता है.\n\nआपका व्यवस्थापक ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है.\n\nअधिक जानकारी के लिए अपने व्यवस्थापक से संपर्क करें.\n\nआप ऐसे VPN से भी कनेक्ट हैं, जो आपकी नेटवर्क गतिविधि की निगरानी कर सकता है."</string> + <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> आपकी वर्क प्रोफ़ाइल को प्रबंधित करता है.\n\n आपका एडमिन ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है.\n\nऔर जानकारी के लिए अपने एडमिन से संपर्क करें.\n\nआप ऐसे VPN से भी कनेक्ट हैं, जो आपकी नेटवर्क गतिविधि की निगरानी कर सकता है."</string> <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string> <string name="monitoring_description_app" msgid="1828472472674709532">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> से कनेक्ट हैं, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है."</string> <string name="monitoring_description_app_personal" msgid="484599052118316268">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> से कनेक्ट हैं, जो ईमेल, ऐप्स और वेबसाइटों सहित आपकी व्यक्तिगत नेटवर्क गतिविधि की निगरानी कर सकता है."</string> <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> से कनेक्ट हैं, जो ईमेल, ऐप्लिकेशन और वेबसाइट सहित आपकी व्यक्तिगत नेटवर्क गतिविधि को मॉनिटर कर सकता है."</string> - <string name="monitoring_description_app_work" msgid="4612997849787922906">"आपकी कार्य प्रोफ़ाइल का प्रबंधन <xliff:g id="ORGANIZATION">%1$s</xliff:g> करता है. प्रोफ़ाइल <xliff:g id="APPLICATION">%2$s</xliff:g> से कनेक्ट है, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है.\n\nअधिक जानकारी के लिए, अपने व्यवस्थापक से संपर्क करें."</string> + <string name="monitoring_description_app_work" msgid="4612997849787922906">"आपकी वर्क प्रोफ़ाइल का प्रबंधन <xliff:g id="ORGANIZATION">%1$s</xliff:g> करता है. प्रोफ़ाइल <xliff:g id="APPLICATION">%2$s</xliff:g> से कनेक्ट है, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है.\n\nऔर जानकारी के लिए, अपने एडमिन से संपर्क करें."</string> <string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"आपकी कार्य प्रोफ़ाइल का प्रबंधन <xliff:g id="ORGANIZATION">%1$s</xliff:g> करता है. प्रोफ़ाइल <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> से कनेक्ट है, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है.\n\nआप <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> से भी कनेक्ट हैं, जो आपकी व्यक्तिगत नेटवर्क गतिविधि की निगरानी कर सकता है."</string> <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"<xliff:g id="USER_NAME">%1$s</xliff:g> के लिए अनलॉक किया गया"</string> <string name="keyguard_indication_trust_managed" msgid="8319646760022357585">"<xliff:g id="TRUST_AGENT">%1$s</xliff:g> चल रहा है"</string> <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"जब तक कि आप मैन्युअल रूप से अनलॉक नहीं करते तब तक डिवाइस लॉक रहेगा"</string> - <string name="hidden_notifications_title" msgid="7139628534207443290">"सूचनाएं अधिक तेज़ी से प्राप्त करें"</string> + <string name="hidden_notifications_title" msgid="7139628534207443290">"सूचनाएं ज़्यादा तेज़ी से पाएं"</string> <string name="hidden_notifications_text" msgid="2326409389088668981">"आपके द्वारा उन्हें अनलॉक किए जाने से पहले देखें"</string> <string name="hidden_notifications_cancel" msgid="3690709735122344913">"रहने दें"</string> <string name="hidden_notifications_setup" msgid="41079514801976810">"सेट करें"</string> @@ -495,24 +493,24 @@ <string name="stream_ring" msgid="8213049469184048338">"घंटी बजाएं"</string> <string name="stream_music" msgid="9086982948697544342">"मीडिया"</string> <string name="stream_alarm" msgid="5209444229227197703">"अलार्म"</string> - <string name="stream_notification" msgid="2563720670905665031">"नोटिफ़िकेशन"</string> + <string name="stream_notification" msgid="2563720670905665031">"सूचना"</string> <string name="stream_bluetooth_sco" msgid="2055645746402746292">"ब्लूटूथ"</string> <string name="stream_dtmf" msgid="2447177903892477915">"दोहरी बहु टोन आवृत्ति"</string> <string name="stream_accessibility" msgid="301136219144385106">"एक्सेस-योग्यता"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. अनम्यूट करने के लिए टैप करें."</string> - <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. कंपन पर सेट करने के लिए टैप करें. एक्सेस-योग्यता सेवाएं म्यूट हो सकती हैं."</string> + <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. कंपन (वाइब्रेशन) पर सेट करने के लिए छूएं. सुलभता सेवाएं म्यूट हो सकती हैं."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. म्यूट करने के लिए टैप करें. एक्सेस-योग्यता सेवाएं म्यूट हो सकती हैं."</string> - <string name="volume_stream_content_description_vibrate_a11y" msgid="6427727603978431301">"%1$s. कंपन पर सेट करने के लिए टैप करें."</string> + <string name="volume_stream_content_description_vibrate_a11y" msgid="6427727603978431301">"%1$s. कंपन (वाइब्रेशन) पर सेट करने के लिए छूएं."</string> <string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. म्यूट करने के लिए टैप करें."</string> <string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s वॉल्यूम नियंत्रण दिखाए गए हैं. खारिज करने के लिए स्वाइप करें."</string> <string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"वॉल्यूम नियंत्रण छिपे हुए हैं"</string> - <string name="system_ui_tuner" msgid="708224127392452018">"सिस्टम UI ट्यूनर"</string> + <string name="system_ui_tuner" msgid="708224127392452018">"सिस्टम यूज़र इंटरफ़ेस (यूआई) ट्यूनर"</string> <string name="show_battery_percentage" msgid="5444136600512968798">"एम्बेड किया गया बैटरी प्रतिशत दिखाएं"</string> - <string name="show_battery_percentage_summary" msgid="3215025775576786037">"जब चार्ज नहीं किया जा रहा हो तब स्टेटस बार आइकन में बैटरी लेवल का प्रतिशत दिखाएं"</string> + <string name="show_battery_percentage_summary" msgid="3215025775576786037">"जब चार्ज नहीं किया जा रहा हो तब स्टेटस बार आइकॉन में बैटरी लेवल का प्रतिशत दिखाएं"</string> <string name="quick_settings" msgid="10042998191725428">"तेज़ सेटिंग"</string> <string name="status_bar" msgid="4877645476959324760">"स्टेटस बार"</string> <string name="overview" msgid="4018602013895926956">"खास जानकारी"</string> - <string name="demo_mode" msgid="2532177350215638026">"सिस्टम UI डेमो मोड"</string> + <string name="demo_mode" msgid="2532177350215638026">"सिस्टम यूज़र इंटरफ़ेस (यूआई) डेमो मोड"</string> <string name="enable_demo_mode" msgid="4844205668718636518">"डेमो मोड सक्षम करें"</string> <string name="show_demo_mode" msgid="2018336697782464029">"डेमो मोड दिखाएं"</string> <string name="status_bar_ethernet" msgid="5044290963549500128">"ईथरनेट"</string> @@ -529,12 +527,12 @@ <string name="accessibility_status_bar_hotspot" msgid="4099381329956402865">"हॉटस्पॉट"</string> <string name="accessibility_managed_profile" msgid="6613641363112584120">"कार्य प्रोफ़ाइल"</string> <string name="tuner_warning_title" msgid="7094689930793031682">"कुछ के लिए मज़ेदार लेकिन सबके लिए नहीं"</string> - <string name="tuner_warning" msgid="8730648121973575701">"सिस्टम UI ट्यूनर, आपको Android उपयोगकर्ता इंटरफ़ेस में सुधार लाने और उसे अपनी पसंद के हिसाब से बदलने के कुछ और तरीके देता है. प्रयोग के तौर पर इस्तेमाल हो रहीं ये सुविधाएं आगे चल कर रिलीज़ की जा सकती हैं, रोकी जा सकती हैं या दिखाई देना बंद हो सकती हैं. सावधानी से आगे बढ़ें."</string> + <string name="tuner_warning" msgid="8730648121973575701">"सिस्टम यूज़र इंटरफ़ेस (यूआई) ट्यूनर, आपको Android यूज़र इंटरफ़ेस में सुधार लाने और उसे अपनी पसंद के हिसाब से बदलने के कुछ और तरीके देता है. प्रयोग के तौर पर इस्तेमाल हो रहीं ये सुविधाएं आगे चल कर रिलीज़ की जा सकती हैं, रोकी जा सकती हैं या दिखाई देना बंद हो सकती हैं. सावधानी से आगे बढ़ें."</string> <string name="tuner_persistent_warning" msgid="8597333795565621795">"ये प्रयोगात्मक सुविधाएं आगामी रिलीज़ में बदल सकती हैं, रुक सकती हैं या दिखाई देना बंद हो सकती हैं. सावधानी से आगे बढ़ें."</string> <string name="got_it" msgid="2239653834387972602">"समझ लिया"</string> - <string name="tuner_toast" msgid="603429811084428439">"बधाई हो! सिस्टम UI ट्यूनर को सेटिंग में जोड़ दिया गया है"</string> + <string name="tuner_toast" msgid="603429811084428439">"बधाई हो! सिस्टम यूज़र इंटरफ़ेस (यूआई) ट्यूनर को सेटिंग में जोड़ दिया गया है"</string> <string name="remove_from_settings" msgid="8389591916603406378">"सेटिंग से निकालें"</string> - <string name="remove_from_settings_prompt" msgid="6069085993355887748">"सेटिंग से सिस्टम UI ट्यूनर निकालें और इसकी सभी सुविधाओं का उपयोग रोक दें?"</string> + <string name="remove_from_settings_prompt" msgid="6069085993355887748">"सेटिंग से सिस्टम यूज़र इंटरफ़ेस (यूआई) ट्यूनर निकालें और इसकी सभी सुविधाओं का इस्तेमाल रोक दें?"</string> <string name="activity_not_found" msgid="348423244327799974">"ऐप्लिकेशन आपके डिवाइस पर इंस्टॉल नहीं है"</string> <string name="clock_seconds" msgid="7689554147579179507">"घड़ी के सेकंड दिखाएं"</string> <string name="clock_seconds_desc" msgid="6282693067130470675">"स्टेटस बार में सेकंड में समय दिखाएं. इससे बैटरी लाइफ़ पर असर पड़ सकता है."</string> @@ -544,38 +542,38 @@ <string name="enable_bluetooth_title" msgid="5027037706500635269">"ब्लूटूथ चालू करें?"</string> <string name="enable_bluetooth_message" msgid="9106595990708985385">"अपने कीबोर्ड को अपने टैबलेट से कनेक्ट करने के लिए, आपको पहले ब्लूटूथ चालू करना होगा."</string> <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"चालू करें"</string> - <string name="show_silently" msgid="6841966539811264192">"नोटिफ़िकेशन मौन रूप से दिखाएं"</string> + <string name="show_silently" msgid="6841966539811264192">"सूचना बिना आवाज़ के दिखाएं"</string> <string name="block" msgid="2734508760962682611">"सभी सूचनाएं रोकें"</string> <string name="do_not_silence" msgid="6878060322594892441">"मौन ना करें"</string> <string name="do_not_silence_block" msgid="4070647971382232311">"मौन या अवरुद्ध ना करें"</string> - <string name="tuner_full_importance_settings" msgid="3207312268609236827">"पावर नोटिफ़िकेशन नियंत्रण"</string> + <string name="tuner_full_importance_settings" msgid="3207312268609236827">"पावर सूचना नियंत्रण"</string> <string name="tuner_full_importance_settings_on" msgid="7545060756610299966">"चालू"</string> <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"बंद"</string> - <string name="power_notification_controls_description" msgid="4372459941671353358">"पावर नोटिफ़िकेशन नियंत्रण के ज़रिये, आप किसी ऐप के नोटिफ़िकेशन को उसकी अहमियत के हिसाब से 0 से 5 के लेवल पर सेट कर सकते हैं.\n\n"<b>"लेवल 5"</b>" \n- नोटिफ़िकेशन सूची में सबसे ऊपर दिखाएं \n- पूरे स्क्रीन को ढंकने की अनुमति दें \n- लगातार देखते रहें \n\n"<b>" लेवल 4"</b>" \n- पूरे स्क्रीन को ढंकें \n- लगातार देखते रहें \n\n"<b>"लेवल 3"</b>" \n- पूरे स्क्रीन को ढंकने से रोकें \n- कभी भी न देखें \n\n"<b>"लेवल 2"</b>" \n- पूरे स्क्रीन को ढंकने से रोकें \n- कभी भी देखें \n- कभी भी आवाज़ या कंपन (वाइब्रेशन) ना करें \n\n"<b>"लेवल 1"</b>" \n- पूरे स्क्रीन को ढंकने से रोकें \n- कभी भी ना देखें \n- कभी भी आवाज़ या कंपन (वाइब्रेशन) ना करें \n- लॉक स्क्रीन और स्टेटस बार से छिपाएं \n- नोटिफ़िकेशन सूची के नीचे दिखाएं \n\n"<b>"लेवल 0"</b>" \n- ऐप्लिकेशन के सभी नोटिफ़िकेशन रोक दें"</string> - <string name="notification_header_default_channel" msgid="7506845022070889909">"नोटिफ़िकेशन"</string> - <string name="notification_channel_disabled" msgid="2139193533791840539">"अब आपको ये नोटिफ़िकेशन नहीं मिलेंगे"</string> - <string name="notification_num_channels" msgid="2048144408999179471">"नोटिफ़िकेशन की <xliff:g id="NUMBER">%d</xliff:g> श्रेणियां"</string> - <string name="notification_default_channel_desc" msgid="2506053815870808359">"इस ऐप्लिकेशन में नोटिफ़िकेशन श्रेणियां नहीं हैं"</string> - <string name="notification_unblockable_desc" msgid="3561016061737896906">"इस ऐप्लिकेशन के नोटिफ़िकेशन बंद नहीं किए जा सकते"</string> + <string name="power_notification_controls_description" msgid="4372459941671353358">"पावर सूचना नियंत्रण के ज़रिये, आप किसी ऐप की सूचना को उसकी अहमियत के हिसाब से 0 से 5 के लेवल पर सेट कर सकते हैं.\n\n"<b>"लेवल 5"</b>" \n- सूचना सूची में सबसे ऊपर दिखाएं \n- पूरे स्क्रीन को ढंकने की अनुमति दें \n- लगातार देखते रहें \n\n"<b>" लेवल 4"</b>" \n- पूरे स्क्रीन को ढंकें \n- लगातार देखते रहें \n\n"<b>"लेवल 3"</b>" \n- पूरे स्क्रीन को ढंकने से रोकें \n-कभी भी न देखें \n\n"<b>"लेवल 2"</b>" \n- पूरे स्क्रीन को ढंकने से रोकें \n- कभी भी देखें \n- कभी भी आवाज़ या कंपन (वाइब्रेशन) न करें \n\n"<b>"लेवल 1"</b>" \n- पूरे स्क्रीन को ढंकने से रोकें \n- कभी भी न देखें \n- कभी भी आवाज़ या कंपन (वाइब्रेशन) न करें \n- लॉक स्क्रीन और स्टेटस बार से छिपाएं \n- सूचना सूची के नीचे दिखाएं \n\n"<b>"लेवल 0"</b>" \n- ऐप्लिकेशन की सभी सूचनाएं रोक दें"</string> + <string name="notification_header_default_channel" msgid="7506845022070889909">"सूचना"</string> + <string name="notification_channel_disabled" msgid="2139193533791840539">"अब आपको ये सूचनाएं नहीं मिलेंगी"</string> + <string name="notification_num_channels" msgid="2048144408999179471">"सूचना की <xliff:g id="NUMBER">%d</xliff:g> श्रेणियां"</string> + <string name="notification_default_channel_desc" msgid="2506053815870808359">"इस ऐप्लिकेशन में सूचना श्रेणियां नहीं हैं"</string> + <string name="notification_unblockable_desc" msgid="3561016061737896906">"इस ऐप की सूचनाएं बंद नहीं की जा सकती"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">इस ऐप्लिकेशन की <xliff:g id="NUMBER_1">%d</xliff:g> नोटिफ़िकेशन श्रेणियों में से 1 श्रेणी</item> - <item quantity="other">इस ऐप्लिकेशन की <xliff:g id="NUMBER_1">%d</xliff:g> नोटिफ़िकेशन श्रेणियों में से 1 श्रेणी</item> + <item quantity="one">इस ऐप की <xliff:g id="NUMBER_1">%s</xliff:g> सूचना श्रेणियों में से 1 श्रेणी</item> + <item quantity="other">इस ऐप की <xliff:g id="NUMBER_1">%s</xliff:g> सूचना श्रेणियों में से 1 श्रेणी</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> और <xliff:g id="NUMBER_5">%3$d</xliff:g> अन्य</item> <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> और <xliff:g id="NUMBER_5">%3$d</xliff:g> अन्य</item> </plurals> - <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए नोटिफ़िकेशन नियंत्रण चालू हैं"</string> - <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए नोटिफ़िकेशन नियंत्रण बंद हैं"</string> - <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"इस चैनल से नोटिफ़िकेशन की अनुमति दें"</string> + <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए सूचना नियंत्रण चालू हैं"</string> + <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए सूचना नियंत्रण बंद हैं"</string> + <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"इस चैनल से सूचना की पाने की मंज़ूरी दें"</string> <string name="notification_all_categories" msgid="5407190218055113282">"सभी श्रेणियां"</string> <string name="notification_more_settings" msgid="816306283396553571">"और सेटिंग"</string> - <string name="notification_app_settings" msgid="3743278649182392015">"कस्टमाइज़ करें: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string> + <string name="notification_app_settings" msgid="3743278649182392015">"अपनी पसंद के मुताबिक बनाएं: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string> <string name="notification_done" msgid="5279426047273930175">"हो गया"</string> <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string> - <string name="notification_menu_gear_description" msgid="2204480013726775108">"नोटिफ़िकेशन नियंत्रण"</string> - <string name="notification_menu_snooze_description" msgid="3653669438131034525">"नोटिफ़िकेशन की याद दिलाने के विकल्प"</string> + <string name="notification_menu_gear_description" msgid="2204480013726775108">"सूचना नियंत्रण"</string> + <string name="notification_menu_snooze_description" msgid="3653669438131034525">"सूचना को स्नूज़ (थोड़ी देर के लिए चुप करना) करने के विकल्प"</string> <string name="snooze_undo" msgid="6074877317002985129">"पहले जैसा करें"</string> <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> के लिए याद दिलाया गया"</string> <plurals name="snoozeHourOptions" formatted="false" msgid="2124335842674413030"> @@ -587,8 +585,8 @@ <item quantity="other">%d मिनट</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"बैटरी उपयोग"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"चार्ज किए जाने के दौरान बैटरी सेवर उपलब्ध नहीं है"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"बैटरी सेवर"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"चार्ज करते समय बैटरी सेवर उपलब्ध नहीं होता"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"बैटरी सेवर"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"निष्पादन और पृष्ठभूमि डेटा को कम करता है"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"बटन <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -620,15 +618,15 @@ <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"होम"</string> <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"हाल ही के"</string> <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"वापस जाएं"</string> - <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"नोटिफ़िकेशन"</string> + <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"सूचना"</string> <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"कीबोर्ड शॉर्टकट"</string> - <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"इनपुट पद्धति बदलें"</string> + <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"इनपुट का तरीका बदलें"</string> <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"ऐप्लिकेशन"</string> <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"सहायक"</string> <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ब्राउज़र"</string> <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"संपर्क"</string> <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"ईमेल"</string> - <string name="keyboard_shortcut_group_applications_sms" msgid="638701213803242744">"SMS करें"</string> + <string name="keyboard_shortcut_group_applications_sms" msgid="638701213803242744">"मैसेज (एसएमएस) करें"</string> <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"संगीत"</string> <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string> <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"कैलेंडर"</string> @@ -671,8 +669,8 @@ <string name="accessibility_key" msgid="5701989859305675896">"कस्टम मार्गदर्शक बटन"</string> <string name="left_keycode" msgid="2010948862498918135">"बायां कुंजी कोड"</string> <string name="right_keycode" msgid="708447961000848163">"दायां कुंजी कोड"</string> - <string name="left_icon" msgid="3096287125959387541">"बायां आइकन"</string> - <string name="right_icon" msgid="3952104823293824311">"दायां आइकन"</string> + <string name="left_icon" msgid="3096287125959387541">"बायां आइकॉन"</string> + <string name="right_icon" msgid="3952104823293824311">"दायां आइकॉन"</string> <string name="drag_to_add_tiles" msgid="7058945779098711293">"टाइलों को जोड़ने के लिए खींचें और छोड़ें"</string> <string name="drag_to_remove_tiles" msgid="3361212377437088062">"हटाने के लिए यहां खींचें और छोड़ें"</string> <string name="qs_edit" msgid="2232596095725105230">"संपादित करें"</string> @@ -680,12 +678,12 @@ <string-array name="clock_options"> <item msgid="5965318737560463480">"घंटे, मिनट और सेकंड दिखाएं"</item> <item msgid="1427801730816895300">"घंटे और मिनट दिखाएं (डिफ़ॉल्ट)"</item> - <item msgid="3830170141562534721">"यह आइकन ना दिखाएं"</item> + <item msgid="3830170141562534721">"इस आइकॉन को ना दिखाएं"</item> </string-array> <string-array name="battery_options"> <item msgid="3160236755818672034">"हमेशा प्रतिशत दिखाएं"</item> <item msgid="2139628951880142927">"चार्ज होते समय प्रतिशत दिखाएं (डिफ़ॉल्ट)"</item> - <item msgid="3327323682209964956">"यह आइकन ना दिखाएं"</item> + <item msgid="3327323682209964956">"इस आइकॉन को ना दिखाएं"</item> </string-array> <string name="other" msgid="4060683095962566764">"अन्य"</string> <string name="accessibility_divider" msgid="5903423481953635044">"विभाजित स्क्रीन विभाजक"</string> @@ -699,16 +697,16 @@ <string name="accessibility_action_divider_top_50" msgid="6385859741925078668">"ऊपर की स्क्रीन को 50% बनाएं"</string> <string name="accessibility_action_divider_top_30" msgid="6201455163864841205">"ऊपर की स्क्रीन को 30% बनाएं"</string> <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"नीचे की स्क्रीन को पूर्ण स्क्रीन बनाएं"</string> - <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. संपादित करने के लिए डबल टैप करें."</string> - <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. जोड़ने के लिए डबल टैप करें."</string> - <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>. चुनने के लिए डबल टैप करें."</string> + <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. में बदलाव करने के लिए दो बार छूएं."</string> + <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. जोड़ने के लिए दो बार छूएं."</string> + <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>. चुनने के लिए दो बार छूएं."</string> <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> को ले जाएं"</string> <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> निकालें"</string> <string name="accessibility_qs_edit_tile_added" msgid="8050200862063548309">"<xliff:g id="TILE_NAME">%1$s</xliff:g> को <xliff:g id="POSITION">%2$d</xliff:g> स्थिति में जोड़ा गया"</string> <string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> निकाल दिया गया है"</string> <string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> को <xliff:g id="POSITION">%2$d</xliff:g> स्थिति में ले जाया गया"</string> <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"त्वरित सेटिंग संपादक."</string> - <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> नोटिफ़िकेशन: <xliff:g id="ID_2">%2$s</xliff:g>"</string> + <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g> सूचना: <xliff:g id="ID_2">%2$s</xliff:g>"</string> <string name="dock_forced_resizable" msgid="5914261505436217520">"हो सकता है कि ऐप्लिकेशन विभाजित स्क्रीन के साथ काम ना करे."</string> <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ऐप विभाजित स्क्रीन का समर्थन नहीं करता है."</string> <string name="forced_resizable_secondary_display" msgid="4230857851756391925">"हो सकता है कि ऐप प्राइमरी (मुख्य) डिस्प्ले के अलावा बाकी दूसरे डिस्प्ले पर काम न करे."</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"छोटा करें"</string> <string name="pip_phone_close" msgid="8416647892889710330">"बंद करें"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"खारिज करने के लिए नीचे खींचें और छोड़ें"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"चित्र में चित्र मेनू"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"मेन्यू"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> पिक्चर में पिक्चर के अंदर है"</string> <string name="pip_notification_message" msgid="5619512781514343311">"अगर आप नहीं चाहते कि <xliff:g id="NAME">%s</xliff:g> इस सुविधा का उपयोग करे, तो सेटिंग खोलने के लिए टैप करें और उसे बंद करें ."</string> <string name="pip_play" msgid="1417176722760265888">"चलाएं"</string> @@ -753,11 +751,10 @@ <string name="tuner_minus" msgid="4806116839519226809">"घटाने का चिह्न"</string> <string name="tuner_left" msgid="8404287986475034806">"बायां"</string> <string name="tuner_right" msgid="6222734772467850156">"दायां"</string> - <string name="tuner_menu" msgid="191640047241552081">"मेनू"</string> + <string name="tuner_menu" msgid="191640047241552081">"मेन्यू"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> ऐप"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"सूचनाएं"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"बैटरी"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"स्क्रीनशॉट"</string> <string name="notification_channel_general" msgid="4525309436693914482">"सामान्य संदेश"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"जगह"</string> @@ -776,6 +773,7 @@ <string name="qs_dnd_keep" msgid="1825009164681928736">"रखें"</string> <string name="qs_dnd_replace" msgid="8019520786644276623">"बदलें"</string> <string name="running_foreground_services_title" msgid="381024150898615683">"बैकग्राउंड में चल रहे ऐप्लिकेशन"</string> - <string name="running_foreground_services_msg" msgid="6326247670075574355">"बैटरी और डेटा खर्च की जानकारी के लिए टैप करें"</string> + <string name="running_foreground_services_msg" msgid="6326247670075574355">"बैटरी और डेटा खर्च की जानकारी के लिए छूएं"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"मोबाइल डेटा बंद करना चाहते हैं?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"चूंकि ऐप की वजह से अनुमति के अनुरोध को समझने में दिक्कत हो रही है, इसलिए सेटिंग से आपके जवाब की पुष्टि नहीं हो पा रही है."</string> </resources> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index be8268fdce56..858e69498839 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -65,8 +65,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Otisak prsta RSA ključa računala je: \n <xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Uvijek dopusti s ovog računala"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Otklanjanje pogrešaka putem USB-a nije dopušteno"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Korisnik koji je trenutačno prijavljen na ovaj uređaj ne može uključiti otklanjanje pogrešaka putem USB-a. Da biste upotrebljavali tu značajku, prijeđite na primarnog korisnika."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zumiraj i ispuni zaslon"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Rastegni i ispuni zaslon"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Spremanje snimke zaslona..."</string> @@ -459,8 +458,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Saznajte više"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Povezani ste s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g> koja može nadzirati vašu aktivnost na mreži, uključujući e-poštu, aplikacije i web-lokacije."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Otvorite postavke VPN-a"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Otvorite pouzdane vjerodajnice"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administrator je uključio mrežni zapisnik koji prati promet na vašem uređaju.\n\nViše informacija možete saznati od administratora."</string> @@ -560,9 +558,9 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Ova aplikacija nema kategorije obavijesti"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Obavijesti ove aplikacije ne mogu se isključiti"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorije obavijesti iz ove aplikacije</item> - <item quantity="few">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorije obavijesti iz ove aplikacije</item> - <item quantity="other">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorija obavijesti iz ove aplikacije</item> + <item quantity="one">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorije obavijesti iz ove aplikacije</item> + <item quantity="few">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorije obavijesti iz ove aplikacije</item> + <item quantity="other">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorija obavijesti iz ove aplikacije</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -593,8 +591,8 @@ <item quantity="other">%d minuta</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Potrošnja baterije"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Štednja baterije nije dostupna tijekom punjenja"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Štednja baterije"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Štednja baterije nije dostupna tijekom punjenja"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Štednja baterije"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Smanjuje količinu rada i pozadinske podatke"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Tipka <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Početak"</string> @@ -734,7 +732,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimiziraj"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Zatvori"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Povucite prema dolje da biste odbacili"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Izbornik slike u slici"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Izbornik"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> jest na slici u slici"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Ako ne želite da aplikacija <xliff:g id="NAME">%s</xliff:g> upotrebljava tu značajku, dodirnite da biste otvorili postavke i isključili je."</string> <string name="pip_play" msgid="1417176722760265888">"Reproduciraj"</string> @@ -762,8 +760,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Izbornik"</string> <string name="tuner_app" msgid="3507057938640108777">"Aplikacija <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozorenja"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Baterija"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Snimke zaslona"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Općenite poruke"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Pohrana"</string> @@ -784,4 +781,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Izvođenje aplikacija u pozadini"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Dodirnite da biste vidjeli pojedinosti o potrošnji baterije i podatkovnom prometu"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Isključiti mobilne podatke?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Budući da aplikacija prekriva zahtjev za dopuštenje, Postavke ne mogu potvrditi vaš odgovor."</string> </resources> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 98022718d616..609992fb9bd1 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"A számítógép RSA kulcs ujjlenyomata:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Mindig engedélyezze erről a számítógépről"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Az USB hibakeresése nem engedélyezett"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Az eszközre jelenleg bejelentkezett felhasználó nem engedélyezheti az USB-hibakeresést. A funkció használatához váltson az elsődleges felhasználóra."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Nagyítás a kitöltéshez"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Nyújtás kitöltéshez"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Képernyőkép mentése..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"További információ"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Ön kapcsolódik ehhez: <xliff:g id="VPN_APP">%1$s</xliff:g>, amely figyelheti hálózati tevékenységét, köztük a levelezést, az alkalmazás- és webhelyhasználatot."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN-beállítások megnyitása"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Megbízható hitelesítési adatok megnyitása"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"A rendszergazda bekapcsolta az eszköz forgalmát figyelő hálózati naplózást.\n\nHa további információra van szüksége, forduljon a rendszergazdához."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Az alkalmazás nem rendelkezik értesítési kategóriákkal"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Az alkalmazástól érkező értesítések nem kapcsolhatók ki"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g>/1 értesítési kategória az alkalmazásból</item> - <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g>/1 értesítési kategória az alkalmazásból</item> + <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g>/1 értesítési kategória az alkalmazásból</item> + <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g>/1 értesítési kategória az alkalmazásból</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d perc</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Akkumulátorhasználat"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Az Akkumulátorkímélő módot töltés közben nem lehet használni"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Akkumulátorkímélő mód"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Az Akkumulátorkímélő módot töltés közben nem lehet használni"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Akkumulátorkímélő mód"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Csökkenti a teljesítményt és a háttéradatok használatát"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g> gomb"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Kezdőképernyő"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Kis méret"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Bezárás"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Elvetéshez húzza lefelé"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Kép a képben menü"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menü"</string> <string name="pip_notification_title" msgid="3204024940158161322">"A(z) <xliff:g id="NAME">%s</xliff:g> kép a képben funkciót használ"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Ha nem szeretné, hogy a(z) <xliff:g id="NAME">%s</xliff:g> használja ezt a funkciót, koppintson a beállítások megnyitásához, és kapcsolja ki."</string> <string name="pip_play" msgid="1417176722760265888">"Lejátszás"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menü"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> alkalmazás"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Értesítések"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Akkumulátor"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Képernyőképek"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Általános üzenetek"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Tárhely"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"A háttérben még futnak alkalmazások"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Koppintson az akkumulátor- és adathasználat részleteinek megtekintéséhez"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Kikapcsolja a mobiladatokat?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Mivel az egyik alkalmazás eltakarja az engedélykérést, a Beállítások alkalmazás nem tudja ellenőrizni az Ön válaszát."</string> </resources> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index 01a1e1b33a0c..6856735dc071 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Համակարգչի RSA-ի բանալի մատնահետքն է`\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Միշտ թույլատրել այս համակարգչից"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB վրիպազերծումը արգելված է"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Ընթացիկ հաշվի օգտատերը չի կարող միացնել USB վրիպազերծումը: Այս գործառույթը միացնելու համար մուտք գործեք հիմնական օգտատիրոջ հաշվով:"</string> <string name="compat_mode_on" msgid="6623839244840638213">"Խոշորացնել` էկրանը լցնելու համար"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Ձգել` էկրանը լցնելու համար"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Պահում է էկրանի պատկերը…"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Իմանալ ավելին"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Դուք կապակցված եք <xliff:g id="VPN_APP">%1$s</xliff:g> հավելվածին, որը կարող է վերահսկել ձեր ցանցային գործողությունը, այդ թվում նաև էլփոստը, հավելվածները և կայքերը:"</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Բացել VPN-ի կարգավորումները"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Բացել վստահելի հավատարմագրերը"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Ձեր ադմինիստրատորը միացրել է ցանցային իրադարձությունների գրանցումը, որը վերահսկում է ձեր սարքի թրաֆիկը։\n\nԼրացուցիչ տեղեկություններ ստանալու համար դիմեք ձեր ադմինիստրատորին։"</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Այս հավելվածը ծանուցման կատեգորիաներ չունի"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Այս հավելվածի ծանուցումները հնարավոր չէ անջատել"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 out of <xliff:g id="NUMBER_1">%d</xliff:g> notification categories from this app</item> - <item quantity="other">1 ալիք` այս հավելվածի <xliff:g id="NUMBER_1">%d</xliff:g> կատեգորիաներից</item> + <item quantity="one">1 out of <xliff:g id="NUMBER_1">%s</xliff:g> notification categories from this app</item> + <item quantity="other">1 ալիք` այս հավելվածի <xliff:g id="NUMBER_1">%s</xliff:g> կատեգորիաներից</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="other">%d րոպե</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Մարտկոցի օգտագործում"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Մարտկոցի տնտեսումը լիցքավորման ժամանակ հասանելի չէ"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Մարտկոցի տնտեսում"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Մարտկոցի էներգախնայիչը լիցքավորման ժամանակ հասանելի չէ"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Մարտկոցի էներգախնայիչ"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Նվազեցնում է ծանրաբեռնվածությունը և ֆոնային տվյալները"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g> կոճակ"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Գլխավոր էջ"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Ծալել"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Փակել"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Քաշեք վար՝ փակելու համար"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"«Նկար նկարի մեջ» ռեժիմի ընտրացանկ"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Ընտրացանկ"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g>-ը «Նկար նկարի մեջ» ռեժիմում է"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Եթե չեք ցանկանում, որ <xliff:g id="NAME">%s</xliff:g>-ն օգտագործի այս գործառույթը, հպեք՝ կարգավորումները բացելու և այն անջատելու համար։"</string> <string name="pip_play" msgid="1417176722760265888">"Նվագարկել"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Ընտրացանկ"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> հավելված"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Ծանուցումներ"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Մարտկոց"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Էկրանի պատկերներ"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Ընդհանուր հաղորդագրություններ"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Տարածք"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Ֆոնային ռեժիմում աշխատող հավելվածներ"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Հպեք՝ մարտկոցի և թրաֆիկի մանրամասները տեսնելու համար"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Անջատե՞լ բջջային ինտերնետը։"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Քանի որ ներածումն արգելափակված է ինչ-որ հավելվածի կողմից, Կարգավորումները չեն կարող հաստատել ձեր պատասխանը:"</string> </resources> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index eb392bd84be8..aaf95fbe95c2 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Sidik jari kunci RSA komputer adalah:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Selalu izinkan dari komputer ini"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Debug USB tidak diizinkan"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Pengguna yang sedang login ke perangkat ini tidak dapat mengaktifkan proses debug USB. Beralihlah ke pengguna utama untuk menggunakan fitur ini."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Perbesar utk mengisi layar"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Rentangkn utk mngisi layar"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Menyimpan screenshot..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Pelajari lebih lanjut"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Anda tersambung ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Buka setelan VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Buka kredensial terpercaya"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Admin telah mengaktifkan pencatatan log jaringan, yang memantau traffic di perangkat.\n\nUntuk informasi selengkapnya, hubungi admin."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Aplikasi ini tidak memiliki kategori notifikasi"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Notifikasi dari aplikasi ini tidak dapat dinonaktifkan"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 dari <xliff:g id="NUMBER_1">%d</xliff:g> kategori notifikasi dari aplikasi ini</item> - <item quantity="one">1 dari <xliff:g id="NUMBER_0">%d</xliff:g> kategori notifikasi dari aplikasi ini</item> + <item quantity="other">1 dari <xliff:g id="NUMBER_1">%s</xliff:g> kategori notifikasi dari aplikasi ini</item> + <item quantity="one">1 dari <xliff:g id="NUMBER_0">%s</xliff:g> kategori notifikasi dari aplikasi ini</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d menit</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Pemakaian baterai"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Penghemat Baterai tidak tersedia selama pengisian daya"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Penghemat Baterai"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Penghemat baterai tidak tersedia selama mengisi daya"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Penghemat baterai"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Mengurangi performa dan data latar belakang"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Tombol <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalkan"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Tutup"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Seret ke bawah untuk menutup"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Menu picture in picture"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> adalah picture-in-picture"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Jika Anda tidak ingin <xliff:g id="NAME">%s</xliff:g> menggunakan fitur ini, tap untuk membuka setelan dan menonaktifkannya."</string> <string name="pip_play" msgid="1417176722760265888">"Putar"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menu"</string> <string name="tuner_app" msgid="3507057938640108777">"Aplikasi <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Notifikasi"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Baterai"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshot"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Pesan Umum"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Penyimpanan"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Aplikasi yang sedang berjalan di latar belakang"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Tap untuk melihat detail penggunaan baterai dan data"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Nonaktifkan data seluler?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Karena sebuah aplikasi menghalangi permintaan izin, Setelan tidak dapat memverifikasi respons Anda."</string> </resources> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index b38614d80deb..eefb363320c4 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Fingrafar RSA-lykils tölvunnar er:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Leyfa alltaf úr þessari tölvu"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB-villuleit ekki leyfð"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Notandinn sem er skráður inn í þetta tæki núna getur ekki kveikt á USB-villuleit. Til þess að nota þennan eiginleika skaltu skipta yfir í aðalnotandann."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Fylla skjá með aðdrætti"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Teygja yfir allan skjáinn"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Vistar skjámynd…"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Frekari upplýsingar"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Þú ert með tengingu við <xliff:g id="VPN_APP">%1$s</xliff:g>, sem getur fylgst með netnotkun þinni, þ. á m. tölvupósti, forritum og vefsvæðum."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Opna VPN-stillingar"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Opna traust skilríki"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Kerfisstjóri hefur kveikt á eftirliti netkerfa, sem fylgist með netumferð á tækinu þínu.\n\nHafðu samband við kerfisstjóra til að fá frekari upplýsingar."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Þetta forrit er ekki með tilkynningaflokka"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Ekki er hægt að slökkva á tilkynningum frá þessu forriti"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 af <xliff:g id="NUMBER_1">%d</xliff:g> tilkynningaflokki frá þessu forriti</item> - <item quantity="other">1 af <xliff:g id="NUMBER_1">%d</xliff:g> tilkynningaflokkum frá þessu forriti</item> + <item quantity="one">1 af <xliff:g id="NUMBER_1">%s</xliff:g> tilkynningaflokki frá þessu forriti</item> + <item quantity="other">1 af <xliff:g id="NUMBER_1">%s</xliff:g> tilkynningaflokkum frá þessu forriti</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="other">%d mínútur</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Rafhlöðunotkun"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Ekki er hægt að nota rafhlöðusparnað meðan á hleðslu stendur"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Rafhlöðusparnaður"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Ekki er hægt að nota rafhlöðusparnað meðan á hleðslu stendur"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Rafhlöðusparnaður"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Dregur úr afköstum og bakgrunnsgögnum"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Hnappur <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minnka"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Loka"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Draga niður til að hunsa"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Valmynd fyrir mynd í mynd"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Valmynd"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> er með mynd í mynd"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Ef þú vilt ekki að <xliff:g id="NAME">%s</xliff:g> noti þennan eiginleika skaltu ýta til að opna stillingarnar og slökkva á því."</string> <string name="pip_play" msgid="1417176722760265888">"Spila"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Valmynd"</string> <string name="tuner_app" msgid="3507057938640108777">"Forritið <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Tilkynningar"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Rafhlaða"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Skjámyndir"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Almenn skilaboð"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Geymslurými"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Forrit sem keyra í bakgrunni"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Ýttu til að fá upplýsingar um rafhlöðu- og gagnanotkun"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Slökkva á farsímagögnum?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Stillingar geta ekki staðfest svarið þitt vegna þess að forrit er að fela heimildarbeiðni."</string> </resources> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 7d4617ced6bf..915f40a3253a 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Fingerprint della chiave RSA del computer: \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Consenti sempre da questo computer"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Debug USB non consentito"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"L\'utente che ha eseguito l\'accesso a questo dispositivo non può attivare il debug USB. Per utilizzare questa funzione, passa all\'utente principale."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zoom per riempire schermo"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Estendi per riemp. schermo"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Salvataggio screenshot..."</string> @@ -459,8 +458,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Ulteriori informazioni"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Sei connesso a <xliff:g id="VPN_APP">%1$s</xliff:g>, che consente di monitorare le attività di rete, inclusi siti web, email e app."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Apri impostazioni VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Apri credenziali attendibili"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"L\'amministratore ha attivato i log di rete, che consentono di monitorare il traffico sul dispositivo.\n\nPer ulteriori informazioni, contatta l\'amministratore."</string> @@ -560,8 +558,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Questa app non ha categorie di notifica"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Le notifiche di quest\'app non possono essere disattivate"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 categoria di notifica su <xliff:g id="NUMBER_1">%d</xliff:g> di questa app</item> - <item quantity="one">1 categoria di notifica su <xliff:g id="NUMBER_0">%d</xliff:g> di questa app</item> + <item quantity="other">1 categoria di notifica su <xliff:g id="NUMBER_1">%s</xliff:g> di questa app</item> + <item quantity="one">1 categoria di notifica su <xliff:g id="NUMBER_0">%s</xliff:g> di questa app</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -589,8 +587,8 @@ <item quantity="one">%d minuto</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Utilizzo batteria"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Risparmio energetico non disponibile durante la ricarica"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Risparmio energetico"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Risparmio energetico non disponibile durante la ricarica"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Risparmio energetico"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Riduce le prestazioni e i dati in background"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Pulsante <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home page"</string> @@ -600,7 +598,7 @@ <string name="keyboard_key_dpad_left" msgid="1346446024676962251">"Sinistra"</string> <string name="keyboard_key_dpad_right" msgid="3317323247127515341">"Destra"</string> <string name="keyboard_key_dpad_center" msgid="2566737770049304658">"Al centro"</string> - <string name="keyboard_key_tab" msgid="3871485650463164476">"Scheda"</string> + <string name="keyboard_key_tab" msgid="3871485650463164476">"Tab"</string> <string name="keyboard_key_space" msgid="2499861316311153293">"Spazio"</string> <string name="keyboard_key_enter" msgid="5739632123216118137">"Invio"</string> <string name="keyboard_key_backspace" msgid="1559580097512385854">"Backspace"</string> @@ -730,7 +728,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Riduci a icona"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Chiudi"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Trascina verso il basso per ignorare"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Menu Picture in picture"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> è in Picture in picture"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Se non desideri che l\'app <xliff:g id="NAME">%s</xliff:g> utilizzi questa funzione, tocca per aprire le impostazioni e disattivarla."</string> <string name="pip_play" msgid="1417176722760265888">"Riproduci"</string> @@ -758,8 +756,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menu"</string> <string name="tuner_app" msgid="3507057938640108777">"App <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Avvisi"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Batteria"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshot"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Messaggi generali"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Spazio di archiviazione"</string> @@ -780,4 +777,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"App in esecuzione in background"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Tocca per conoscere i dettagli sull\'utilizzo dei dati e della batteria"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Disattivare i dati mobili?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Un\'app sta oscurando una richiesta di autorizzazione, pertanto Impostazioni non può verificare la tua risposta."</string> </resources> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 246e4d1826ea..11c246d98806 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -66,8 +66,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"טביעת האצבע של מפתח ה-RSA של המחשב היא:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"אפשר תמיד ממחשב זה"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"לא ניתן לבצע ניפוי באגים ב-USB"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"למשתמש המחובר לחשבון במכשיר הזה אין אפשרות להפעיל ניפוי באגים ב-USB. כדי להשתמש בתכונה הזו יש לעבור אל המשתמש הראשי."</string> <string name="compat_mode_on" msgid="6623839244840638213">"הגדל תצוגה כדי למלא את המסך"</string> <string name="compat_mode_off" msgid="4434467572461327898">"מתח כדי למלא את המסך"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"שומר צילום מסך..."</string> @@ -88,7 +87,7 @@ <string name="accessibility_menu" msgid="316839303324695949">"תפריט"</string> <string name="accessibility_accessibility_button" msgid="7601252764577607915">"נגישות"</string> <string name="accessibility_recent" msgid="5208608566793607626">"סקירה"</string> - <string name="accessibility_search_light" msgid="1103867596330271848">"חפש"</string> + <string name="accessibility_search_light" msgid="1103867596330271848">"חיפוש"</string> <string name="accessibility_camera_button" msgid="8064671582820358152">"מצלמה"</string> <string name="accessibility_phone_button" msgid="6738112589538563574">"טלפון"</string> <string name="accessibility_voice_assist_button" msgid="487611083884852965">"מסייע קולי"</string> @@ -337,7 +336,7 @@ <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"מחקת הכול"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"מידע על האפליקציה"</string> <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"הצמדת מסך"</string> - <string name="recents_search_bar_label" msgid="8074997400187836677">"חפש"</string> + <string name="recents_search_bar_label" msgid="8074997400187836677">"חיפוש"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"לא ניתן היה להפעיל את <xliff:g id="APP">%s</xliff:g>."</string> <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> מושבת במצב בטוח."</string> <string name="recents_stack_action_button_label" msgid="6593727103310426253">"נקה הכל"</string> @@ -461,8 +460,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"למידע נוסף"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"אתה מחובר לאפליקציה <xliff:g id="VPN_APP">%1$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת, כולל הודעות אימייל, אפליקציות ואתרים."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"להגדרות ה-VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"פתח את פרטי הכניסה המהימנים"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"מנהל המערכת הפעיל את תכונת רישום התנועה ברשת, שמנטרת את תנועת הנתונים במכשיר.\n\nלמידע נוסף, צור קשר עם מנהל המערכת."</string> @@ -562,10 +560,10 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"האפליקציה הזו לא תומכת בקטגוריות של הודעות"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"לא ניתן לכבות התראות של האפליקציה הזאת"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="two">קטגוריית הודעות אחת מתוך <xliff:g id="NUMBER_1">%d</xliff:g> מאפליקציה זו</item> - <item quantity="many">קטגוריית הודעות אחת מתוך <xliff:g id="NUMBER_1">%d</xliff:g> מאפליקציה זו</item> - <item quantity="other">קטגוריית הודעות אחת מתוך <xliff:g id="NUMBER_1">%d</xliff:g> מאפליקציה זו</item> - <item quantity="one">קטגוריית הודעות אחת מתוך <xliff:g id="NUMBER_0">%d</xliff:g> מאפליקציה זו</item> + <item quantity="two">קטגוריית הודעות אחת מתוך <xliff:g id="NUMBER_1">%s</xliff:g> מאפליקציה זו</item> + <item quantity="many">קטגוריית הודעות אחת מתוך <xliff:g id="NUMBER_1">%s</xliff:g> מאפליקציה זו</item> + <item quantity="other">קטגוריית הודעות אחת מתוך <xliff:g id="NUMBER_1">%s</xliff:g> מאפליקציה זו</item> + <item quantity="one">קטגוריית הודעות אחת מתוך <xliff:g id="NUMBER_0">%s</xliff:g> מאפליקציה זו</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -599,8 +597,8 @@ <item quantity="one">דקה</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"שימוש בסוללה"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"תכונת החיסכון בסוללה אינה זמינה בעת טעינת המכשיר"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"חיסכון בסוללה"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"תכונת החיסכון בסוללה לא זמינה כשהמכשיר בטעינה"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"חיסכון בסוללה"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"מפחית את רמת הביצועים ואת נתוני הרקע"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"לחצן <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"דף הבית"</string> @@ -740,7 +738,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"מזער"</string> <string name="pip_phone_close" msgid="8416647892889710330">"סגור"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"גרור למטה כדי לסגור"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"תפריט \'תמונה בתוך תמונה\'"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"תפריט"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> במצב תמונה בתוך תמונה"</string> <string name="pip_notification_message" msgid="5619512781514343311">"אם אינך רוצה שהתכונה הזו תשמש את <xliff:g id="NAME">%s</xliff:g>, יש להקיש כדי לפתוח את ההגדרות ולכבות את התכונה."</string> <string name="pip_play" msgid="1417176722760265888">"הפעל"</string> @@ -768,8 +766,7 @@ <string name="tuner_menu" msgid="191640047241552081">"תפריט"</string> <string name="tuner_app" msgid="3507057938640108777">"האפליקציה <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"התראות"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"סוללה"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"צילומי מסך"</string> <string name="notification_channel_general" msgid="4525309436693914482">"הודעות כלליות"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"אחסון"</string> @@ -790,4 +787,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"אפליקציות שפועלות ברקע"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"הקש לקבלת פרטים על צריכה של נתונים וסוללה"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"לכבות את חבילת הגלישה?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"יש אפליקציה שמסתירה את בקשת ההרשאה, ולכן להגדרות אין אפשרות לאמת את התשובה."</string> </resources> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 38e872ca4331..e400ffffcd91 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"このパソコンのRSAキーのフィンガープリント:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"このパソコンからのUSBデバッグを常に許可する"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USBデバッグは許可されていません"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"この端末に現在ログインしているユーザーでは、USB デバッグを ON にすることはできません。この機能を使用するには、メインユーザーに切り替えてください。"</string> <string name="compat_mode_on" msgid="6623839244840638213">"画面サイズに合わせて拡大"</string> <string name="compat_mode_off" msgid="4434467572461327898">"画面サイズに合わせて拡大"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"スクリーンショットを保存中..."</string> @@ -459,8 +458,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"詳細"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"「<xliff:g id="VPN_APP">%1$s</xliff:g>」に接続しています。このアプリはあなたのネットワーク アクティビティ(メール、アプリ、ウェブサイトなど)を監視できます。"</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN 設定を開く"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"信頼できる認証情報を開く"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"管理者がネットワーク ログを有効にしているため、この端末のトラフィックは監視されています。\n\n詳しくは管理者にお問い合わせください。"</string> @@ -560,8 +558,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"このアプリでは通知カテゴリが設定されていません"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"このアプリの通知を OFF にすることはできません"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">このアプリの通知カテゴリ <xliff:g id="NUMBER_1">%d</xliff:g> 件中 1 件</item> - <item quantity="one">このアプリの通知カテゴリ <xliff:g id="NUMBER_0">%d</xliff:g> 件中 1 件</item> + <item quantity="other">このアプリの通知カテゴリ <xliff:g id="NUMBER_1">%s</xliff:g> 件中 1 件</item> + <item quantity="one">このアプリの通知カテゴリ <xliff:g id="NUMBER_0">%s</xliff:g> 件中 1 件</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>、<xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -589,8 +587,8 @@ <item quantity="one">%d分</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"電池の使用状況"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"充電中はバッテリー セーバーは利用できません"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"バッテリー セーバー"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"充電中はバッテリー セーバーは利用できません"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"バッテリー セーバー"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"パフォーマンスとバックグラウンド データを制限します"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g> ボタン"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -730,7 +728,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string> <string name="pip_phone_close" msgid="8416647892889710330">"閉じる"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"下にドラッグして閉じる"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"ピクチャー イン ピクチャー メニュー"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"メニュー"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g>はピクチャー イン ピクチャーで表示中です"</string> <string name="pip_notification_message" msgid="5619512781514343311">"<xliff:g id="NAME">%s</xliff:g>でこの機能を使用しない場合は、タップして設定を開いて OFF にしてください。"</string> <string name="pip_play" msgid="1417176722760265888">"再生"</string> @@ -758,8 +756,7 @@ <string name="tuner_menu" msgid="191640047241552081">"メニュー"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> アプリ"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"通知"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"電池"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"スクリーンショット"</string> <string name="notification_channel_general" msgid="4525309436693914482">"一般メッセージ"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"ストレージ"</string> @@ -780,4 +777,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"バックグラウンドで実行中のアプリ"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"タップして電池やデータの使用量を確認"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"モバイルデータを OFF にしますか?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"アプリが許可リクエストを隠しているため、設定側でユーザーの応答を確認できません。"</string> </resources> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index 02b15352d793..6aa1502a6467 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"კომპიუტერის RSA გასაღების თითის ანაბეჭდია:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"ყოველთვის დართე ნება ამ კომპიუტერიდან."</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB ხარვეზების გამართვა ნებადართული არაა"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ამ მოწყობილობაზე ამჟამად შესულ მომხმარებელს არ შეუძლია USB ხარვეზების გამართვის ფუნქციის ჩართვა. ამ ფუნქციის გამოსაყენებლად, მიუერთდით მთავარ მომხმარებელს."</string> <string name="compat_mode_on" msgid="6623839244840638213">"მასშტაბი შეცვალეთ ეკრანის შესავსებად."</string> <string name="compat_mode_off" msgid="4434467572461327898">"გაწიეთ ეკრანის შესავსებად."</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"სკრინშოტის შენახვა…"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"შეიტყვეთ მეტი"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"თქვენ დაუკავშირდით <xliff:g id="VPN_APP">%1$s</xliff:g>-ს, რომელსაც თქვენი ქსელის აქტივობის, მათ შორის, ელფოსტის, აპებისა და ვებსაიტების, მონიტორინგი შეუძლია."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN-ის პარამეტრების გახსნა"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"ავტორიზაციის სანდო მონაცემების გახსნა"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"თქვენმა ადმინისტრატორმა ქსელის ჟურნალირება ჩართო, რომელიც თქვენი მოწყობილობის ტრაფიკის მონიტორინგს ახორციელებს.\n\nდამატებითი ინფორმაციისთვის დაუკავშირდით თქვენს ადმინისტრატორს."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"ამ აპს შეტყობინებების კატეგორიები არ აქვს"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"ამ აპიდან შეტყობინებების გამორთვა ვერ მოხერხდება"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">ამ აპის შეტყობინებების <xliff:g id="NUMBER_1">%d</xliff:g> კატეგორიიდან 1</item> - <item quantity="one">ამ აპის შეტყობინებების <xliff:g id="NUMBER_0">%d</xliff:g> კატეგორიიდან 1</item> + <item quantity="other">ამ აპის შეტყობინებების <xliff:g id="NUMBER_1">%s</xliff:g> კატეგორიიდან 1</item> + <item quantity="one">ამ აპის შეტყობინებების <xliff:g id="NUMBER_0">%s</xliff:g> კატეგორიიდან 1</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d წუთი</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"ბატარეის მოხმარება"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"ბატარეის დამზოგი დატენვისას მიწვდომელია"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"ბატარეის დამზოგი"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"ბატარეის დამზოგი დატენვისას მიუწვდომელია"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"ბატარეის დამზოგი"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"ამცირებს წარმადობას და ფონურ მონაცემებს"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"ღილაკი „<xliff:g id="NAME">%1$s</xliff:g>“"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"ჩაკეცვა"</string> <string name="pip_phone_close" msgid="8416647892889710330">"დახურვა"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"დასახურად ჩავლებით ჩამოიტანეთ ქვემოთ"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"მენიუ „ეკრანი ეკრანში“"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"მენიუ"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> იყენებს რეჟიმს „ეკრანი ეკრანში“"</string> <string name="pip_notification_message" msgid="5619512781514343311">"თუ არ გსურთ, რომ <xliff:g id="NAME">%s</xliff:g> ამ ფუნქციას იყენებდეს, აქ შეხებით შეგიძლიათ გახსნათ პარამეტრები და გამორთოთ ის."</string> <string name="pip_play" msgid="1417176722760265888">"დაკვრა"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"მენიუ"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> აპი"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"გაფრთხილებები"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"ბატარეა"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"ეკრანის ანაბეჭდები"</string> <string name="notification_channel_general" msgid="4525309436693914482">"ზოგადი შეტყობინებები"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"მეხსიერება"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"ფონურ რეჟიმში გაშვებული აპები"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"შეეხეთ ბატარეისა და მონაცემების მოხმარების შესახებ დეტალური ინფორმაციისთვის"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"გსურთ მობილური ინტერნეტის გამორთვა?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"ვინაიდან აპი ფარავს ნებართვის მოთხოვნას, პარამეტრების მიერ თქვენი პასუხი ვერ დასტურდება."</string> </resources> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index caa4eb9e9440..dba2addc86c4 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Бұл компьютердің RSA перне саусақ таңбасы:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Осы компьютерден әрқашан рұқсат беру"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB жөндеу рұқсат етілмеген"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Бұл құрылғыға жаңа кірген пайдаланушы USB түзетуін іске қосылмайды. Бұл мүмкіндікті пайдалану үшін негізгі пайдаланушыға ауысыңыз."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Экранды толтыру үшін ұлғайту"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Экранды толтыру үшін созу"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Скриншотты сақтауда…"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Толығырақ"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Желідегі әрекеттерді, соның ішінде электрондық хабарларды, қолданбаларды және вебсайттарды бақылайтын <xliff:g id="VPN_APP">%1$s</xliff:g> қолданбасына қосылдыңыз."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN параметрлерін ашу"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Сенімді тіркелу деректерін ашу"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Әкімші құрылғыдағы трафикті қадағалау үшін желі журналын жүргізуді қосып қойған.\n\nТолығырақ ақпарат алу үшін әкімшімен хабарласыңыз."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Бұл қолданбада хабарландыру санаттары жоқ"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Бұл қолданбаның хабарландырулары өшірілмейді"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">Осы қолданбадан <xliff:g id="NUMBER_1">%d</xliff:g> ішінен 1 хабарландыру санаты</item> - <item quantity="one">Осы қолданбадан <xliff:g id="NUMBER_0">%d</xliff:g> ішінен 1 хабарландыру санаты</item> + <item quantity="other">Осы қолданбадан <xliff:g id="NUMBER_1">%s</xliff:g> ішінен 1 хабарландыру санаты</item> + <item quantity="one">Осы қолданбадан <xliff:g id="NUMBER_0">%s</xliff:g> ішінен 1 хабарландыру санаты</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d минут</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Батареяны пайдалану"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Зарядтау кезінде Батарея үнемдегіш қол жетімді емес"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Батарея үнемдегіш"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Зарядтау кезінде \"Battery saver\" функциясы қол жетімді емес"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Battery saver"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Өнімділікті және фондық деректерді азайтады"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g> түймесі"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Кішірейту"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Жабу"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Жабу үшін төмен қарай сүйреңіз"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"\"Сурет ішіндегі сурет\" мәзірі"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Mәзір"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> \"сурет ішіндегі сурет\" режимінде"</string> <string name="pip_notification_message" msgid="5619512781514343311">"<xliff:g id="NAME">%s</xliff:g> деген пайдаланушының бұл мүмкіндікті пайдалануын қаламасаңыз, параметрлерді түртіп ашыңыз да, оларды өшіріңіз."</string> <string name="pip_play" msgid="1417176722760265888">"Ойнату"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Mәзір"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> қолданбасы"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Дабылдар"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Батарея"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Скриншоттар"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Жалпы хабарлар"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Жад"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Фонда жұмыс істеп тұрған қолданбалар"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Батарея мен деректер трафигі туралы білу үшін түртіңіз"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Мобильдік деректер өшірілсін бе?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Басқа қолданба рұқсат сұрауын жасырып тұрғандықтан, параметрлер жауабыңызды растай алмайды."</string> </resources> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index 5c74dbfc928a..8adf1542558e 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"ស្នាមម្រាមដៃ RSA របស់កុំព្យូទ័រគឺ៖ \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"អនុញ្ញាតជានិច្ចសម្រាប់កុំព្យូទ័រនេះ"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"មិនអនុញ្ញាតការកែកំហុសតាមរយៈយូអេសប៊ីទេ"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"អ្នកប្រើដែលបច្ចុប្បន្នបានចូលគណនីនៅលើឧបករណ៍នេះមិនអាចបើកការកែកំហុស USB បានទេ។ ដើម្បីប្រើមុខងារនេះ សូមប្តូរទៅអ្នកប្រើចម្បង។"</string> <string name="compat_mode_on" msgid="6623839244840638213">"ពង្រីកដើម្បីឲ្យពេញអេក្រង់"</string> <string name="compat_mode_off" msgid="4434467572461327898">"ទាញដើម្បីឲ្យពេញអេក្រង់"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"កំពុងរក្សាទុករូបថតអេក្រង់…"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"ស្វែងយល់បន្ថែម"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"អ្នកបានភ្ជាប់ទៅ <xliff:g id="VPN_APP">%1$s</xliff:g> ដែលអាចតាមដានសកម្មភាពក្នុងបណ្តាញរបស់អ្នក រួមទាំងអ៊ីមែល កម្មវិធី និងគេហទំព័រផងដែរ។"</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"បើកការកំណត់ VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"បើកព័ត៌មានសម្គាល់ខ្លួនដែលទុកចិត្ត"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"អ្នកគ្រប់គ្រងរបស់អ្នកបានបើកការធ្វើកំណត់ហេតុបណ្តាញ ដែលនឹងតាមដានចរាចរណ៍នៅលើឧបករណ៍របស់អ្នក។\n\nសម្រាប់ព័ត៌មានបន្ថែម សូមទាក់ទងអ្នកគ្រប់គ្រងរបស់អ្នក។"</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"កម្មវិធីនេះមិនមានប្រភេទនៃការជូនដំណឹងទេ"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"ការជូនដំណឹងពីកម្មវិធីនេះមិនអាចបិទបានទេ"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">ប្រភេទនៃការជូនដំណឹង 1 ក្នុងចំណោម <xliff:g id="NUMBER_1">%d</xliff:g> ដែលបានពីកម្មវិធីនេះ</item> - <item quantity="one">ប្រភេទនៃការជូនដំណឹង 1 ក្នុងចំណោម <xliff:g id="NUMBER_0">%d</xliff:g> ដែលបានពីកម្មវិធីនេះ</item> + <item quantity="other">ប្រភេទនៃការជូនដំណឹង 1 ក្នុងចំណោម <xliff:g id="NUMBER_1">%s</xliff:g> ដែលបានពីកម្មវិធីនេះ</item> + <item quantity="one">ប្រភេទនៃការជូនដំណឹង 1 ក្នុងចំណោម <xliff:g id="NUMBER_0">%s</xliff:g> ដែលបានពីកម្មវិធីនេះ</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d នាទី</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"ការប្រើប្រាស់ថ្ម"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"កម្មវិធីសន្សំថ្មមិនអាចប្រើបានអំឡុងពេលសាកថ្មទេ"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"កម្មវិធីសន្សំថ្ម"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"កម្មវិធីសន្សំថ្មមិនអាចប្រើបានអំឡុងពេលសាកថ្មទេ"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"កម្មវិធីសន្សំថ្ម"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"កាត់បន្ថយប្រតិបត្តិការ និងទិន្នន័យផ្ទៃខាងក្រោយ"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"ប៊ូតុង <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"បង្រួម"</string> <string name="pip_phone_close" msgid="8416647892889710330">"បិទ"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"អូសចុះក្រោមដើម្បីបដិសេធ"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"ម៉ឺនុយរូបក្នុងរូប"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"ម៉ឺនុយ"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ស្ថិតក្នុងមុខងាររូបក្នុងរូប"</string> <string name="pip_notification_message" msgid="5619512781514343311">"ប្រសិនបើអ្នកមិនចង់ឲ្យ <xliff:g id="NAME">%s</xliff:g> ប្រើមុខងារនេះ សូមចុចបើកការកំណត់ រួចបិទវា។"</string> <string name="pip_play" msgid="1417176722760265888">"លេង"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"ម៉ឺនុយ"</string> <string name="tuner_app" msgid="3507057938640108777">"កម្មវិធី <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"ការជូនដំណឹង"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"ថ្ម"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"រូបថតអេក្រង់"</string> <string name="notification_channel_general" msgid="4525309436693914482">"សារទូទៅ"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"ទំហំផ្ទុក"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"កម្មវិធីដែលកំពុងដំណើរការនៅផ្ទៃខាងក្រោយ"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"ចុចដើម្បីមើលព័ត៌មានលម្អិតអំពីការប្រើប្រាស់ទិន្នន័យ និងថ្ម"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"បិទទិន្នន័យចល័ត?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"ការកំណត់មិនអាចផ្ទៀងផ្ទាត់ការឆ្លើយតបរបស់អ្នកបានទេ ដោយសារកម្មវិធីកំពុងបាំងសំណើសុំការអនុញ្ញាត។"</string> </resources> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index 8422ac879a84..087da86cff74 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"ಕಂಪ್ಯೂಟರ್ನ RSA ಕೀ ಫಿಂಗರ್ ಪ್ರಿಂಟ್ ಹೀಗಿದೆ :\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"ಈ ಕಂಪ್ಯೂಟರ್ನಿಂದ ಯಾವಾಗಲೂ ಅನುಮತಿಸಿ"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB ಡೀಬಗ್ ಮಾಡುವಿಕೆಯನ್ನು ಅನುಮತಿಸಲಾಗಿಲ್ಲ"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ಬಳಕೆದಾರರು ಪ್ರಸ್ತುತ ಈ ಸಾಧನಕ್ಕೆ ಸೈನ್ ಇನ್ ಮಾಡಿದ್ದಾರೆ USB ಡೀಬಗ್ ಮಾಡುವುದನ್ನು ಆನ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ಈ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಬಳಸಲು, ಪ್ರಾಥಮಿಕ ಬಳಕೆದಾರರಿಗೆ ಬದಲಾಯಿಸಿ."</string> <string name="compat_mode_on" msgid="6623839244840638213">"ಪರದೆ ತುಂಬಿಸಲು ಝೂಮ್ ಮಾಡು"</string> <string name="compat_mode_off" msgid="4434467572461327898">"ಪರದೆ ತುಂಬಿಸಲು ವಿಸ್ತಾರಗೊಳಿಸು"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಉಳಿಸಲಾಗುತ್ತಿದೆ…"</string> @@ -260,10 +259,10 @@ <string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> ಸೆಟ್ಟಿಂಗ್ಗಳು"</string> <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ಪರದೆಯು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ತಿರುಗುತ್ತದೆ."</string> <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"ಪರದೆಯನ್ನು ಲ್ಯಾಂಡ್ಸ್ಕೇಪ್ ಓರಿಯಂಟೇಶನ್ನಲ್ಲಿ ಲಾಕ್ ಮಾಡಲಾಗಿದೆ."</string> - <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"ಪರದೆಯನ್ನು ಪೋಟ್ರೇಟ್ ಓರಿಯಂಟೇಶನ್ನಲ್ಲಿ ಲಾಕ್ ಮಾಡಲಾಗಿದೆ."</string> + <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"ಪರದೆಯನ್ನು ಪೋರ್ಟ್ರೇಟ್ ಓರಿಯಂಟೇಶನ್ನಲ್ಲಿ ಲಾಕ್ ಮಾಡಲಾಗಿದೆ."</string> <string name="accessibility_rotation_lock_off_changed" msgid="8134601071026305153">"ಪರದೆಯು ಈಗ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ತಿರುಗುತ್ತದೆ."</string> <string name="accessibility_rotation_lock_on_landscape_changed" msgid="3135965553707519743">"ಪರದೆಯು ಇದೀಗ ಲ್ಯಾಂಡ್ಸ್ಕೇಪ್ ಒರಿಯಂಟೇಶನ್ನಲ್ಲಿ ಲಾಕ್ ಆಗಿದೆ."</string> - <string name="accessibility_rotation_lock_on_portrait_changed" msgid="8922481981834012126">"ಪರದೆಯು ಇದೀಗ ಪೋಟ್ರೇಟ್ ಒರಿಯಂಟೇಶನ್ನಲ್ಲಿ ಲಾಕ್ ಆಗಿದೆ."</string> + <string name="accessibility_rotation_lock_on_portrait_changed" msgid="8922481981834012126">"ಪರದೆಯು ಇದೀಗ ಪೋರ್ಟ್ರೇಟ್ ಒರಿಯಂಟೇಶನ್ನಲ್ಲಿ ಲಾಕ್ ಆಗಿದೆ."</string> <string name="dessert_case" msgid="1295161776223959221">"ಡೆಸರ್ಟ್ ಕೇಸ್"</string> <string name="start_dreams" msgid="5640361424498338327">"ಸ್ಕ್ರೀನ್ ಸೇವರ್"</string> <string name="ethernet_label" msgid="7967563676324087464">"ಇಥರ್ನೆಟ್"</string> @@ -280,7 +279,7 @@ <string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"ಪರದೆಯನ್ನು ಸ್ವಯಂ-ತಿರುಗಿಸಿ"</string> <string name="accessibility_quick_settings_rotation_value" msgid="8187398200140760213">"<xliff:g id="ID_1">%s</xliff:g> ಮೋಡ್"</string> <string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"ತಿರುಗುವಿಕೆ ಲಾಕ್ ಆಗಿದೆ"</string> - <string name="quick_settings_rotation_locked_portrait_label" msgid="5102691921442135053">"ಪೋಟ್ರೇಟ್"</string> + <string name="quick_settings_rotation_locked_portrait_label" msgid="5102691921442135053">"ಪೋರ್ಟ್ರೇಟ್"</string> <string name="quick_settings_rotation_locked_landscape_label" msgid="8553157770061178719">"ಲ್ಯಾಂಡ್ಸ್ಕೇಪ್"</string> <string name="quick_settings_ime_label" msgid="7073463064369468429">"ಇನ್ಪುಟ್ ವಿಧಾನ"</string> <string name="quick_settings_location_label" msgid="5011327048748762257">"ಸ್ಥಳ"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"ನೀವು ಇಮೇಲ್ಗಳು, ಅಪ್ಲಿಕೇಶನ್ಗಳು ಮತ್ತು ವೆಬ್ಸೈಟ್ಗಳನ್ನು ಒಳಗೊಂಡಂತೆ ನಿಮ್ಮ ನೆಟ್ವರ್ಕ್ ಚಟುವಟಿಕೆಯ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದಾದ, <xliff:g id="VPN_APP">%1$s</xliff:g> ಗೆ ನೀವು ಸಂಪರ್ಕಗೊಂಡಿರುವಿರಿ."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ತೆರೆಯಿರಿ"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"ವಿಶ್ವಾಸಾರ್ಹ ರುಜುವಾತುಗಳನ್ನು ತೆರೆಯಿರಿ"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ನೆಟ್ವರ್ಕ್ ಲಾಗಿಂಗ್ ಆನ್ ಮಾಡಿದ್ದಾರೆ. ಇದು ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿನ ಟ್ರಾಫಿಕ್ ಮೇಲೆ ನಿಗಾ ಇರಿಸುತ್ತದೆ.\n\nಹೆಚ್ಚಿನ ಮಾಹಿತಿಗೆ ನಿಮ್ಮ ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string> @@ -499,7 +497,7 @@ <string name="stream_bluetooth_sco" msgid="2055645746402746292">"ಬ್ಲೂಟೂತ್"</string> <string name="stream_dtmf" msgid="2447177903892477915">"ಡ್ಯುಯಲ್ ಬಹು ಟೋನ್ ಆವರ್ತನೆ"</string> <string name="stream_accessibility" msgid="301136219144385106">"ಪ್ರವೇಶಿಸುವಿಕೆ"</string> - <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. ಅನ್ಮ್ಯೂಟ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> + <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. ಅನ್ಮ್ಯೂಟ್ ಮಾಡುವುದಕ್ಕಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ."</string> <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. ಕಂಪನಕ್ಕೆ ಹೊಂದಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ. ಪ್ರವೇಶಿಸುವಿಕೆ ಸೇವೆಗಳನ್ನು ಮ್ಯೂಟ್ ಮಾಡಬಹುದು."</string> <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. ಮ್ಯೂಟ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ. ಪ್ರವೇಶಿಸುವಿಕೆ ಸೇವೆಗಳನ್ನು ಮ್ಯೂಟ್ ಮಾಡಬಹುದು."</string> <string name="volume_stream_content_description_vibrate_a11y" msgid="6427727603978431301">"%1$s. ವೈಬ್ರೇಟ್ ಮಾಡಲು ಹೊಂದಿಸುವುದಕ್ಕಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಅಧಿಸೂಚನೆ ವರ್ಗಗಳನ್ನು ಹೊಂದಿಲ್ಲ"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"ಈ ಅಪ್ಲಿಕೇಶನ್ನಿಂದ ಅಧಿಸೂಚನೆಗಳನ್ನು ಆಫ್ ಮಾಡಲಾಗುವುದಿಲ್ಲ"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">ಈ ಅಪ್ಲಿಕೇಶನ್ನಿಂದ <xliff:g id="NUMBER_1">%d</xliff:g> ಅಧಿಸೂಚನೆ ವರ್ಗಗಳಲ್ಲಿ 1 ವರ್ಗ</item> - <item quantity="other">ಈ ಅಪ್ಲಿಕೇಶನ್ನಿಂದ <xliff:g id="NUMBER_1">%d</xliff:g> ಅಧಿಸೂಚನೆ ವರ್ಗಗಳಲ್ಲಿ 1 ವರ್ಗ</item> + <item quantity="one">ಈ ಅಪ್ಲಿಕೇಶನ್ನಿಂದ <xliff:g id="NUMBER_1">%s</xliff:g> ಅಧಿಸೂಚನೆ ವರ್ಗಗಳಲ್ಲಿ 1 ವರ್ಗ</item> + <item quantity="other">ಈ ಅಪ್ಲಿಕೇಶನ್ನಿಂದ <xliff:g id="NUMBER_1">%s</xliff:g> ಅಧಿಸೂಚನೆ ವರ್ಗಗಳಲ್ಲಿ 1 ವರ್ಗ</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="other">%d ನಿಮಿಷಗಳು</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"ಬ್ಯಾಟರಿ ಬಳಕೆ"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"ಚಾರ್ಜಿಂಗ್ ಸಮಯದಲ್ಲಿ ಬ್ಯಾಟರಿ ಸೇವರ್ ಲಭ್ಯವಿರುವುದಿಲ್ಲ"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"ಬ್ಯಾಟರಿ ಸೇವರ್"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"ಚಾರ್ಜಿಂಗ್ ಸಮಯದಲ್ಲಿ ಬ್ಯಾಟರಿ ಸೇವರ್ ಲಭ್ಯವಿರುವುದಿಲ್ಲ"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"ಬ್ಯಾಟರಿ ಸೇವರ್"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"ಕಾರ್ಯಕ್ಷಮತೆ ಮತ್ತು ಹಿನ್ನೆಲೆ ಡೇಟಾವನ್ನು ಕಡಿಮೆ ಮಾಡುತ್ತದೆ"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g> ಬಟನ್"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"ಕುಗ್ಗಿಸಿ"</string> <string name="pip_phone_close" msgid="8416647892889710330">"ಮುಚ್ಚಿ"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ವಜಾಗೊಳಿಸಲು ಕೆಳಕ್ಕೆ ಡ್ರ್ಯಾಗ್ ಮಾಡಿ"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"ಚಿತ್ರದಲ್ಲಿ ಚಿತ್ರ ಮೆನು"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"ಮೆನು"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ಚಿತ್ರದಲ್ಲಿನ ಚಿತ್ರದಲ್ಲಿದೆ"</string> <string name="pip_notification_message" msgid="5619512781514343311">"<xliff:g id="NAME">%s</xliff:g> ಈ ವೈಶಿಷ್ಟ್ಯ ಬಳಸುವುದನ್ನು ನೀವು ಬಯಸದಿದ್ದರೆ, ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ತೆರೆಯಲು ಮತ್ತು ಅದನ್ನು ಆಫ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> <string name="pip_play" msgid="1417176722760265888">"ಪ್ಲೇ"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"ಮೆನು"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> ಅಪ್ಲಿಕೇಶನ್"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"ಎಚ್ಚರಿಕೆಗಳು"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"ಬ್ಯಾಟರಿ"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"ಸ್ಕ್ರೀನ್ಶಾಟ್ಗಳು"</string> <string name="notification_channel_general" msgid="4525309436693914482">"ಸಾಮಾನ್ಯ ಸಂದೇಶಗಳು"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"ಸಂಗ್ರಹಣೆ"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"ಅಪ್ಲಿಕೇಶನ್ಗಳು ಹಿನ್ನೆಲೆಯಲ್ಲಿ ರನ್ ಆಗುತ್ತಿವೆ"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"ಬ್ಯಾಟರಿ,ಡೇಟಾ ಬಳಕೆಯ ವಿವರಗಳಿಗಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"ಮೊಬೈಲ್ ಡೇಟಾ ಆಫ್ ಮಾಡಬೇಕೆ?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"ಅನುಮತಿ ವಿನಂತಿಯನ್ನು ಅಪ್ಲಿಕೇಶನ್ ಮರೆಮಾಚುತ್ತಿರುವ ಕಾರಣ, ಸೆಟ್ಟಿಂಗ್ಗಳಿಗೆ ನಿಮ್ಮ ಪ್ರತಿಕ್ರಿಯೆಯನ್ನು ಪರಿಶೀಲಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string> </resources> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 1815eca842a1..092b6bff71b0 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"컴퓨터 RSA 키 지문:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"이 컴퓨터에서 항상 허용"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB 디버깅이 허용되지 않음"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"현재 이 기기에 로그인한 사용자는 USB 디버깅을 사용 설정할 수 없습니다. 이 기능을 사용하려면 기본 사용자로 전환하세요."</string> <string name="compat_mode_on" msgid="6623839244840638213">"전체화면 모드로 확대"</string> <string name="compat_mode_off" msgid="4434467572461327898">"전체화면 모드로 확대"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"캡쳐화면 저장 중..."</string> @@ -459,8 +458,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"자세히 알아보기"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"<xliff:g id="VPN_APP">%1$s</xliff:g>에 연결되었습니다. 이 앱은 이메일, 앱, 웹사이트와 같은 내 네트워크 활동을 모니터링할 수 있습니다."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"공개 VPN 설정"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"신뢰할 수 있는 사용자 인증 정보 열기"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"관리자가 기기에서 발생하는 트래픽을 모니터링하는 네트워크 로깅을 사용 설정했습니다.\n\n자세한 정보는 관리자에게 문의하세요."</string> @@ -560,8 +558,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"이 앱에는 알림 카테고리가 없습니다."</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"이 앱의 알림을 사용 중지할 수 없습니다."</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">이 앱에서 <xliff:g id="NUMBER_1">%d</xliff:g>개의 알림 카테고리 중 1개가 정의됨</item> - <item quantity="one">이 앱에서 <xliff:g id="NUMBER_0">%d</xliff:g>개의 알림 카테고리 중 1개가 정의됨</item> + <item quantity="other">이 앱에서 <xliff:g id="NUMBER_1">%s</xliff:g>개의 알림 카테고리 중 1개가 정의됨</item> + <item quantity="one">이 앱에서 <xliff:g id="NUMBER_0">%s</xliff:g>개의 알림 카테고리 중 1개가 정의됨</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -589,8 +587,8 @@ <item quantity="one">%d분</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"배터리 사용량"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"충전하는 동안 배터리 세이버는 사용할 수 없습니다."</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"배터리 세이버"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"충전 중에는 배터리 세이버를 사용할 수 없습니다."</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"배터리 세이버"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"성능 및 백그라운드 데이터를 줄입니다."</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g> 버튼"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -730,7 +728,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"최소화"</string> <string name="pip_phone_close" msgid="8416647892889710330">"닫기"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"아래로 드래그하여 닫기"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"PIP 메뉴"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"메뉴"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g>에서 PIP 사용 중"</string> <string name="pip_notification_message" msgid="5619512781514343311">"<xliff:g id="NAME">%s</xliff:g>에서 이 기능이 사용되는 것을 원하지 않는 경우 탭하여 설정을 열고 기능을 사용 중지하세요."</string> <string name="pip_play" msgid="1417176722760265888">"재생"</string> @@ -758,8 +756,7 @@ <string name="tuner_menu" msgid="191640047241552081">"메뉴"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> 앱"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"알림"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"배터리"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"스크린샷"</string> <string name="notification_channel_general" msgid="4525309436693914482">"일반 메시지"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"저장공간"</string> @@ -780,4 +777,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"백그라운드에서 실행 중인 앱"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"탭하여 배터리 및 데이터 사용량 확인"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"모바일 데이터를 사용 중지하시겠습니까?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"앱이 권한 요청을 가리고 있기 때문에 설정에서 내 응답을 확인할 수 없습니다."</string> </resources> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 40d8585afb63..ac6e7086e70f 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Компүтердин RSA ачкычынын контролдук суммасы:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Бул компүтерден дайыма уруксат берилсин"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB мүчүлүштүктөрүн оңдоого уруксат жок"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Учурда бул түзмөккө каттоо эсеби менен кирген колдонуучу USB мүчүлүштүктөрүн оңдоо функциясын күйгүзө албай жатат. Бул функцияны колдонуу үчүн негизги колдонуучунун каттоо эсебине которулуңуз."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Экрнд тлтр ү. чен өлч өзг"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Экранды толтуруу ү-н чоюу"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Скриншот сакталууда…"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Кеңири маалымат"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Электрондук почта, колдонмолор жана вебсайттар сыяктуу тармактагы аракеттериңизди тескей турган <xliff:g id="VPN_APP">%1$s</xliff:g> колдонмосуна туташып турасыз."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN жөндөөлөрүн ачуу"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Ишенимдүү эсептик дайындар баракчасын ачыңыз"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Администраторуңуз тармактын таржымалын алууну иштетти, андыктан түзмөгүңүздөгү трафик көзөмөлгө алынды.\n\nКеңири маалымат алуу үчүн администраторуңузга кайрылыңыз."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Бул колдонмонун эскертме категориялары жок"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Бул колдонмонун эскертмелерин өчүрүүгө болбойт"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">Бул колдонмодогу <xliff:g id="NUMBER_1">%d</xliff:g> эскертме категориянын ичинен 1 категория</item> - <item quantity="one">Бул колдонмодогу <xliff:g id="NUMBER_0">%d</xliff:g> эскертме категориянын ичинен 1 категория</item> + <item quantity="other">Бул колдонмодогу <xliff:g id="NUMBER_1">%s</xliff:g> эскертме категориянын ичинен 1 категория</item> + <item quantity="one">Бул колдонмодогу <xliff:g id="NUMBER_0">%s</xliff:g> эскертме категориянын ичинен 1 категория</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d мүнөт</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Батарея колдонулушу"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Батареяны үнөмдөгүч түзмөк кубатталып жатканда иштебейт"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Батареяны үнөмдөгүч"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Батареяны үнөмдөгүч түзмөк кубатталып жатканда иштебейт"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Батареяны үнөмдөгүч"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Иштин майнаптуулугун начарлатып, фондук дайындарды чектейт"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g> баскычы"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Башкы бет"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Кичирейтүү"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Жабуу"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Четке кагуу үчүн төмөн сүйрөңүз"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Сүрөт ичиндеги сүрөт менюсу"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Меню"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> – сүрөт ичиндеги сүрөт"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Эгер <xliff:g id="NAME">%s</xliff:g> колдонмосу бул функцияны пайдаланбасын десеңиз, жөндөөлөрдү ачып туруп, аны өчүрүп коюңуз."</string> <string name="pip_play" msgid="1417176722760265888">"Ойнотуу"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Меню"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> колдонмосу"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Эскертүүлөр"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Батарея"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Скриншоттор"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Жалпы билдирүүлөр"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Сактагыч"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Фондо иштеп жаткан колдонмолор"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Батареянын кубаты жана трафиктин көлөмү жөнүндө билүү үчүн таптап коюңуз"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Мобилдик Интернетти өчүрөсүзбү?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Уруксат берүү сурамыңыз көрүнбөй калгандыктан, Жөндөөлөр жообуңузду ырастай албай жатат."</string> </resources> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index a22d6e613960..941ef71101bd 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"ລາຍນິ້ມື RSA ຂອງຄອມພິວເຕີແມ່ນ:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"ອະນຸຍາດຈາກຄອມພິວເຕີນີ້ຕະຫຼອດ"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"ບໍ່ອະນຸຍາດໃຫ້ມີການແກ້ໄຂບັນຫາ USB"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ຜູ້ໃຊ້ທີ່ກຳລັງເຂົ້າສູ່ລະບົບອຸປະກອນຢູ່ໃນຕອນນີ້ບໍ່ສາມາດເປີດໃຊ້ການດີບັກ USB ໄດ້. ເພື່ອໃຊ້ຄຸນສົມບັດນີ້, ໃຫ້ສະຫຼັບໄປໃຊ້ຜູ້ໃຊ້ຫຼັກ."</string> <string name="compat_mode_on" msgid="6623839244840638213">"ຊູມໃຫ້ເຕັມໜ້າຈໍ"</string> <string name="compat_mode_off" msgid="4434467572461327898">"ປັບໃຫ້ເຕັມໜ້າຈໍ"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"ກຳລັງບັນທຶກຮູບໜ້າຈໍ"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"ສຶກສາເພີ່ມເຕີມ"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"ທ່ານເຊື່ອມຕໍ່ກັບ <xliff:g id="VPN_APP">%1$s</xliff:g> ແລ້ວ, ເຊິ່ງສາມາດຕິດຕາມການເຄື່ອນໄຫວເຄືອຂ່າຍ, ຮວມທັງອີເມວ, ແອັບ ແລະ ເວັບໄຊຕ່າງໆໄດ້."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"ເປີດການຕັ້ງຄ່າ VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"ເປີດຂໍ້ມູນການຮັບຮອງທີ່ເຊື່ອຖືໄດ້"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Your admin has turned on network logging, which monitors traffic on your device.\n\nFor more information, contact your admin."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"ແອັບນີ້ບໍ່ມີໝວດໝູ່ການແຈ້ງເຕືອນ"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"ການແຈ້ງເຕືອນຈາກແອັບນີ້ບໍ່ສາມາດປິດໄວ້ໄດ້"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 ຈາກທັງໝົດ <xliff:g id="NUMBER_1">%d</xliff:g> ໝວດໝູ່ການແຈ້ງເຕືອນຈາກແອັບນີ້</item> - <item quantity="one">1 ຈາກທັງໝົດ <xliff:g id="NUMBER_0">%d</xliff:g> ໝວດໝູ່ການແຈ້ງເຕືອນຈາກແອັບນີ້</item> + <item quantity="other">1 ຈາກທັງໝົດ <xliff:g id="NUMBER_1">%s</xliff:g> ໝວດໝູ່ການແຈ້ງເຕືອນຈາກແອັບນີ້</item> + <item quantity="one">1 ຈາກທັງໝົດ <xliff:g id="NUMBER_0">%s</xliff:g> ໝວດໝູ່ການແຈ້ງເຕືອນຈາກແອັບນີ້</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d ນາທີ</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"ການໃຊ້ແບັດເຕີຣີ"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"ຕົວປະຢັດແບັດເຕີຣີບໍ່ມີໃຫ້ນຳໃຊ້ໃນລະຫວ່າງການສາກ"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"ຕົວປະຢັດແບັດເຕີຣີ"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"ບໍ່ສາມາດໃຊ້ຕົວປະຢັດແບັດເຕີຣີໃນຂະນະທີ່ກຳລັງສາກໄຟໄດ້"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"ຕົວປະຢັດແບັດເຕີຣີ"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"ຫຼຸດປະສິທິພາບການໃຊ້ງານ ແລະ ຂໍ້ມູນພື້ນຫຼັງ"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"ປຸ່ມ <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"ຫຍໍ້"</string> <string name="pip_phone_close" msgid="8416647892889710330">"ປິດ"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ລາກລົງເພື່ອປິດໄວ້"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"ເມນູຊ້ອນຮູບພາບ"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"ເມນູ"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ແມ່ນເປັນການສະແດງຜົນຫຼາຍຢ່າງພ້ອມກັນ"</string> <string name="pip_notification_message" msgid="5619512781514343311">"ຫາກທ່ານບໍ່ຕ້ອງການ <xliff:g id="NAME">%s</xliff:g> ໃຫ້ໃຊ້ຄຸນສົມບັດນີ້, ໃຫ້ແຕະເພື່ອເປີດການຕັ້ງຄ່າ ແລ້ວປິດມັນໄວ້."</string> <string name="pip_play" msgid="1417176722760265888">"ຫຼິ້ນ"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"ເມນູ"</string> <string name="tuner_app" msgid="3507057938640108777">"ແອັບ <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"ການເຕືອນ"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"ແບັດເຕີຣີ"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"ຮູບຖ່າຍໜ້າຈໍ"</string> <string name="notification_channel_general" msgid="4525309436693914482">"ຂໍ້ຄວາມທົ່ວໄປ"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"ບ່ອນເກັບຂໍ້ມູນ"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"ແອັບທີ່ກຳລັງເຮັດວຽກໃນພື້ນຫຼັງ"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"ແຕະເພື່ອເບິ່ງລາຍລະອຽດການນຳໃຊ້ແບັດເຕີຣີ ແລະ ອິນເຕີເນັດ"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"ປິດອິນເຕີເນັດມືຖືໄວ້ບໍ?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"ເນື່ອງຈາກມີແອັບໃດໜຶ່ງກຳລັງຂັດຂວາງການຂໍອະນຸຍາດ, ການຕັ້ງຄ່າຈຶ່ງບໍ່ສາມາດຢັ້ງຢືນການຕອບຮັບຂອງທ່ານໄດ້."</string> </resources> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 014c9bf34352..d003d290c458 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -66,8 +66,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Šio kompiuterio RSA rakto kontrolinis kodas yra:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Visada leisti iš šio kompiuterio"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB derinimas neleidžiamas"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Šiuo metu prie įrenginio prisijungęs naudotojas negali įjungti USB derinimo. Kad galėtumėte naudoti šią funkciją, perjunkite į pagrindinį naudotoją."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Keisti mast., kad atit. ekr."</string> <string name="compat_mode_off" msgid="4434467572461327898">"Ištempti, kad atit. ekr."</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Išsaugoma ekrano kopija..."</string> @@ -461,8 +460,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Sužinoti daugiau"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Esate prisijungę prie programos „<xliff:g id="VPN_APP">%1$s</xliff:g>“, kuri gali stebėti tinklo veiklą, įskaitant el. laiškus, programas ir svetaines."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Atidaryti VPN nustatymus"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Atidaryti patikimų prisijungimo duomenų puslapį"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administratorius įjungė tinklo duomenų įrašymą į žurnalą. Įjungus šią funkciją stebimas srautas jūsų įrenginyje.\n\nJei reikia daugiau informacijos, susisiekite su administratoriumi."</string> @@ -562,10 +560,10 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Šioje programoje nėra pranešimų kategorijų"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Šios programos pranešimų negalima išjungti"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 iš <xliff:g id="NUMBER_1">%d</xliff:g> šios programos pranešimų kategorijos</item> - <item quantity="few">1 iš <xliff:g id="NUMBER_1">%d</xliff:g> šios programos pranešimų kategorijų</item> - <item quantity="many">1 iš <xliff:g id="NUMBER_1">%d</xliff:g> šios programos pranešimų kategorijos</item> - <item quantity="other">1 iš <xliff:g id="NUMBER_1">%d</xliff:g> šios programos pranešimų kategorijų</item> + <item quantity="one">1 iš <xliff:g id="NUMBER_1">%s</xliff:g> šios programos pranešimų kategorijos</item> + <item quantity="few">1 iš <xliff:g id="NUMBER_1">%s</xliff:g> šios programos pranešimų kategorijų</item> + <item quantity="many">1 iš <xliff:g id="NUMBER_1">%s</xliff:g> šios programos pranešimų kategorijos</item> + <item quantity="other">1 iš <xliff:g id="NUMBER_1">%s</xliff:g> šios programos pranešimų kategorijų</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"„<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>“, „<xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>“"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -599,8 +597,8 @@ <item quantity="other">%d minučių</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Akum. energ. vartoj."</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Akumuliatoriaus tausojimo priemonė nepasiekiama įkraunant"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Akumuliatoriaus tausojimo priemonė"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Akumuliatoriaus tausojimo priemonė nepasiekiama įkraunant"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Akumuliatoriaus tausojimo priemonė"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Sumažinamas našumas ir foninių duomenų naudojimas"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Mygtukas <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Pagrindinis"</string> @@ -740,7 +738,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Sumažinti"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Uždaryti"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Nuvilkite žemyn, kad atsisakytumėte"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Vaizdo vaizde meniu"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Meniu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> rodom. vaizdo vaizde"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Jei nenorite, kad „<xliff:g id="NAME">%s</xliff:g>“ naudotų šią funkciją, palietę atidarykite nustatymus ir išjunkite ją."</string> <string name="pip_play" msgid="1417176722760265888">"Leisti"</string> @@ -768,8 +766,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Meniu"</string> <string name="tuner_app" msgid="3507057938640108777">"Programa „<xliff:g id="APP">%1$s</xliff:g>“"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Įspėjimai"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Akumuliatorius"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Ekrano kopijos"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Bendrieji pranešimai"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Saugykla"</string> @@ -790,4 +787,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Programos, veikiančios fone"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Palieskite ir sužinokite išsamios informacijos apie akumuliatoriaus bei duomenų naudojimą"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Išjungti mobiliojo ryšio duomenis?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Kadangi programa užstoja leidimo užklausą, nustatymuose negalima patvirtinti jūsų atsakymo."</string> </resources> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 33a63cfef529..e101ff0f8f6c 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -65,8 +65,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Datora RSA atslēgas ciparfails: \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Vienmēr atļaut no šī datora"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB atkļūdošana nav atļauta"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Lietotājs, kurš pašlaik ir pierakstījies šajā ierīcē, nevar iespējot USB atkļūdošanu. Lai izmantotu šo funkciju, pārslēdzieties uz galveno lietotāju."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Tālumm., lai aizp. ekr."</string> <string name="compat_mode_off" msgid="4434467572461327898">"Stiepiet, lai aizp. ekr."</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Saglabā ekrānuzņēmumu…"</string> @@ -459,8 +458,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Uzzināt vairāk"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Ir izveidots savienojums ar lietotni <xliff:g id="VPN_APP">%1$s</xliff:g>, kas var pārraudzīt jūsu darbības tīklā, tostarp e-pasta ziņojumus, lietotnes un vietnes."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Atvērt VPN iestatījumus"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Atvērt uzticamo akreditācijas datu sadaļu"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administrators ir ieslēdzis tīkla reģistrēšanu, kuru izmanto, lai pārraudzītu datplūsmu jūsu ierīcē.\n\nLai iegūtu plašāku informāciju, sazinieties ar administratoru."</string> @@ -560,9 +558,9 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Paziņojumu kategorijas šajā lietotnē nav pieejamas."</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Paziņojumus no šīs lietotnes nevar izslēgt"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="zero">1 no <xliff:g id="NUMBER_1">%d</xliff:g> šīs lietotnes paziņojumu kategorijām.</item> - <item quantity="one">1 no <xliff:g id="NUMBER_1">%d</xliff:g> šīs lietotnes paziņojumu kategorijas.</item> - <item quantity="other">1 no <xliff:g id="NUMBER_1">%d</xliff:g> šīs lietotnes paziņojumu kategorijām.</item> + <item quantity="zero">1 no <xliff:g id="NUMBER_1">%s</xliff:g> šīs lietotnes paziņojumu kategorijām.</item> + <item quantity="one">1 no <xliff:g id="NUMBER_1">%s</xliff:g> šīs lietotnes paziņojumu kategorijas.</item> + <item quantity="other">1 no <xliff:g id="NUMBER_1">%s</xliff:g> šīs lietotnes paziņojumu kategorijām.</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -593,8 +591,8 @@ <item quantity="other">%d minūtes</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Akumulatora lietojums"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Akumulatora jaudas taupīšanas režīms uzlādes laikā nav pieejams."</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Akumulatora jaudas taupīšanas režīms"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Akumulatora jaudas taupīšanas režīms nav pieejams uzlādes laikā."</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Akumulatora jaudas taupīšanas režīms"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Samazina veiktspēju un fona datus."</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Poga <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Sākumvietas taustiņš"</string> @@ -734,7 +732,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizēt"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Aizvērt"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Velciet lejup, lai noraidītu"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Izvēlne attēlam attēlā"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Izvēlne"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ir attēlā attēlā"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Ja nevēlaties lietotnē <xliff:g id="NAME">%s</xliff:g> izmantot šo funkciju, pieskarieties, lai atvērtu iestatījumus un izslēgtu funkciju."</string> <string name="pip_play" msgid="1417176722760265888">"Atskaņot"</string> @@ -762,8 +760,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Izvēlne"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> lietotne"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Brīdinājumi"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Akumulators"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Ekrānuzņēmumi"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Vispārīgi ziņojumi"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Krātuve"</string> @@ -784,4 +781,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Lietotnes, kas darbojas fonā"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Pieskarieties, lai skatītu detalizētu informāciju par akumulatora un datu lietojumu"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Vai izslēgt mobilos datus?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Lietotne Iestatījumi nevar verificēt jūsu atbildi, jo cita lietotne aizsedz atļaujas pieprasījumu."</string> </resources> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index b7c53bafec5b..f299c4421a23 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Клучниот отпечаток на RSA на компјутерот е:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Секогаш дозволувај од овој компјутер"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Отстранувањето грешки на USB не е дозволено"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Корисникот што моментално е најавен на уредов не може да вклучи отстранување грешки на USB. За да ја користите функцијава, префрлете се на примарниот корисник."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Зумирај да се исполни екранот"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Растегни да се исполни екранот"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Сликата на екранот се зачувува..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Дознајте повеќе"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Поврзани сте на <xliff:g id="VPN_APP">%1$s</xliff:g>, којашто може да ја следи вашата активност на мрежата, вклучувајќи ги е-пораките, апликациите и веб-сајтовите."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Отворете „Поставки за VPN“"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Отворете ги доверливите акредитиви"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Вашиот администратор вклучил евиденција на мрежата, што подразбира следење на сообраќајот на вашиот уред.\n\nЗа повеќе информации, контактирајте со администраторот."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Апликацијава нема катерии известувања"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Известувањата од апликацијава не може да се исклучат"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 од <xliff:g id="NUMBER_1">%d</xliff:g> категорија известувања од апликацијава</item> - <item quantity="other">1 од <xliff:g id="NUMBER_1">%d</xliff:g> категории известувања од апликацијава</item> + <item quantity="one">1 од <xliff:g id="NUMBER_1">%s</xliff:g> категорија известувања од апликацијава</item> + <item quantity="other">1 од <xliff:g id="NUMBER_1">%s</xliff:g> категории известувања од апликацијава</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="other">%d минути</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Користење батерија"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Штедачот на батерија не е достапен при полнење"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Штедач на батерија"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Штедачот на батерија не е достапен при полнење"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Штедач на батерија"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Ја намалува изведбата и податоците во заднина"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Копче <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home-копче"</string> @@ -598,8 +596,8 @@ <string name="keyboard_key_dpad_left" msgid="1346446024676962251">"Стрелка налево"</string> <string name="keyboard_key_dpad_right" msgid="3317323247127515341">"Стрелка надесно"</string> <string name="keyboard_key_dpad_center" msgid="2566737770049304658">"Центар"</string> - <string name="keyboard_key_tab" msgid="3871485650463164476">"Картичка"</string> - <string name="keyboard_key_space" msgid="2499861316311153293">"Празно место"</string> + <string name="keyboard_key_tab" msgid="3871485650463164476">"Tab"</string> + <string name="keyboard_key_space" msgid="2499861316311153293">"Space"</string> <string name="keyboard_key_enter" msgid="5739632123216118137">"Внеси"</string> <string name="keyboard_key_backspace" msgid="1559580097512385854">"Бришење наназад"</string> <string name="keyboard_key_media_play_pause" msgid="3861975717393887428">"Пушти/Паузирај"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Минимизирај"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Затвори"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Повлечете надолу за да отфрлите"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Мени слика во слика"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Мени"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> е во слика во слика"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Ако не сакате <xliff:g id="NAME">%s</xliff:g> да ја користи функцијава, допрете за да ги отворите поставките и да ја исклучите."</string> <string name="pip_play" msgid="1417176722760265888">"Пушти"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Мени"</string> <string name="tuner_app" msgid="3507057938640108777">"Апликација <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Предупредувања"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Батерија"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Слики од екранот"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Општи пораки"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Капацитет"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Апликациите се извршуваат во заднина"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Допрете за детали за батеријата и потрошениот сообраќај"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Да се исклучи мобилниот интернет?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Бидејќи апликацијата го прикрива барањето за дозвола, „Поставките“ не може да го потврдат вашиот одговор."</string> </resources> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index 9128c7cc5536..6a0c8cdacf6c 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"ഈ കമ്പ്യൂട്ടറിന്റെ RSA കീ ഫിംഗർപ്രിന്റ് ഇതാണ്:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"ഈ കമ്പ്യൂട്ടറിൽ നിന്ന് എല്ലായ്പ്പോഴും അനുവദിക്കുക"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB ഡീബഗ്ഗിംഗ് അനുവദനീയമല്ല"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ഉപകരണത്തിൽ ഇപ്പോൾ സൈൻ ഇൻ ചെയ്തിരിക്കുന്ന ഉപയോക്താവിന് USB ഡീബഗ്ഗിംഗ് ഓണാക്കാനാകില്ല. ഈ ഫീച്ചർ ഉപയോഗിക്കാൻ പ്രാഥമിക ഉപയോക്താവിലേക്ക് മാറുക."</string> <string name="compat_mode_on" msgid="6623839244840638213">"സ്ക്രീനിൽ ഉൾക്കൊള്ളിക്കാൻ സൂം ചെയ്യുക"</string> <string name="compat_mode_off" msgid="4434467572461327898">"സ്ക്രീനിൽ ഉൾക്കൊള്ളിക്കാൻ വലിച്ചുനീട്ടുക"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"കൂടുതലറിയുക"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"നിങ്ങൾ <xliff:g id="VPN_APP">%1$s</xliff:g> ആപ്പിലേക്ക് കണക്റ്റുചെയ്തിരിക്കുന്നു, ഇമെയിലുകൾ, ആപ്സ്, വെബ്സൈറ്റുകൾ എന്നിവ ഉൾപ്പെടെ നിങ്ങളുടെ നെറ്റ്വർക്ക് ആക്റ്റിവിറ്റി നിരീക്ഷിക്കാൻ ഈ ആപ്പിന് കഴിയും."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" 5"</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN ക്രമീകരണം തുറക്കുക"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" 5"</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"പരിചിത ക്രെഡൻഷ്യലുകൾ തുറക്കുക"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"നിങ്ങളുടെ ഉപകരണത്തിലെ ട്രാഫിക്ക് നിരീക്ഷിക്കുന്ന നെറ്റ്വർക്ക് ലോഗിംഗ് അഡ്മിൻ ഓണാക്കിയിട്ടുണ്ട്.\n\nകൂടുതൽ വിവരങ്ങൾക്ക് അഡ്മിനുമായി ബന്ധപ്പെടുക."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"ഈ ആപ്പിന് അറിയിപ്പ് വിഭാഗങ്ങളില്ല"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"ഈ ആപ്പിൽ നിന്നുള്ള അറിയിപ്പുകൾ ഓഫാക്കാൻ കഴിയില്ല"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">ഈ ആപ്പിൽ നിന്ന് 1 / <xliff:g id="NUMBER_1">%d</xliff:g> അറിയിപ്പ് വിഭാഗങ്ങൾ</item> - <item quantity="one">ഈ ആപ്പിൽ നിന്ന് 1 / <xliff:g id="NUMBER_0">%d</xliff:g> അറിയിപ്പ് വിഭാഗം</item> + <item quantity="other">ഈ ആപ്പിൽ നിന്ന് 1 / <xliff:g id="NUMBER_1">%s</xliff:g> അറിയിപ്പ് വിഭാഗങ്ങൾ</item> + <item quantity="one">ഈ ആപ്പിൽ നിന്ന് 1 / <xliff:g id="NUMBER_0">%s</xliff:g> അറിയിപ്പ് വിഭാഗം</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d മിനിറ്റ്</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"ബാറ്ററി ഉപയോഗം"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"ചാർജുചെയ്യുന്ന സമയത്ത് ബാറ്ററി ലാഭിക്കൽ നടക്കില്ല"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"ബാറ്ററി ലാഭിക്കൽ"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"ചാർജുചെയ്യുന്ന സമയത്ത് ബാറ്ററി ലാഭിക്കൽ നടക്കില്ല"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"ബാറ്ററി ലാഭിക്കൽ"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"പ്രവർത്തനവും പശ്ചാത്തല ഡാറ്റയും കുറയ്ക്കുന്നു"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"ബട്ടൺ <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"ഹോം"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"ചെറുതാക്കുക"</string> <string name="pip_phone_close" msgid="8416647892889710330">"അടയ്ക്കുക"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"തള്ളിക്കളയാൻ താഴേക്ക് വലിച്ചിടുക"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"\'ചിത്രത്തിനുള്ളിൽ ചിത്രം\' മെനു"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"മെനു"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ചിത്രത്തിനുള്ളിലെ ചിത്രത്തിലാണ്"</string> <string name="pip_notification_message" msgid="5619512781514343311">"<xliff:g id="NAME">%s</xliff:g> ഈ ഫീച്ചർ ഉപയോഗിക്കുന്നതിൽ നിങ്ങൾക്ക് താൽപ്പര്യമില്ലെങ്കിൽ, ടാപ്പുചെയ്ത് ക്രമീകരണം തുറന്ന് അത് ഓഫാക്കുക."</string> <string name="pip_play" msgid="1417176722760265888">"പ്ലേ ചെയ്യുക"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"മെനു"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> ആപ്പ്"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"അലേർട്ടുകൾ"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"ബാറ്ററി"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"സ്ക്രീൻഷോട്ടുകൾ"</string> <string name="notification_channel_general" msgid="4525309436693914482">"പൊതുവായ സന്ദേശങ്ങൾ"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"സ്റ്റോറേജ്"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"ആപ്പുകൾ പശ്ചാത്തലത്തിൽ റൺ ചെയ്യുന്നു"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"ബാറ്ററി, ഡാറ്റ ഉപയോഗം എന്നിവയുടെ വിശദാംശങ്ങളറിയാൻ ടാപ്പുചെയ്യുക"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"മൊബൈൽ ഡാറ്റ ഓഫാക്കണോ?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"അനുമതി അഭ്യർത്ഥനയെ ഒരു ആപ്പ് മറയ്ക്കുന്നതിനാൽ, ക്രമീകരണത്തിന് നിങ്ങളുടെ പ്രതികരണം പരിശോധിച്ചുറപ്പിക്കാനാകില്ല."</string> </resources> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 3c88c4dcb952..8455c5adee80 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -62,8 +62,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Компьютерийн RSA түлхүүрийн хурууны хээ :\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Энэ компьютерээс орохыг байнга зөвшөөрөх"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB алдаа засалт хийх боломжгүй"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Энэ төхөөрөмжид нэвтэрсэн хэрэглэгч USB дебаг хийх онцлогийг асаах боломжгүй байна. Энэ онцлогийг ашиглахын тулд үндсэн хэрэглэгч рүү сэлгэнэ үү."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Дэлгэц дүүргэх бол өсгөнө үү"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Дэлгэц дүүргэх бол татна уу"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Дэлгэцийн агшинг хадгалж байна…"</string> @@ -455,8 +454,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Дэлгэрэнгүй үзэх"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Таны имэйл, апп, вэб хуудас зэрэг сүлжээний үйл ажиллагааг хянах боломжтой <xliff:g id="VPN_APP">%1$s</xliff:g>-д холбогдсон байна."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN тохиргоог нээх"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Итгэмжлэгдсэн мандат үнэмлэхийг нээх"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Таны админ төхөөрөмжийн ачааллыг хянадаг сүлжээний логийг асаасан байна.\n\nДэлгэрэнгүй мэдээлэл авах бол админтайгаа холбогдоно уу."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Энэ апп-д мэдэгдлийн категори алга"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Энэ аппын мэдэгдлийг унтраах боломжгүй"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">Энэ аппын <xliff:g id="NUMBER_1">%d</xliff:g> мэдэгдлийн категорийн 1</item> - <item quantity="one">Энэ аппын <xliff:g id="NUMBER_0">%d</xliff:g> мэдэгдлийн категорийн 1</item> + <item quantity="other">Энэ аппын <xliff:g id="NUMBER_1">%s</xliff:g> мэдэгдлийн категорийн 1</item> + <item quantity="one">Энэ аппын <xliff:g id="NUMBER_0">%s</xliff:g> мэдэгдлийн категорийн 1</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d минут</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Тэжээл ашиглалт"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Цэнэглэх үед тэжээл хэмнэгч ажиллахгүй"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Тэжээл хэмнэгч"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Цэнэглэх үед тэжээл хэмнэгч ажиллахгүй"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Тэжээл хэмнэгч"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Гүйцэтгэл болон дэвсгэрийн датаг багасгадаг"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g> товчлуур"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Нүүр хуудас"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Багасгах"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Хаах"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Хаахын тулд доош чирэх"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Дэлгэцэн доторх дэлгэцийн цэс"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Цэс"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> дэлгэцэн доторх дэлгэцэд байна"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Та <xliff:g id="NAME">%s</xliff:g>-д энэ онцлогийг ашиглуулахыг хүсэхгүй байвал тохиргоог нээгээд, үүнийг унтраана уу."</string> <string name="pip_play" msgid="1417176722760265888">"Тоглуулах"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Цэс"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> апп"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Сануулга"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Батерей"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Дэлгэцийн зураг дарах"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Энгийн зурвас"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Хадгалах сан"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Цаана ажиллаж буй апп"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Батерей, дата ашиглалтын талаар дэлгэрэнгүйг харахын тулд товшино уу"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Мобайл датаг унтраах уу?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Апп нь зөвшөөрлийн хүсэлтийг танихгүй байгаа тул Тохиргооноос таны хариултыг баталгаажуулах боломжгүй байна."</string> </resources> diff --git a/packages/SystemUI/res/values-mr-land/strings.xml b/packages/SystemUI/res/values-mr-land/strings.xml index fd3ba777a12d..01728d300ceb 100644 --- a/packages/SystemUI/res/values-mr-land/strings.xml +++ b/packages/SystemUI/res/values-mr-land/strings.xml @@ -19,5 +19,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="toast_rotation_locked" msgid="7609673011431556092">"स्क्रीन आता भूदृश्य अभिमुखतेत लॉक केली आहे."</string> + <string name="toast_rotation_locked" msgid="7609673011431556092">"स्क्रीन आता लॅंडस्केप ओरिएंटेशनमध्ये लॉक केली आहे."</string> </resources> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index b3a9152bf8f6..89749af39acc 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -45,27 +45,26 @@ <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"सेटिंग्ज"</string> <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"वाय-फाय"</string> <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"स्वयं-फिरणारी स्क्रीन"</string> - <string name="status_bar_settings_mute_label" msgid="554682549917429396">"नि:शब्द करा"</string> + <string name="status_bar_settings_mute_label" msgid="554682549917429396">"म्युट करा"</string> <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"स्वयं"</string> <string name="status_bar_settings_notifications" msgid="397146176280905137">"सूचना"</string> - <string name="bluetooth_tethered" msgid="7094101612161133267">"ब्लूटुथ टिथर केले"</string> + <string name="bluetooth_tethered" msgid="7094101612161133267">"ब्लूटूथ टेदर केले"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"इनपुट पद्धती सेट करा"</string> <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"वास्तविक कीबोर्ड"</string> <string name="usb_device_permission_prompt" msgid="834698001271562057">"USB डिव्हाइसवर प्रवेश करण्यासाठी <xliff:g id="APPLICATION">%1$s</xliff:g> अॅप ला अनुमती द्यायची?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"अॅप <xliff:g id="APPLICATION">%1$s</xliff:g> ला USB उपसाधनात प्रवेश करण्याची अनुमती द्यायची?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"हे USB डीव्हाइस कनेक्ट केलेले असते तेव्हा <xliff:g id="ACTIVITY">%1$s</xliff:g> उघडायचे?"</string> <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"हे USB उपसाधन कनेक्ट केलेले असते तेव्हा <xliff:g id="ACTIVITY">%1$s</xliff:g> उघडायचे?"</string> - <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"स्थापित केलेले अॅप्स या USB उपसाधनासह कार्य करत नाहीत. <xliff:g id="URL">%1$s</xliff:g> येथे या उपसाधनाविषयी अधिक जाणून घ्या"</string> + <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"इंस्टॉल केलेले अॅप्स या USB उपसाधनासह कार्य करत नाहीत. <xliff:g id="URL">%1$s</xliff:g> येथे या उपसाधनाविषयी अधिक जाणून घ्या"</string> <string name="title_usb_accessory" msgid="4966265263465181372">"USB उपसाधन"</string> <string name="label_view" msgid="6304565553218192990">"पहा"</string> - <string name="always_use_device" msgid="1450287437017315906">"या USB डिव्हाइससाठी डीफॉल्टनुसार वापरा"</string> - <string name="always_use_accessory" msgid="1210954576979621596">"या USB उपसाधनासाठी डीफॉल्टनुसार वापरा"</string> + <string name="always_use_device" msgid="1450287437017315906">"या USB डीव्हाइससाठी डीफॉल्टनुसार वापरा"</string> + <string name="always_use_accessory" msgid="1210954576979621596">"या USB अॅक्सेसरीसाठी डीफॉल्टनुसार वापरा"</string> <string name="usb_debugging_title" msgid="4513918393387141949">"USB डीबग करण्यास अनुमती द्यायची?"</string> <string name="usb_debugging_message" msgid="2220143855912376496">"संगणकाची RSA की फिंगरप्रिंट ही आहे:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"या संगणकावरून नेहमी अनुमती द्या"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB डीबग करण्यास अनुमती नाही"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"सध्या या डीव्हाइसमध्ये साइन इन केलेला वापरकर्ता USB डीबग करणे चालू करू शकत नाही. हे वैशिष्ट्य वापरण्यासाठी, प्राथमिक वापरकर्त्यावर स्विच करा."</string> <string name="compat_mode_on" msgid="6623839244840638213">"स्क्रीन भरण्यासाठी झूम करा"</string> <string name="compat_mode_off" msgid="4434467572461327898">"स्क्रीन भरण्यासाठी ताणा"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"स्क्रीनशॉट जतन करत आहे…"</string> @@ -80,9 +79,9 @@ <string name="usb_preference_title" msgid="6551050377388882787">"USB फाईल स्थानांतरण पर्याय"</string> <string name="use_mtp_button_title" msgid="4333504413563023626">"मीडिया प्लेअर म्हणून माउंट करा (MTP)"</string> <string name="use_ptp_button_title" msgid="7517127540301625751">"कॅमेरा म्हणून माउंट करा (PTP)"</string> - <string name="installer_cd_button_title" msgid="2312667578562201583">"Mac साठी Android फाईल स्थानांतर अॅप स्थापित करा"</string> - <string name="accessibility_back" msgid="567011538994429120">"परत"</string> - <string name="accessibility_home" msgid="8217216074895377641">"होम स्क्रीन"</string> + <string name="installer_cd_button_title" msgid="2312667578562201583">"Mac साठी Android फाईल स्थानांतर अॅप इंस्टॉल करा"</string> + <string name="accessibility_back" msgid="567011538994429120">"मागे"</string> + <string name="accessibility_home" msgid="8217216074895377641">"होम"</string> <string name="accessibility_menu" msgid="316839303324695949">"मेनू"</string> <string name="accessibility_accessibility_button" msgid="7601252764577607915">"प्रवेशयोग्यता"</string> <string name="accessibility_recent" msgid="5208608566793607626">"अवलोकन"</string> @@ -101,8 +100,8 @@ <string name="cancel" msgid="6442560571259935130">"रद्द करा"</string> <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"सुसंगतता झूम बटण."</string> <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"लहानपासून मोठ्या स्क्रीनवर झूम करा."</string> - <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ब्लूटुथ कनेक्ट केले."</string> - <string name="accessibility_bluetooth_disconnected" msgid="7416648669976870175">"ब्लूटुथ डिस्कनेक्ट केले."</string> + <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ब्लूटूथ कनेक्ट केले."</string> + <string name="accessibility_bluetooth_disconnected" msgid="7416648669976870175">"ब्लूटूथ डिस्कनेक्ट केले."</string> <string name="accessibility_no_battery" msgid="358343022352820946">"बॅटरी नाही."</string> <string name="accessibility_battery_one_bar" msgid="7774887721891057523">"बॅटरी एक बार."</string> <string name="accessibility_battery_two_bars" msgid="8500650438735009973">"बॅटरी दोन बार."</string> @@ -156,7 +155,7 @@ <string name="accessibility_cell_data" msgid="5326139158682385073">"मोबाइल डेटा"</string> <string name="accessibility_cell_data_on" msgid="5927098403452994422">"मोबाइल डेटा चालू आहे"</string> <string name="accessibility_cell_data_off" msgid="443267573897409704">"मोबाइल डेटा बंद आहे"</string> - <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ब्लूटुथ टिथरिंग."</string> + <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ब्लूटूथ टेदरिंग."</string> <string name="accessibility_airplane_mode" msgid="834748999790763092">"विमान मोड."</string> <string name="accessibility_vpn_on" msgid="5993385083262856059">"VPN चालू."</string> <string name="accessibility_no_sims" msgid="3957997018324995781">"सिम कार्ड नाही."</string> @@ -178,8 +177,8 @@ <string name="accessibility_work_mode" msgid="2478631941714607225">"कार्य मोड"</string> <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> डिसमिस करा."</string> <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> डिसमिस केला."</string> - <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"अलीकडील सर्व अनुप्रयोग डिसमिस झाले."</string> - <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> अनुप्रयोग माहिती उघडा."</string> + <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"अलीकडील सर्व अॅप्लिकेशन डिसमिस झाले."</string> + <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> अॅप्लिकेशन माहिती उघडा."</string> <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> प्रारंभ करीत आहे."</string> <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string> <string name="accessibility_notification_dismissed" msgid="854211387186306927">"सूचना डिसमिस केल्या."</string> @@ -206,13 +205,13 @@ <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"व्यत्यय आणू नका बंद."</string> <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"व्यत्यय आणू नका बंद करा"</string> <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"व्यत्यय आणू नका चालू करा"</string> - <string name="accessibility_quick_settings_bluetooth" msgid="6341675755803320038">"ब्लूटुथ."</string> - <string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"ब्लूटुथ बंद."</string> - <string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"ब्लूटुथ चालू."</string> - <string name="accessibility_quick_settings_bluetooth_connecting" msgid="6953242966685343855">"ब्लूटुथ कनेक्ट करत आहे."</string> - <string name="accessibility_quick_settings_bluetooth_connected" msgid="4306637793614573659">"ब्लूटुथ कनेक्ट केले."</string> - <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="2730003763480934529">"ब्लूटुथ बंद केले."</string> - <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="8722351798763206577">"ब्लूटुथ चालू केले."</string> + <string name="accessibility_quick_settings_bluetooth" msgid="6341675755803320038">"ब्लूटूथ."</string> + <string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"ब्लूटूथ बंद."</string> + <string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"ब्लूटूथ चालू."</string> + <string name="accessibility_quick_settings_bluetooth_connecting" msgid="6953242966685343855">"ब्लूटूथ कनेक्ट करत आहे."</string> + <string name="accessibility_quick_settings_bluetooth_connected" msgid="4306637793614573659">"ब्लूटूथ कनेक्ट केले."</string> + <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="2730003763480934529">"ब्लूटूथ बंद केले."</string> + <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="8722351798763206577">"ब्लूटूथ चालू केले."</string> <string name="accessibility_quick_settings_location_off" msgid="5119080556976115520">"स्थान अहवाल बंद."</string> <string name="accessibility_quick_settings_location_on" msgid="5809937096590102036">"स्थान अहवाल चालू."</string> <string name="accessibility_quick_settings_location_changed_off" msgid="8526845571503387376">"स्थान अहवाल बंद केला."</string> @@ -237,7 +236,7 @@ <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"कार्य मोड चालू केला."</string> <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"डेटा सर्व्हर बंद केला."</string> <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"डेटा सर्व्हर चालू केला."</string> - <string name="accessibility_brightness" msgid="8003681285547803095">"प्रदर्शन चमक"</string> + <string name="accessibility_brightness" msgid="8003681285547803095">"डिस्प्ले चमक"</string> <string name="accessibility_ambient_display_charging" msgid="9084521679384069087">"चार्ज होत आहे"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G डेटास विराम दिला आहे"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G डेटास विराम दिला आहे"</string> @@ -259,10 +258,10 @@ <string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"सूचना सेटिंग्ज"</string> <string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> सेटिंग्ज"</string> <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"स्क्रीन स्वयंचलितपणे फिरेल."</string> - <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"भूदृश्य अभिमुखतेमध्ये स्क्रीन लॉक केली आहे."</string> + <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"लॅंडस्केप ओरिएंटेशनमध्ये स्क्रीन लॉक केली आहे."</string> <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"पोर्ट्रेट अभिमुखतेमध्ये स्क्रीन लॉक केली आहे."</string> <string name="accessibility_rotation_lock_off_changed" msgid="8134601071026305153">"स्क्रीन आता स्वयंचलितपणे फिरेल."</string> - <string name="accessibility_rotation_lock_on_landscape_changed" msgid="3135965553707519743">"स्क्रीन आता भूदृश्य अभिमुखतेत लॉक केली आहे."</string> + <string name="accessibility_rotation_lock_on_landscape_changed" msgid="3135965553707519743">"स्क्रीन आता लॅंडस्केप ओरिएंटेशनमध्ये लॉक केली आहे."</string> <string name="accessibility_rotation_lock_on_portrait_changed" msgid="8922481981834012126">"स्क्रीन आता पोर्ट्रेट अभिमुखतेत लॉक केली आहे."</string> <string name="dessert_case" msgid="1295161776223959221">"मिष्ठान्न प्रकरण"</string> <string name="start_dreams" msgid="5640361424498338327">"स्क्रीन सेव्हर"</string> @@ -271,9 +270,9 @@ <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"केवळ प्राधान्य"</string> <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"केवळ अलार्म"</string> <string name="quick_settings_dnd_none_label" msgid="5025477807123029478">"संपूर्ण शांतता"</string> - <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ब्लूटुथ"</string> - <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ब्लूटुथ (<xliff:g id="NUMBER">%d</xliff:g> डिव्हाइसेस)"</string> - <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ब्लूटुथ बंद"</string> + <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ब्लूटूथ"</string> + <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ब्लूटूथ (<xliff:g id="NUMBER">%d</xliff:g> डीव्हाइस)"</string> + <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ब्लूटूथ बंद"</string> <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"कोणतेही जोडलेले डिव्हाइसेस उपलब्ध नाहीत"</string> <string name="quick_settings_brightness_label" msgid="6968372297018755815">"चमक"</string> <string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"स्वयं-फिरवा"</string> @@ -281,7 +280,7 @@ <string name="accessibility_quick_settings_rotation_value" msgid="8187398200140760213">"<xliff:g id="ID_1">%s</xliff:g> मोड"</string> <string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"फिरविणे लॉक केले"</string> <string name="quick_settings_rotation_locked_portrait_label" msgid="5102691921442135053">"पोर्ट्रेट"</string> - <string name="quick_settings_rotation_locked_landscape_label" msgid="8553157770061178719">"भूदृश्य"</string> + <string name="quick_settings_rotation_locked_landscape_label" msgid="8553157770061178719">"लॅंडस्केप"</string> <string name="quick_settings_ime_label" msgid="7073463064369468429">"इनपुट पद्धत"</string> <string name="quick_settings_location_label" msgid="5011327048748762257">"स्थान"</string> <string name="quick_settings_location_off_label" msgid="7464544086507331459">"स्थान बंद"</string> @@ -298,7 +297,7 @@ <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"नेटवर्क नाही"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"वाय-फाय बंद"</string> <string name="quick_settings_wifi_on_label" msgid="7607810331387031235">"वाय-फाय चालू"</string> - <string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"Wi-Fi नेटवर्क उपलब्ध नाहीत"</string> + <string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"वाय-फाय नेटवर्क उपलब्ध नाहीत"</string> <string name="quick_settings_cast_title" msgid="7709016546426454729">"कास्ट करा"</string> <string name="quick_settings_casting" msgid="6601710681033353316">"कास्ट करत आहे"</string> <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"निनावी डीव्हाइस"</string> @@ -331,7 +330,7 @@ <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC सक्षम केले आहे"</string> <string name="recents_empty_message" msgid="808480104164008572">"अलीकडील कोणतेही आयटम नाहीत"</string> <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"आपण सर्वकाही साफ केले"</string> - <string name="recents_app_info_button_label" msgid="2890317189376000030">"अनुप्रयोग माहिती"</string> + <string name="recents_app_info_button_label" msgid="2890317189376000030">"अॅप्लिकेशन माहिती"</string> <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"स्क्रीन पिन करणे"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"शोधा"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> प्रारंभ करणे शक्य झाले नाही."</string> @@ -392,7 +391,7 @@ <string name="guest_exit_guest_dialog_remove" msgid="7402231963862520531">"काढा"</string> <string name="guest_wipe_session_title" msgid="6419439912885956132">"अतिथी, आपले पुन्हा स्वागत आहे!"</string> <string name="guest_wipe_session_message" msgid="8476238178270112811">"आपण आपले सत्र सुरु ठेवू इच्छिता?"</string> - <string name="guest_wipe_session_wipe" msgid="5065558566939858884">"येथून प्रारंभ करा"</string> + <string name="guest_wipe_session_wipe" msgid="5065558566939858884">"येथून सुरू करा"</string> <string name="guest_wipe_session_dontwipe" msgid="1401113462524894716">"होय, सुरु ठेवा"</string> <string name="guest_notification_title" msgid="1585278533840603063">"अतिथी वापरकर्ता"</string> <string name="guest_notification_text" msgid="335747957734796689">"अॅप्स आणि डेटा हटविण्यासाठी, अतिथी वापरकर्ता काढा"</string> @@ -401,7 +400,7 @@ <string name="user_logout_notification_text" msgid="3350262809611876284">"वर्तमान वापरकर्ता लॉगआउट करा"</string> <string name="user_logout_notification_action" msgid="1195428991423425062">"वापरकर्त्यास लॉगआउट करा"</string> <string name="user_add_user_title" msgid="4553596395824132638">"नवीन वापरकर्ता जोडायचा?"</string> - <string name="user_add_user_message_short" msgid="2161624834066214559">"आपण एक नवीन वापरकर्ता जोडता तेव्हा, त्या व्यक्तीने त्यांचे स्थान सेट करणे आवश्यक असते.\n\nकोणताही वापरकर्ता इतर सर्व वापरकर्त्यांसाठी अॅप्स अद्यतनित करू शकतो."</string> + <string name="user_add_user_message_short" msgid="2161624834066214559">"आपण एक नवीन वापरकर्ता जोडता तेव्हा, त्या व्यक्तीने त्यांचे स्थान सेट करणे आवश्यक असते.\n\nकोणताही वापरकर्ता इतर सर्व वापरकर्त्यांसाठी अॅप्स अपडेट करू शकतो."</string> <string name="user_remove_user_title" msgid="4681256956076895559">"वापरकर्त्यास काढायचे?"</string> <string name="user_remove_user_message" msgid="1453218013959498039">"या वापरकर्त्याचे सर्व अॅप्स आणि डेटा काढून टाकला जाईल."</string> <string name="user_remove_user_remove" msgid="7479275741742178297">"काढा"</string> @@ -411,7 +410,7 @@ <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> आपल्या स्क्रीनवर प्रदर्शित होणारी प्रत्येक गोष्ट कॅप्चर करणे प्रारंभ करेल."</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"पुन्हा दर्शवू नका"</string> <string name="clear_all_notifications_text" msgid="814192889771462828">"सर्व साफ करा"</string> - <string name="media_projection_action_text" msgid="8470872969457985954">"आता प्रारंभ करा"</string> + <string name="media_projection_action_text" msgid="8470872969457985954">"आता सुरू करा"</string> <string name="empty_shade_text" msgid="708135716272867002">"सूचना नाहीत"</string> <string name="profile_owned_footer" msgid="8021888108553696069">"प्रोफाईलचे परीक्षण केले जाऊ शकते"</string> <string name="vpn_footer" msgid="2388611096129106812">"नेटवर्कचे परीक्षण केले जाऊ शकते"</string> @@ -440,11 +439,11 @@ <string name="disable_vpn" msgid="4435534311510272506">"VPN अक्षम करा"</string> <string name="disconnect_vpn" msgid="1324915059568548655">"VPN डिस्कनेक्ट करा"</string> <string name="monitoring_button_view_policies" msgid="100913612638514424">"धोरणे पहा"</string> - <string name="monitoring_description_named_management" msgid="5281789135578986303">"तुमचे डीव्हाइस <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> व्यवस्थापित करते.\n\nतुमचा प्रशासक सेटिंग्ज, कॉर्पोरेट अॅक्सेस, अॅप्स, तुमच्या डीव्हाइस शी संबंधित डेटा आणि तुमच्या डीव्हाइस च्या ठिकाणाची माहिती मॉनिटर करू शकते आणि ती व्यवस्थापित करू शकतो.\n\n3आणखी माहितीसाठी, तुमच्या प्रशासकाशी संपर्क साधा."</string> - <string name="monitoring_description_management" msgid="4573721970278370790">"तुमचे डीव्हाइस तुमची संस्था व्यवस्थापित करते.\n\nतुमचा प्रशासक सेटिंग्ज, कॉर्पोरेट अॅक्सेस, अॅप्स, तुमच्या डीव्हाइस शी संबंधित डेटा आणि तुमच्या डीव्हाइस च्या ठिकाणाची माहिती मॉनिटर करू शकतो आणि ती व्यवस्थापित करू शकतो.\n\nआणखी माहितीसाठी, तुमच्या प्रशासकाशी संपर्क साधा."</string> - <string name="monitoring_description_management_ca_certificate" msgid="5202023784131001751">"आपल्या संस्थेने या डिव्हाइसवर प्रमाणपत्र अधिकार स्थापित केला आहे. आपल्या सुरक्षित नेटवर्क रहदारीचे परीक्षण केले जाऊ शकते किंवा ती सुधारली जाऊ शकते."</string> - <string name="monitoring_description_managed_profile_ca_certificate" msgid="4683248196789897964">"आपल्या संस्थेने आपल्या कार्य प्रोफाइलवर प्रमाणपत्र अधिकार स्थापित केला आहे. आपल्या सुरक्षित नेटवर्क रहदारीचे परीक्षण केले जाऊ शकते किंवा ती सुधारली जाऊ शकते."</string> - <string name="monitoring_description_ca_certificate" msgid="7886985418413598352">"या डिव्हाइसवर प्रमाणपत्र अधिकार स्थापित केला आहे. आपल्या सुरक्षित नेटवर्क रहदारीचे परीक्षण केले जाऊ शकते किंवा ती सुधारली जाऊ शकते."</string> + <string name="monitoring_description_named_management" msgid="5281789135578986303">"तुमचे डीव्हाइस <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> व्यवस्थापित करते.\n\nतुमचा प्रशासक सेटिंग्ज, कॉर्पोरेट अॅक्सेस, अॅप्स, तुमच्या डीव्हाइस शी संबंधित डेटा आणि तुमच्या डीव्हाइस च्या ठिकाणाची माहिती मॉनिटर करू शकते आणि ती व्यवस्थापित करू शकतो.\n\nआणखी माहितीसाठी, तुमच्या प्रशासकाशी संपर्क साधा."</string> + <string name="monitoring_description_management" msgid="4573721970278370790">"तुमचे डीव्हाइस तुमची संस्था व्यवस्थापित करते.\n\nतुमचा प्रशासक सेटिंग्ज, कॉर्पोरेट अॅक्सेस, अॅप्स, तुमच्या डीव्हाइस शी संबंधित डेटा आणि तुमच्या डीव्हाइस च्या ठिकाणाची माहिती मॉनिटर करू शकतो आणि ती व्यवस्थापित करू शकतो.\n\nआणखी माहितीसाठी, तुमच्या प्रशासकाशी संपर्क साधा."</string> + <string name="monitoring_description_management_ca_certificate" msgid="5202023784131001751">"आपल्या संस्थेने या डिव्हाइसवर प्रमाणपत्र अधिकार इंस्टॉल केला आहे. आपल्या सुरक्षित नेटवर्क रहदारीचे परीक्षण केले जाऊ शकते किंवा ती सुधारली जाऊ शकते."</string> + <string name="monitoring_description_managed_profile_ca_certificate" msgid="4683248196789897964">"आपल्या संस्थेने आपल्या कार्य प्रोफाइलवर प्रमाणपत्र अधिकार इंस्टॉल केला आहे. आपल्या सुरक्षित नेटवर्क रहदारीचे परीक्षण केले जाऊ शकते किंवा ती सुधारली जाऊ शकते."</string> + <string name="monitoring_description_ca_certificate" msgid="7886985418413598352">"या डिव्हाइसवर प्रमाणपत्र अधिकार इंस्टॉल केला आहे. आपल्या सुरक्षित नेटवर्क रहदारीचे परीक्षण केले जाऊ शकते किंवा ती सुधारली जाऊ शकते."</string> <string name="monitoring_description_management_network_logging" msgid="7184005419733060736">"आपल्या प्रशासकाने नेटवर्क लॉगिंग चालू केले आहे, जे आपल्या डिव्हाइसवरील रहदारीचे परीक्षण करते."</string> <string name="monitoring_description_named_vpn" msgid="7403457334088909254">"तुम्ही <xliff:g id="VPN_APP">%1$s</xliff:g> शी कनेक्ट केले आहे, जे ईमेल, अॅप्स आणि वेबसाइटसहित आपल्या नेटवर्क क्रिया मॉनिटर करू शकते."</string> <string name="monitoring_description_two_named_vpns" msgid="4198511413729213802">"तुम्ही <xliff:g id="VPN_APP_0">%1$s</xliff:g> आणि <xliff:g id="VPN_APP_1">%2$s</xliff:g> शी कनेक्ट केले आहे, जे ईमेल, अॅप्स आणि वेबसाइटसहित आपल्या नेटवर्क क्रिया मॉनिटर करू शकते."</string> @@ -457,13 +456,12 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"अधिक जाणून घ्या"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"आपण <xliff:g id="VPN_APP">%1$s</xliff:g> शी कनेक्ट केले आहे, जो ईमेल, अॅप्स आणि वेबसाइटसह आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करू शकतो."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN सेटिंग्ज उघडा"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> - <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"विश्वासू क्रेडेन्शियल उघडा"</string> + <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"विश्वासू क्रेडेंशियल उघडा"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"आपल्या प्रशासकाने नेटवर्क लॉगिंग चालू केले आहे, जे आपल्या डिव्हाइसवरील रहदारीचे निरीक्षण करते.\n\nअधिक माहितीसाठी आपल्या प्रशासकाशी संपर्क साधा."</string> <string name="monitoring_description_vpn" msgid="4445150119515393526">"तुम्ही VPN कनेक्शन सेट करण्यासाठी अॅपला परवानगी दिली.\n\nहा अॅप ईमेल, अॅप्स आणि वेबसाइटसह, तुमच्या डीव्हाइस आणि नेटवर्क अॅक्टिव्हिटीचे परीक्षण करू शकतो."</string> - <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"आपले कार्य प्रोफाइल <xliff:g id="ORGANIZATION">%1$s</xliff:g> द्वारे व्यवस्थापित केले जाते.\n\nआपला प्रशासक ईमेल, अॅप्स आणि वेबसाइटसह आपल्या नेटवर्क क्रियाकलापाचे निरीक्षण करण्यास सक्षम आहे.\n\nअधिक माहितीसाठी आपल्या प्रशासकाशी संपर्क साधा.\n\nआपण VPN शी देखील कनेक्ट आहात, जे आपल्या नेटवर्क क्रियाकलापाचे निरीक्षण करू शकते."</string> + <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"आपले कार्य प्रोफाइल <xliff:g id="ORGANIZATION">%1$s</xliff:g> द्वारे व्यवस्थापित केले जाते.\n\nआपला प्रशासक ईमेल, अॅप्स आणि वेबसाइटसह आपल्या नेटवर्क अॅक्टिव्हिटीचे निरीक्षण करण्यास सक्षम आहे.\n\nअधिक माहितीसाठी आपल्या प्रशासकाशी संपर्क साधा.\n\nआपण VPN शी देखील कनेक्ट आहात, जे आपल्या नेटवर्क अॅक्टिव्हिटीचे निरीक्षण करू शकते."</string> <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string> <string name="monitoring_description_app" msgid="1828472472674709532">"आपण <xliff:g id="APPLICATION">%1$s</xliff:g> शी कनेक्ट केले आहे, जे ईमेल, अॅप्स आणि वेबसाइटसह आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करू शकते."</string> <string name="monitoring_description_app_personal" msgid="484599052118316268">"आपण <xliff:g id="APPLICATION">%1$s</xliff:g> शी कनेक्ट केले आहे, जो ईमेल, अॅप्स आणि वेबसाइटसह आपल्या वैयक्तिक नेटवर्क क्रियाकलापाचे परीक्षण करू शकतो."</string> @@ -496,7 +494,7 @@ <string name="stream_music" msgid="9086982948697544342">"मीडिया"</string> <string name="stream_alarm" msgid="5209444229227197703">"अलार्म"</string> <string name="stream_notification" msgid="2563720670905665031">"सूचना"</string> - <string name="stream_bluetooth_sco" msgid="2055645746402746292">"ब्लूटुथ"</string> + <string name="stream_bluetooth_sco" msgid="2055645746402746292">"ब्लूटूथ"</string> <string name="stream_dtmf" msgid="2447177903892477915">"दुहेरी एकाधिक टोन वारंंवारता"</string> <string name="stream_accessibility" msgid="301136219144385106">"प्रवेशयोग्यता"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. सशब्द करण्यासाठी टॅप करा."</string> @@ -513,7 +511,7 @@ <string name="status_bar" msgid="4877645476959324760">"स्टेटस बार"</string> <string name="overview" msgid="4018602013895926956">"अवलोकन"</string> <string name="demo_mode" msgid="2532177350215638026">"सिस्टीम UI डेमो मोड"</string> - <string name="enable_demo_mode" msgid="4844205668718636518">"डेमो मोड सक्षम करा"</string> + <string name="enable_demo_mode" msgid="4844205668718636518">"डेमो मोड सुरू करा"</string> <string name="show_demo_mode" msgid="2018336697782464029">"डेमो मोड दर्शवा"</string> <string name="status_bar_ethernet" msgid="5044290963549500128">"इथरनेट"</string> <string name="status_bar_alarm" msgid="8536256753575881818">"अलार्म"</string> @@ -535,14 +533,14 @@ <string name="tuner_toast" msgid="603429811084428439">"अभिनंदन! सिस्टम UI ट्युनर सेटिंग्जमध्ये जोडले गेले आहे"</string> <string name="remove_from_settings" msgid="8389591916603406378">"सेटिंग्ज मधून काढा"</string> <string name="remove_from_settings_prompt" msgid="6069085993355887748">"सेटिंग्ज मधून सिस्टम UI ट्युनर काढून त्याची सर्व वैशिष्ट्ये वापरणे थांबवायचे?"</string> - <string name="activity_not_found" msgid="348423244327799974">"अनुप्रयोग आपल्या डिव्हाइसवर स्थापित केलेला नाही"</string> + <string name="activity_not_found" msgid="348423244327799974">"अॅप्लिकेशन आपल्या डिव्हाइसवर इंस्टॉल केलेला नाही"</string> <string name="clock_seconds" msgid="7689554147579179507">"घड्याळाचे सेकंद दर्शवा"</string> <string name="clock_seconds_desc" msgid="6282693067130470675">"स्टेटस बारमध्ये घड्याळाचे सेकंद दर्शवा. कदाचित बॅटरी आयुष्य प्रभावित होऊ शकते."</string> <string name="qs_rearrange" msgid="8060918697551068765">"द्रुत सेटिंग्जची पुनर्रचना करा"</string> <string name="show_brightness" msgid="6613930842805942519">"द्रुत सेटिंग्जमध्ये चमक दर्शवा"</string> <string name="experimental" msgid="6198182315536726162">"प्रायोगिक"</string> - <string name="enable_bluetooth_title" msgid="5027037706500635269">"ब्लूटुथ सुरू करायचे?"</string> - <string name="enable_bluetooth_message" msgid="9106595990708985385">"आपला कीबोर्ड आपल्या टॅब्लेटसह कनेक्ट करण्यासाठी, आपल्याला प्रथम ब्लूटुथ चालू करणे आवश्यक आहे."</string> + <string name="enable_bluetooth_title" msgid="5027037706500635269">"ब्लूटूथ सुरू करायचे?"</string> + <string name="enable_bluetooth_message" msgid="9106595990708985385">"आपला कीबोर्ड तुमच्या टॅबलेटसह कनेक्ट करण्यासाठी, तुम्ही प्रथम ब्लूटूथ चालू करणे आवश्यक आहे."</string> <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"चालू करा"</string> <string name="show_silently" msgid="6841966539811264192">"सूचना शांतपणे दर्शवा"</string> <string name="block" msgid="2734508760962682611">"सर्व सूचना ब्लॉक करा"</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"या अॅपला सूचना श्रेण्या नाहीत"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"या अॅपकडून येणार्या सूचना बंद ठेवता येणार नाहीत"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">या अॅपकडील <xliff:g id="NUMBER_1">%d</xliff:g> पैकी 1 सूचना श्रेणी</item> - <item quantity="other">या अॅपकडील <xliff:g id="NUMBER_1">%d</xliff:g> पैकी 1 सूचना श्रेणी</item> + <item quantity="one">या अॅपकडील <xliff:g id="NUMBER_1">%s</xliff:g> पैकी 1 सूचना श्रेणी</item> + <item quantity="other">या अॅपकडील <xliff:g id="NUMBER_1">%s</xliff:g> पैकी 1 सूचना श्रेणी</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="other"> %d मिनिटे</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"बॅटरी वापर"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"चार्ज करताना बॅटरी बचतकर्ता उपलब्ध नाही"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"बॅटरी बचतकर्ता"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"चार्ज करताना बॅटरी सेव्हर उपलब्ध नाही"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"बॅटरी सेव्हर"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"कामगिरी आणि पार्श्वभूमीवरील डेटा कमी करते"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"बटण <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -617,13 +615,13 @@ <string name="keyboard_key_num_lock" msgid="5052537581246772117">"Num Lock"</string> <string name="keyboard_key_numpad_template" msgid="8729216555174634026">"Numpad <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_shortcut_group_system" msgid="6472647649616541064">"सिस्टीम"</string> - <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"होम स्क्रीन"</string> + <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"होम"</string> <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"अलीकडील"</string> <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"परत"</string> <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"सूचना"</string> <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"कीबोर्ड शॉर्टकट"</string> <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"इनपुट पद्धत स्विच करा"</string> - <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"अनुप्रयोग"</string> + <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"अॅप्लिकेशन"</string> <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"सहाय्य"</string> <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"ब्राउझर"</string> <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"संपर्क"</string> @@ -664,15 +662,15 @@ <item msgid="586019486955594690">"उजवीकडे कललेले"</item> </string-array> <string name="menu_ime" msgid="4998010205321292416">"कीबोर्ड स्विचर"</string> - <string name="save" msgid="2311877285724540644">"जतन करा"</string> + <string name="save" msgid="2311877285724540644">"सेव्ह करा"</string> <string name="reset" msgid="2448168080964209908">"रीसेट करा"</string> <string name="adjust_button_width" msgid="6138616087197632947">"बटण रूंदी समायोजित करा"</string> <string name="clipboard" msgid="1313879395099896312">"क्लिपबोर्ड"</string> <string name="accessibility_key" msgid="5701989859305675896">"सानुकूल नेव्हिगेशन बटण"</string> <string name="left_keycode" msgid="2010948862498918135">"डावा कीकोड"</string> <string name="right_keycode" msgid="708447961000848163">"उजवा कीकोड"</string> - <string name="left_icon" msgid="3096287125959387541">"डावे चिन्ह"</string> - <string name="right_icon" msgid="3952104823293824311">"उजवे चिन्ह"</string> + <string name="left_icon" msgid="3096287125959387541">"डावे आयकन"</string> + <string name="right_icon" msgid="3952104823293824311">"उजवे आयकन"</string> <string name="drag_to_add_tiles" msgid="7058945779098711293">"टाइल जोडण्यासाठी ड्रॅग करा"</string> <string name="drag_to_remove_tiles" msgid="3361212377437088062">"काढण्यासाठी येथे ड्रॅग करा"</string> <string name="qs_edit" msgid="2232596095725105230">"संपादित करा"</string> @@ -680,12 +678,12 @@ <string-array name="clock_options"> <item msgid="5965318737560463480">"तास, मिनिटे आणि सेकंद दर्शवा"</item> <item msgid="1427801730816895300">"तास आणि मिनिटे दर्शवा (डीफॉल्ट)"</item> - <item msgid="3830170141562534721">"हे चिन्ह दर्शवू नका"</item> + <item msgid="3830170141562534721">"हे आयकन दाखवू नका"</item> </string-array> <string-array name="battery_options"> <item msgid="3160236755818672034">"नेहमी टक्केवारी दर्शवा"</item> <item msgid="2139628951880142927">"चार्ज करताना टक्केवारी दर्शवा (डीफॉल्ट)"</item> - <item msgid="3327323682209964956">"हे चिन्ह दर्शवू नका"</item> + <item msgid="3327323682209964956">"हे आयकन दाखवू नका"</item> </string-array> <string name="other" msgid="4060683095962566764">"अन्य"</string> <string name="accessibility_divider" msgid="5903423481953635044">"विभाजित-स्क्रीन विभाजक"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"लहान करा"</string> <string name="pip_phone_close" msgid="8416647892889710330">"बंद करा"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"डिसमिस करण्यासाठी खाली ड्रॅग करा"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"चित्र मेनूमधील चित्र"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"मेनू"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> चित्रामध्ये चित्र मध्ये आहे"</string> <string name="pip_notification_message" msgid="5619512781514343311">"<xliff:g id="NAME">%s</xliff:g>ने हे वैशिष्ट्य वापरू नये असे तुम्हाला वाटत असल्यास, सेटिंग्ज उघडण्यासाठी टॅप करा आणि ते बंद करा."</string> <string name="pip_play" msgid="1417176722760265888">"प्ले करा"</string> @@ -749,15 +747,14 @@ <string name="tuner_launch_app" msgid="1527264114781925348">"<xliff:g id="APP">%1$s</xliff:g> लाँच करा"</string> <string name="tuner_other_apps" msgid="4726596850501162493">"इतर अॅप्स"</string> <string name="tuner_circle" msgid="2340998864056901350">"मंडळ"</string> - <string name="tuner_plus" msgid="6792960658533229675">"अधिक चिन्ह"</string> - <string name="tuner_minus" msgid="4806116839519226809">"उणे चिन्ह"</string> + <string name="tuner_plus" msgid="6792960658533229675">"अधिक आयकन"</string> + <string name="tuner_minus" msgid="4806116839519226809">"उणे आयकन"</string> <string name="tuner_left" msgid="8404287986475034806">"डावा"</string> <string name="tuner_right" msgid="6222734772467850156">"उजवा"</string> <string name="tuner_menu" msgid="191640047241552081">"मेनू"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> अॅप"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"सूचना"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"बॅटरी"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"स्क्रीनशॉट"</string> <string name="notification_channel_general" msgid="4525309436693914482">"सर्वसाधारण संदेश"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"संचय"</string> @@ -767,7 +764,7 @@ <string name="go_to_web" msgid="1106022723459948514">"वेबवर जा"</string> <string name="mobile_data" msgid="7094582042819250762">"मोबाइल डेटा"</string> <string name="wifi_is_off" msgid="1838559392210456893">"वाय-फाय बंद आहे"</string> - <string name="bt_is_off" msgid="2640685272289706392">"ब्लूटुथ बंद आहे"</string> + <string name="bt_is_off" msgid="2640685272289706392">"ब्लूटूथ बंद आहे"</string> <string name="dnd_is_off" msgid="6167780215212497572">"व्यत्यय आणू नका बंद आहे"</string> <string name="qs_dnd_prompt_auto_rule" msgid="862559028345233052">"व्यत्यय आणू नका एका <xliff:g id="ID_1">%s</xliff:g> स्वयंचलित नियमाने चालू केले."</string> <string name="qs_dnd_prompt_app" msgid="7978037419334156034">"व्यत्यय आणू नका (<xliff:g id="ID_1">%s</xliff:g>) अॅपने चालू केले."</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"अॅप्स बॅकग्राउंडमध्ये चालू आहेत"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"बॅटरी आणि डेटा वापराच्या तपशीलांसाठी टॅप करा"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"मोबाइल डेटा बंद करायचा?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"अॅप परवानगी विनंती अस्पष्ट करत असल्याने, सेटिंग्ज तुमचा प्रतिसाद पडताळू शकत नाहीत."</string> </resources> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 594b25d68295..1a1d337da5b5 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Cap jari kekunci RSA komputer ialah:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Sentiasa benarkan komputer ini"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Penyahpepijatan USB tidak dibenarkan"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Pengguna yang log masuk ke peranti ini pada masa ini tidak boleh menghidupkan penyahpepijatan USB. Untuk menggunakan ciri ini, tukar kepada pengguna utama."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zum untuk memenuhi skrin"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Regang utk memenuhi skrin"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Menyimpan tangkapan skrin..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Ketahui lebih lanjut"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Anda disambungkan ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang boleh memantau aktiviti rangkaian anda, termasuk e-mel, apl dan tapak web."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Buka tetapan VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Buka bukti kelayakan yang dipercayai"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Pentadbir anda telah menghidupkan pengelogan rangkaian yang memantau trafik pada peranti anda.\n\nUntuk mendapatkan maklumat lanjut, hubungi pentadbir anda."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Apl ini tiada kategori pemberitahuan"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Pemberitahuan daripada apl ini tidak boleh dimatikan"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 daripada <xliff:g id="NUMBER_1">%d</xliff:g> kategori pemberitahuan daripada apl ini</item> - <item quantity="one">1 daripada <xliff:g id="NUMBER_0">%d</xliff:g> kategori pemberitahuan daripada apl ini</item> + <item quantity="other">1 daripada <xliff:g id="NUMBER_1">%s</xliff:g> kategori pemberitahuan daripada apl ini</item> + <item quantity="one">1 daripada <xliff:g id="NUMBER_0">%s</xliff:g> kategori pemberitahuan daripada apl ini</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d minit</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Penggunaan bateri"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Penjimat Bateri tidak tersedia semasa mengecas"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Penjimat Bateri"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Penjimat bateri tidak tersedia semasa mengecas"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Penjimat bateri"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Mengurangkan prestasi dan data latar belakang"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Butang <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Skrin Utama"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimumkan"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Tutup"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Seret ke bawah untuk mengetepikan"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Menu gambar dalam gambar"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> terdapat dalam gambar dalam gambar"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Jika anda tidak mahu <xliff:g id="NAME">%s</xliff:g> menggunakan ciri ini, ketik untuk membuka tetapan dan matikan ciri."</string> <string name="pip_play" msgid="1417176722760265888">"Main"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menu"</string> <string name="tuner_app" msgid="3507057938640108777">"Apl <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Makluman"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Bateri"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Tangkapan skrin"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Mesej Am"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Storan"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Apl yang berjalan di latar belakang"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Ketik untuk mendapatkan butiran tentang penggunaan kuasa bateri dan data"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Matikan data mudah alih?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Oleh sebab apl melindungi permintaan kebenaran, Tetapan tidak dapat mengesahkan jawapan anda."</string> </resources> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index 0897832d451d..384daa327716 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"ဒီကွန်ပျူတာရဲ့ RSA key fingerprint ကတော့:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g> ဖြစ်ပါသည်"</string> <string name="usb_debugging_always" msgid="303335496705863070">"ဒီကွန်ပျူတာမှ အမြဲခွင့်ပြုရန်"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB အမှားပြင်ဆင်ခြင်း ခွင့်မပြုပါ"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ဤစက်ပစ္စည်းသို့ လက်ရှိဝင်ရောက်ထားသည့် အသုံးပြုသူသည် USB အမှားပြင်ဆင်ခြင်းကို ဖွင့်၍မရပါ။ ဤဝန်ဆောင်မှုကို အသုံးပြုရန် အဓိကအသုံးပြုသူအဖြစ်သို့ ပြောင်းပါ။"</string> <string name="compat_mode_on" msgid="6623839244840638213">"ဇူးမ်အပြည့်ဆွဲခြင်း"</string> <string name="compat_mode_off" msgid="4434467572461327898">"ဖန်သားပြင်အပြည့်ဆန့်ခြင်း"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"ဖန်သားပြင်ဓါတ်ပုံသိမ်းစဉ်.."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"ပိုမိုလေ့လာရန်"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"အီးမေးလ်၊ အက်ပ်နှင့် ဝဘ်ဆိုက်များအပါအဝင် သင့်ကွန်ရက်လုပ်ဆောင်ချက်ကို စောင့်ကြည့်နိုင်သည့် <xliff:g id="VPN_APP">%1$s</xliff:g> သို့ သင်သည် ချိတ်ဆက်ထားပါသည်။"</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN ဆက်တင်များကို ဖွင့်ရန်"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"ယုံကြည်စိတ်ချရသော အထောက်အထားများကို ဖွင့်ရန်"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"သင့်စီမံခန့်ခွဲသူသည် စက်ပစ္စည်းပေါ်ရှိ ဒေတာအသွားအလာကို စောင့်ကြည့်နိုင်သည့် ကွန်ရက်အတွက် မှတ်တမ်းတင်ခြင်းကို ဖွင့်ထားပါသည်။\n\nနောက်ထပ် အချက်အလက်များအတွက် သင့်စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ။"</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"ဤအက်ပ်တွင် အကြောင်းကြားချက် အမျိုးအစားများ မရှိပါ"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"ဤအက်ပ်မှပို့သော အကြောင်းကြားချက်များကို ပိတ်ထား၍မရပါ"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">ဤအက်ပ်ရှိ အကြောင်းကြားချက်အမျိုးအစား <xliff:g id="NUMBER_1">%d</xliff:g> ခု အနက်မှ ၁ ခု</item> - <item quantity="one">ဤအက်ပ်ရှိ အကြောင်းကြားချက်အမျိုးအစား <xliff:g id="NUMBER_0">%d</xliff:g> ခု အနက်မှ ၁ ခု</item> + <item quantity="other">ဤအက်ပ်ရှိ အကြောင်းကြားချက်အမျိုးအစား <xliff:g id="NUMBER_1">%s</xliff:g> ခု အနက်မှ ၁ ခု</item> + <item quantity="one">ဤအက်ပ်ရှိ အကြောင်းကြားချက်အမျိုးအစား <xliff:g id="NUMBER_0">%s</xliff:g> ခု အနက်မှ ၁ ခု</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>၊ <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d မိနစ်</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"ဘက်ထရီ အသုံးပြုမှု"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"အားသွင်းနေချိန်မှာ Battery Saver ကို သုံးမရပါ"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Battery Saver"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"အားသွင်းနေစဉ် ဘက်ထရီချွေတာမှုစနစ်ကို သုံး၍ မရပါ"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"ဘက်ထရီ ချွေတာမှုစနစ်"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"လုပ်ဆောင်မှု နှင့် နောက်ခံ ဒေတာကို လျော့နည်းစေပါသည်"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"ခလုတ် <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"ပင်မ"</string> @@ -599,7 +597,7 @@ <string name="keyboard_key_dpad_right" msgid="3317323247127515341">"ညာ"</string> <string name="keyboard_key_dpad_center" msgid="2566737770049304658">"ဌာန"</string> <string name="keyboard_key_tab" msgid="3871485650463164476">"တဘ်"</string> - <string name="keyboard_key_space" msgid="2499861316311153293">"နေရာခြားပါ"</string> + <string name="keyboard_key_space" msgid="2499861316311153293">"Space"</string> <string name="keyboard_key_enter" msgid="5739632123216118137">"Enter ခလုတ်"</string> <string name="keyboard_key_backspace" msgid="1559580097512385854">"နောက်ပြန်ဖျက်ပါ"</string> <string name="keyboard_key_media_play_pause" msgid="3861975717393887428">"ဖွင့်ပါ/ခဏရပ်ပါ"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"ချုံ့ရန်"</string> <string name="pip_phone_close" msgid="8416647892889710330">"ပိတ်ရန်"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ပယ်ရန်အတွက် အောက်သို့ ပွတ်ဆွဲပါ"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"တစ်ခုပေါ်တစ်ခု ထပ်၍ ဖွင့်ခြင်းမီနူး"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"မီနူး"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> သည် တစ်ခုပေါ် တစ်ခုထပ်၍ ဖွင့်ထားသည်"</string> <string name="pip_notification_message" msgid="5619512781514343311">"<xliff:g id="NAME">%s</xliff:g> အား ဤဝန်ဆောင်မှုကို အသုံးမပြုစေလိုလျှင် ဆက်တင်ကိုဖွင့်ရန် တို့ပြီး ၎င်းဝန်ဆောင်မှုကို ပိတ်လိုက်ပါ။"</string> <string name="pip_play" msgid="1417176722760265888">"ဖွင့်ရန်"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"မီနူး"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> အက်ပ်"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"သတိပေးချက်များ"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"ဘက်ထရီ"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"မျက်နှာပြင်ဓာတ်ပုံများ"</string> <string name="notification_channel_general" msgid="4525309436693914482">"အထွေထွေ မက်ဆေ့ဂျ်များ"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"သိုလှောင်မှုများ"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"နောက်ခံတွင် ပွင့်နေသော အက်ပ်များ"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"ဘက်ထရီနှင့် ဒေတာအသုံးပြုမှု အသေးစိတ်ကို ကြည့်ရန် တို့ပါ"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"မိုဘိုင်းဒေတာကို ပိတ်လိုပါသလား။"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"အပလီကေးရှင်းတစ်ခုက ခွင့်ပြုချက်တောင်းခံမှုကို ပိတ်ထားသောကြောင့် ဆက်တင်များသည် သင်၏ လုပ်ဆောင်ကို တုံ့ပြန်နိုင်ခြင်းမရှိပါ။"</string> </resources> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index bb9b77cde2d4..3af4e027a5b2 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Datamaskinens nøkkelfingeravtrykk for RSA er:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Tillat alltid fra denne datamaskinen"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB-feilsøking er ikke tillatt"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Brukeren som for øyeblikket er logget på denne enheten, kan ikke slå på USB-feilsøking. For å bruke denne funksjonen, bytt til hovedbrukeren."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zoom for å fylle skjermen"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Strekk for å fylle skjerm"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Lagrer skjermdumpen …"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Finn ut mer"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Enheten er koblet til <xliff:g id="VPN_APP">%1$s</xliff:g>, som kan overvåke nettverksaktiviteten din, inkludert e-post, apper og nettsteder."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Åpne VPN-innstillingene"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Åpne pålitelig legitimasjon"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administratoren din har slått på loggføring av nettverk, som overvåker trafikken på enheten din.\n\nKontakt administratoren for mer informasjon."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Denne appen har ikke varselkategorier"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Varsler fra denne appen kan ikke slås av"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 av <xliff:g id="NUMBER_1">%d</xliff:g> varselkategorier fra denne appen</item> - <item quantity="one">1 av <xliff:g id="NUMBER_0">%d</xliff:g> varselkategori fra denne appen</item> + <item quantity="other">1 av <xliff:g id="NUMBER_1">%s</xliff:g> varselkategorier fra denne appen</item> + <item quantity="one">1 av <xliff:g id="NUMBER_0">%s</xliff:g> varselkategori fra denne appen</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d minutt</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Batteribruk"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Batterisparing er ikke tilgjengelig under lading"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Batterisparing"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Batterisparing er ikke tilgjengelig under lading"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Batterisparing"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduserer ytelsen og begrenser bakgrunnsdataene"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g>-knappen"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Startskjerm"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimer"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Lukk"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Dra ned for å avvise"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Bilde-i-bilde-meny"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Meny"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> er i bilde-i-bilde"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Hvis du ikke vil at <xliff:g id="NAME">%s</xliff:g> skal bruke denne funksjonen, kan du trykke for å åpne innstillingene og slå den av."</string> <string name="pip_play" msgid="1417176722760265888">"Spill av"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Meny"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g>-appen"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Varsler"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Batteri"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Skjermdumper"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Generelle meldinger"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Lagring"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Apper kjører i bakgrunnen"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Trykk for detaljer om batteri- og databruk"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Vil du slå av mobildata?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Fordi en app skjuler tillatelsesforespørselen, kan ikke Innstillinger bekrefte svaret ditt."</string> </resources> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index 9abd8569c408..63c1b79639a6 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"कम्प्युटरको RSA कुञ्जी औंलाछाप:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"यो कम्प्युटरबाट सधैँ अनुमति दिनुहोस्"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB डिबग गर्न अनुमति छैन"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"हाल यस यन्त्रमा साइन इन हुनुभएको प्रयोगकर्ताले USB डिबग सक्रिय गर्न सक्नुहुन्न। यो सुविधाको प्रयोग गर्न प्राथमिक प्रयोगकर्तामा बदल्नुहोस्।"</string> <string name="compat_mode_on" msgid="6623839244840638213">"स्क्रिन भर्न जुम गर्नुहोस्"</string> <string name="compat_mode_off" msgid="4434467572461327898">"स्क्रिन भर्न तन्काउनुहोस्"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"स्क्रिनसट बचत गर्दै…"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"थप जान्नुहोस्"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"तपाईं <xliff:g id="VPN_APP">%1$s</xliff:g> मा जोडिनुभएको छ जसले इमेल, अनुप्रयोग र वेबसाइटहरू लगायत तपाईंको नेटवर्क सम्बन्धी गतिविधिको अनुगमन गर्न सक्छ।"</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN सम्बन्धी सेटिङहरू खोल्नुहोस्"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"खुला विश्वसनीय प्रमाणहरू"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"तपाईँको प्रशासकले तपाईँको यन्त्रमा ट्राफिकको अनुगमन गर्ने नेटवर्कको लगिङलाई सक्रिय पार्नुभएको छ।\n\nथप जानकारीका लागि आफ्नो प्रशासकलाई सम्पर्क गर्नुहोस्।"</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"यस अनुप्रयोगमा सूचना सम्बन्धी कोटीहरू छैनन्"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"यस अनुप्रयोगका सूचनाहरूलाई निष्क्रिय पार्न सकिँदैन"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">यस अनुप्रयोगका <xliff:g id="NUMBER_1">%d</xliff:g> सूचना कोटिहरू मध्ये १</item> - <item quantity="one"> यस अनुप्रयोगको <xliff:g id="NUMBER_0">%d</xliff:g> सूचना कोटी मध्ये १</item> + <item quantity="other">यस अनुप्रयोगका <xliff:g id="NUMBER_1">%s</xliff:g> सूचना कोटिहरू मध्ये १</item> + <item quantity="one"> यस अनुप्रयोगको <xliff:g id="NUMBER_0">%s</xliff:g> सूचना कोटी मध्ये १</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d मिनेट</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"ब्याट्री उपयोग"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"चार्ज गर्ने समयमा ब्याट्री सेभर उपलब्ध छैन"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"ब्याट्री सेभर"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"चार्ज गर्ने समयमा ब्याट्री सेवर उपलब्ध छैन"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"ब्याट्री सेवर"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"कार्यसम्पादन र पृष्ठभूमि डेटा घटाउँछ"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g> बटन"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"सानो बनाउनुहोस्"</string> <string name="pip_phone_close" msgid="8416647892889710330">"बन्द गर्नुहोस्"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"खारेज गर्न तल तान्नुहोस्"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"तस्बिर मेनुमा तस्बिर"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"मेनु"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> Picture-in-picture मा छ"</string> <string name="pip_notification_message" msgid="5619512781514343311">"तपाईं <xliff:g id="NAME">%s</xliff:g> ले सुविधा प्रयोग नगरोस् भन्ने चाहनुहुन्छ भने ट्याप गरेर सेटिङहरू खोल्नुहोस् र यसलाई निष्क्रिय पार्नुहोस्।"</string> <string name="pip_play" msgid="1417176722760265888">"प्ले गर्नुहोस्"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"मेनु"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> अनुप्रयोग"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"अलर्टहरू"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"ब्याट्री"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"स्क्रिनशटहरू"</string> <string name="notification_channel_general" msgid="4525309436693914482">"सामान्य सन्देशहरू"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"भण्डारण"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"पृष्ठभूमिमा चल्ने अनुप्रयोगहरू"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"ब्याट्री र डेटाका प्रयोग सम्बन्धी विवरणहरूका लागि ट्याप गर्नुहोस्"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"मोबाइल डेटा निष्क्रिय पार्ने हो?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"कुनै अनुप्रयोगको कारणले अनुमतिसम्बन्धी अनुरोध बुझ्न गाह्रो भइरहेकोले सेटिङहरूले तपाईंको प्रतिक्रिया प्रमाणित गर्न सक्दैनन्।"</string> </resources> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 81b74e1dbe8c..ec9fde8dae6f 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"De vingerafdruk voor de RSA-sleutel van de computer is:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Altijd toestaan vanaf deze computer"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB-foutopsporing niet toegestaan"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"De gebruiker die momenteel is ingelogd op dit apparaat, kan USB-foutopsporing niet inschakelen. Als je deze functie wilt gebruiken, schakel je naar de primaire gebruiker."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zoom om scherm te vullen"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Rek uit v. schermvulling"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Screenshot opslaan..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Meer informatie"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Je bent verbonden met <xliff:g id="VPN_APP">%1$s</xliff:g>, waarmee je netwerkactiviteit (waaronder e-mails, apps en websites) kan worden gecontroleerd."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN-instellingen openen"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Vertrouwde gegevens openen"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Je beheerder heeft netwerkregistratie ingeschakeld, waarmee verkeer op je apparaat wordt bijgehouden.\n\nNeem contact op met je beheerder voor meer informatie."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Deze app heeft geen meldingscategorieën"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Meldingen van deze app kunnen niet worden uitgeschakeld"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 van <xliff:g id="NUMBER_1">%d</xliff:g> meldingscategorieën van deze app</item> - <item quantity="one">1 van <xliff:g id="NUMBER_0">%d</xliff:g> meldingscategorie van deze app</item> + <item quantity="other">1 van <xliff:g id="NUMBER_1">%s</xliff:g> meldingscategorieën van deze app</item> + <item quantity="one">1 van <xliff:g id="NUMBER_0">%s</xliff:g> meldingscategorie van deze app</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d minuut</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Accugebruik"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Batterijbesparing niet beschikbaar tijdens opladen"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Batterijbesparing"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Batterijbesparing niet beschikbaar tijdens opladen"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Batterijbesparing"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Vermindert de prestaties en achtergrondgegevens"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Knop <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimaliseren"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Sluiten"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Sleep omlaag om te sluiten"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Scherm-in-scherm-menu"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in scherm-in-scherm"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Als je niet wilt dat <xliff:g id="NAME">%s</xliff:g> deze functie gebruikt, tik je om de instellingen te openen en schakel je de functie uit."</string> <string name="pip_play" msgid="1417176722760265888">"Afspelen"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menu"</string> <string name="tuner_app" msgid="3507057938640108777">"Apps <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Meldingen"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Batterij"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Screenshots"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Algemene berichten"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Opslag"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Apps uitgevoerd op achtergrond"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Tik voor batterij- en datagebruik"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Mobiele data uitschakelen?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Aangezien een app een toestemmingsverzoek afdekt, kan Instellingen je reactie niet verifiëren."</string> </resources> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index 5c3a8e18e541..12101eb6fec2 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -24,7 +24,7 @@ <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"ਸੂਚੀ ਵਿੱਚੋਂ ਹਟਾਓ"</string> <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"ਐਪ ਜਾਣਕਾਰੀ"</string> <string name="status_bar_no_recent_apps" msgid="7374907845131203189">"ਤੁਹਾਡੀਆਂ ਹਾਲੀਆ ਸਕ੍ਰੀਨਾਂ ਇੱਥੇ ਪ੍ਰਗਟ ਹੋਣਗੀਆਂ"</string> - <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"ਹਾਲੀਆ ਐਪਸ ਰੱਦ ਕਰੋ"</string> + <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"ਹਾਲੀਆ ਐਪਾਂ ਰੱਦ ਕਰੋ"</string> <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759"> <item quantity="one">ਰੂਪ-ਰੇਖਾ ਵਿੱਚ %d ਸਕ੍ਰੀਨਾਂ</item> <item quantity="other">ਰੂਪ-ਰੇਖਾ ਵਿੱਚ %d ਸਕ੍ਰੀਨਾਂ</item> @@ -43,7 +43,7 @@ <string name="battery_saver_confirmation_ok" msgid="7507968430447930257">"ਚਾਲੂ ਕਰੋ"</string> <string name="battery_saver_start_action" msgid="5576697451677486320">"ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਕਰੋ"</string> <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"ਸੈਟਿੰਗਾਂ"</string> - <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string> + <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"ਵਾਈ-ਫਾਈ"</string> <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"ਸਕ੍ਰੀਨ ਆਪਣੇ-ਆਪ ਘੁੰਮਾਓ"</string> <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ਮਿਊਟ ਕਰੋ"</string> <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"ਆਟੋ"</string> @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"ਕੰਪਿਊਟਰ ਦਾ RSA ਕੁੰਜੀ ਫਿੰਗਰਪ੍ਰਿੰਟ ਹੈ:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"ਹਮੇਸ਼ਾਂ ਇਸ ਕੰਪਿਊਟਰ ਤੋਂ ਆਗਿਆ ਦਿਓ"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB ਡਿਬੱਗਿੰਗ ਦੀ ਆਗਿਆ ਨਹੀਂ"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ਵਰਤਮਾਨ ਵਿੱਚ ਇਸ ਡੀਵਾਈਸ ਵਿੱਚ ਸਾਈਨ-ਇਨ ਕੀਤਾ ਵਰਤੋਂਕਾਰ USB ਡਿਬੱਗਿੰਗ ਨੂੰ ਚਾਲੂ ਨਹੀਂ ਕਰ ਸਕਦਾ ਹੈ। ਇਸ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਵਰਤਣ ਲਈ, ਮੁੱਖ ਵਰਤੋਂਕਾਰ ਸੰਬੰਧੀ ਖਾਤਾ ਵਰਤੋ।"</string> <string name="compat_mode_on" msgid="6623839244840638213">"ਸਕ੍ਰੀਨ ਭਰਨ ਲਈ ਜ਼ੂਮ ਕਰੋ"</string> <string name="compat_mode_off" msgid="4434467572461327898">"ਸਕ੍ਰੀਨ ਭਰਨ ਲਈ ਸਟ੍ਰੈਚ ਕਰੋ"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string> @@ -151,11 +150,11 @@ <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string> <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"ਰੋਮਿੰਗ"</string> <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"ਕਿਨਾਰਾ"</string> - <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string> + <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"ਵਾਈ-ਫਾਈ"</string> <string name="accessibility_no_sim" msgid="8274017118472455155">"ਕੋਈ SIM ਨਹੀਂ।"</string> - <string name="accessibility_cell_data" msgid="5326139158682385073">"ਮੋਬਾਈਲ ਡੈਟਾ"</string> - <string name="accessibility_cell_data_on" msgid="5927098403452994422">"ਮੋਬਾਈਲ ਡੈਟਾ ਚਾਲੂ ਹੈ"</string> - <string name="accessibility_cell_data_off" msgid="443267573897409704">"ਮੋਬਾਈਲ ਡੈਟਾ ਬੰਦ ਹੈ"</string> + <string name="accessibility_cell_data" msgid="5326139158682385073">"ਮੋਬਾਈਲ ਡਾਟਾ"</string> + <string name="accessibility_cell_data_on" msgid="5927098403452994422">"ਮੋਬਾਈਲ ਡਾਟਾ ਚਾਲੂ"</string> + <string name="accessibility_cell_data_off" msgid="443267573897409704">"ਮੋਬਾਈਲ ਡਾਟਾ ਬੰਦ"</string> <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth ਟੈਦਰਿੰਗ।"</string> <string name="accessibility_airplane_mode" msgid="834748999790763092">"ਏਅਰਪਲੇਨ ਮੋਡ।"</string> <string name="accessibility_vpn_on" msgid="5993385083262856059">"VPN ਚਾਲੂ ਹੈ।"</string> @@ -241,12 +240,12 @@ <string name="accessibility_ambient_display_charging" msgid="9084521679384069087">"ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G ਡੈਟਾ ਰੁਕ ਗਿਆ ਹੈ"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G ਡੈਟਾ ਰੁਕ ਗਿਆ ਹੈ"</string> - <string name="data_usage_disabled_dialog_mobile_title" msgid="6801382439018099779">"ਮੋਬਾਈਲ ਡੈਟਾ ਰੋਕ ਦਿੱਤਾ ਗਿਆ ਹੈ"</string> + <string name="data_usage_disabled_dialog_mobile_title" msgid="6801382439018099779">"ਮੋਬਾਈਲ ਡਾਟਾ ਰੋਕ ਦਿੱਤਾ ਗਿਆ ਹੈ"</string> <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ਡੈਟਾ ਰੁਕ ਗਿਆ ਹੈ"</string> - <string name="data_usage_disabled_dialog" msgid="4919541636934603816">"ਤੁਸੀਂ ਤੁਹਾਡੇ ਵੱਲੋਂ ਸੈੱਟ ਕੀਤੀ ਗਈ ਡੈਟਾ ਸੀਮਾ \'ਤੇ ਪਹੁੰਚ ਚੁੱਕੇ ਹੋ। ਤੁਸੀਂ ਹੁਣ ਮੋਬਾਈਲ ਡੈਟੇ ਦੀ ਵਰਤੋਂ ਨਹੀਂ ਕਰ ਰਹੇ ਹੋ।\n\nਜੇਕਰ ਤੁਸੀਂ ਮੁੜ-ਸ਼ੁਰੂ ਕਰਦੇ ਹੋ, ਤਾਂ ਡੈਟਾ ਵਰਤੋਂ ਲਈ ਖਰਚੇ ਲਾਗੂ ਹੋ ਸਕਦੇ ਹਨ।"</string> + <string name="data_usage_disabled_dialog" msgid="4919541636934603816">"ਤੁਸੀਂ ਤੁਹਾਡੇ ਵੱਲੋਂ ਸੈੱਟ ਕੀਤੀ ਗਈ ਡਾਟਾ ਸੀਮਾ \'ਤੇ ਪਹੁੰਚ ਚੁੱਕੇ ਹੋ। ਤੁਸੀਂ ਹੁਣ ਮੋਬਾਈਲ ਡਾਟੇ ਦੀ ਵਰਤੋਂ ਨਹੀਂ ਕਰ ਰਹੇ ਹੋ।\n\nਜੇਕਰ ਤੁਸੀਂ ਮੁੜ-ਸ਼ੁਰੂ ਕਰਦੇ ਹੋ, ਤਾਂ ਡਾਟਾ ਵਰਤੋਂ ਲਈ ਖਰਚੇ ਲਾਗੂ ਹੋ ਸਕਦੇ ਹਨ।"</string> <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"ਦੁਬਾਰਾ ਸ਼ੁਰੂ ਕਰੋ"</string> <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"ਕੋਈ ਇੰਟਰਨੈਟ ਕਨੈਕਸ਼ਨ ਨਹੀਂ"</string> - <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi ਕਨੈਕਟ ਕੀਤਾ"</string> + <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"ਵਾਈ-ਫਾਈ ਕਨੈਕਟ ਹੈ"</string> <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS ਦੀ ਖੋਜ ਕਰ ਰਿਹਾ ਹੈ"</string> <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS ਵੱਲੋਂ ਸੈੱਟ ਕੀਤਾ ਗਿਆ ਟਿਕਾਣਾ"</string> <string name="accessibility_location_active" msgid="2427290146138169014">"ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਸੇਵਾ ਬੇਨਤੀਆਂ ਸਕਿਰਿਆ"</string> @@ -293,12 +292,12 @@ <string name="quick_settings_user_label" msgid="5238995632130897840">"ਮੈਂ"</string> <string name="quick_settings_user_title" msgid="4467690427642392403">"ਵਰਤੋਂਕਾਰ"</string> <string name="quick_settings_user_new_user" msgid="9030521362023479778">"ਨਵਾਂ ਵਰਤੋਂਕਾਰ"</string> - <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string> + <string name="quick_settings_wifi_label" msgid="9135344704899546041">"ਵਾਈ-ਫਾਈ"</string> <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ਕੋਈ ਨੈੱਟਵਰਕ ਨਹੀਂ"</string> - <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi ਬੰਦ"</string> - <string name="quick_settings_wifi_on_label" msgid="7607810331387031235">"Wi-Fi ਚਾਲੂ"</string> - <string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"ਕੋਈ Wi-Fi ਨੈੱਟਵਰਕ ਉਪਲਬਧ ਨਹੀਂ"</string> + <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"ਵਾਈ-ਫਾਈ ਬੰਦ"</string> + <string name="quick_settings_wifi_on_label" msgid="7607810331387031235">"ਵਾਈ-ਫਾਈ ਚਾਲੂ"</string> + <string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"ਕੋਈ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਉਪਲਬਧ ਨਹੀਂ"</string> <string name="quick_settings_cast_title" msgid="7709016546426454729">"ਕਾਸਟ"</string> <string name="quick_settings_casting" msgid="6601710681033353316">"ਕਾਸਟਿੰਗ"</string> <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"ਬਿਨਾਂ ਨਾਮ ਦਾ ਡੀਵਾਈਸ"</string> @@ -317,7 +316,7 @@ <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ਹੌਟਸਪੌਟ"</string> <string name="quick_settings_notifications_label" msgid="4818156442169154523">"ਸੂਚਨਾਵਾਂ"</string> <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ਫਲੈਸ਼ਲਾਈਟ"</string> - <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ਮੋਬਾਈਲ ਡੈਟਾ"</string> + <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ਮੋਬਾਈਲ ਡਾਟਾ"</string> <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ਡਾਟਾ ਵਰਤੋਂ"</string> <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ਬਾਕੀ ਡੈਟਾ"</string> <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"ਸੀਮਾ ਤੋਂ ਵੱਧ"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"ਹੋਰ ਜਾਣੋ"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"ਤੁਸੀਂ <xliff:g id="VPN_APP">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੋ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ, ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।"</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹੋ"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"ਭਰੋਸੇਯੋਗ ਕ੍ਰੀਡੈਂਸ਼ੀਅਲ ਖੋਲ੍ਹੋ"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਨੇ ਨੈੱਟਵਰਕ ਲੌਗਿੰਗ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਹੋਇਆ ਹੈ, ਜੋ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰਦਾ ਹੈ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string> @@ -504,7 +502,7 @@ <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s। ਮਿਊਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ। ਪਹੁੰਚਯੋਗਤਾ ਸੇਵਾਵਾਂ ਮਿਊਟ ਹੋ ਸਕਦੀਆਂ ਹਨ।"</string> <string name="volume_stream_content_description_vibrate_a11y" msgid="6427727603978431301">"%1$s। ਥਰਥਰਾਹਟ \'ਤੇ ਸੈੱਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> <string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s। ਮਿਊਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> - <string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s ਵੌਲਿਊਮ ਕੰਟਰੋਲ ਵਿਖਾਏ ਗਏ ਹਨ। ਬਰਖ਼ਾਸਤ ਕਰਨ ਲਈ ਉੱਪਰ ਸਵਾਈਪ ਕਰੋ।"</string> + <string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s ਵੌਲਿਊਮ ਕੰਟਰੋਲ ਦਿਖਾਏ ਗਏ ਹਨ। ਖਾਰਜ ਕਰਨ ਲਈ ਉੱਪਰ ਸਵਾਈਪ ਕਰੋ।"</string> <string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"ਵੌਲਿਊਮ ਕੰਟਰੋਲ ਲੁਕਾਏ ਗਏ ਹਨ"</string> <string name="system_ui_tuner" msgid="708224127392452018">"System UI ਟਿਊਨਰ"</string> <string name="show_battery_percentage" msgid="5444136600512968798">"ਜੋਡ਼ੀ ਗਈ ਬੈਟਰੀ ਪ੍ਰਤਿਸ਼ਤਤਾ ਦਿਖਾਓ"</string> @@ -529,12 +527,12 @@ <string name="accessibility_status_bar_hotspot" msgid="4099381329956402865">"ਹੌਟਸਪੌਟ"</string> <string name="accessibility_managed_profile" msgid="6613641363112584120">"ਕੰਮ ਪ੍ਰੋਫਾਈਲ"</string> <string name="tuner_warning_title" msgid="7094689930793031682">"ਕੁਝ ਵਾਸਤੇ ਤਾਂ ਮਜ਼ੇਦਾਰ ਹੈ ਲੇਕਿਨ ਸਾਰਿਆਂ ਵਾਸਤੇ ਨਹੀਂ"</string> - <string name="tuner_warning" msgid="8730648121973575701">"ਸਿਸਟਮ UI ਟਿਊਨਰ ਤੁਹਾਨੂੰ Android ਉਪਭੋਗਤਾ ਇੰਟਰਫੇਸ ਤਬਦੀਲ ਕਰਨ ਅਤੇ ਅਨੁਕੂਲਿਤ ਕਰਨ ਲਈ ਵਾਧੂ ਤਰੀਕੇ ਦਿੰਦਾ ਹੈ। ਇਹ ਪ੍ਰਯੋਗਾਤਮਿਕ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਭਵਿੱਖ ਦੀ ਰੀਲੀਜ਼ ਵਿੱਚ ਬਦਲ ਸਕਦੀਆਂ ਹਨ, ਟੁੱਟ ਸਕਦੀਆਂ ਹਨ, ਜਾਂ ਅਲੋਪ ਹੋ ਸਕਦੀਆਂ ਹਨ। ਸਾਵਧਾਨੀ ਨਾਲ ਅੱਗੇ ਵੱਧੋ।"</string> + <string name="tuner_warning" msgid="8730648121973575701">"ਸਿਸਟਮ UI ਟਿਊਨਰ ਤੁਹਾਨੂੰ Android ਵਰਤੋਂਕਾਰ ਇੰਟਰਫੇਸ ਤਬਦੀਲ ਕਰਨ ਅਤੇ ਵਿਉਂਤਬੱਧ ਕਰਨ ਲਈ ਵਾਧੂ ਤਰੀਕੇ ਦਿੰਦਾ ਹੈ। ਇਹ ਪ੍ਰਯੋਗਾਤਮਿਕ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਭਵਿੱਖ ਦੀ ਰੀਲੀਜ਼ ਵਿੱਚ ਬਦਲ ਸਕਦੀਆਂ ਹਨ, ਟੁੱਟ ਸਕਦੀਆਂ ਹਨ, ਜਾਂ ਅਲੋਪ ਹੋ ਸਕਦੀਆਂ ਹਨ। ਸਾਵਧਾਨੀ ਨਾਲ ਅੱਗੇ ਵੱਧੋ।"</string> <string name="tuner_persistent_warning" msgid="8597333795565621795">"ਇਹ ਪ੍ਰਯੋਗਾਤਮਿਕ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਭਵਿੱਖ ਦੀ ਰੀਲੀਜ਼ ਵਿੱਚ ਬਦਲ ਸਕਦੀਆਂ ਹਨ, ਟੁੱਟ ਸਕਦੀਆਂ ਹਨ, ਜਾਂ ਅਲੋਪ ਹੋ ਸਕਦੀਆਂ ਹਨ। ਸਾਵਧਾਨੀ ਨਾਲ ਅੱਗੇ ਵੱਧੋ।"</string> <string name="got_it" msgid="2239653834387972602">"ਸਮਝ ਲਿਆ"</string> - <string name="tuner_toast" msgid="603429811084428439">"ਵਧਾਈਆਂ! ਸਿਸਟਮ UI ਟਿਊਨਰ ਨੂੰ ਸੈਟਿੰਗਜ਼ ਵਿੱਚ ਜੋੜਿਆ ਗਿਆ ਹੈ"</string> + <string name="tuner_toast" msgid="603429811084428439">"ਵਧਾਈਆਂ! ਸਿਸਟਮ UI ਟਿਊਨਰ ਨੂੰ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਜੋੜਿਆ ਗਿਆ ਹੈ"</string> <string name="remove_from_settings" msgid="8389591916603406378">"ਸੈਟਿੰਗਜ਼ ਤੋਂ ਹਟਾਓ"</string> - <string name="remove_from_settings_prompt" msgid="6069085993355887748">"ਕੀ ਸੈਟਿੰਗਜ਼ ਤੋਂ ਸਿਸਟਮ UI ਟਿਊਨਰ ਨੂੰ ਹਟਾਉਣਾ ਹੈ ਅਤੇ ਇਸਦੀਆਂ ਸਾਰੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਉਪਯੋਗ ਕਰਨ ਤੋਂ ਰੋਕਣਾ ਹੈ?"</string> + <string name="remove_from_settings_prompt" msgid="6069085993355887748">"ਕੀ ਸੈਟਿੰਗਾਂ ਤੋਂ ਸਿਸਟਮ UI ਟਿਊਨਰ ਨੂੰ ਹਟਾਉਣਾ ਹੈ ਅਤੇ ਇਸਦੀਆਂ ਸਾਰੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਉਪਯੋਗ ਕਰਨ ਤੋਂ ਰੋਕਣਾ ਹੈ?"</string> <string name="activity_not_found" msgid="348423244327799974">"ਐਪਲੀਕੇਸ਼ਨ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਤੇ ਸਥਾਪਤ ਨਹੀਂ ਕੀਤੀ ਗਈ ਹੈ"</string> <string name="clock_seconds" msgid="7689554147579179507">"ਘੜੀ ਸਕਿੰਟ ਦਿਖਾਓ"</string> <string name="clock_seconds_desc" msgid="6282693067130470675">"ਸਥਿਤੀ ਬਾਰ ਵਿੱਚ ਘੜੀ ਸਕਿੰਟ ਦਿਖਾਓ। ਬੈਟਰੀ ਸਮਰੱਥਾ ਤੇ ਅਸਰ ਪੈ ਸਕਦਾ ਹੈ।"</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"ਇਸ ਐਪ ਵਿੱਚ ਸੂਚਨਾ ਸ਼੍ਰੇਣੀਆਂ ਨਹੀਂ ਹਨ"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"ਇਸ ਐਪ ਤੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਬੰਦ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">ਇਸ ਐਪ ਤੋਂ <xliff:g id="NUMBER_1">%d</xliff:g> ਸੂਚਨਾ ਸ਼੍ਰੇਣੀ ਵਿੱਚੋਂ 1</item> - <item quantity="other">ਇਸ ਐਪ ਤੋਂ <xliff:g id="NUMBER_1">%d</xliff:g> ਸੂਚਨਾ ਸ਼੍ਰੇਣੀਆਂ ਵਿੱਚੋਂ 1</item> + <item quantity="one">ਇਸ ਐਪ ਤੋਂ <xliff:g id="NUMBER_1">%s</xliff:g> ਸੂਚਨਾ ਸ਼੍ਰੇਣੀ ਵਿੱਚੋਂ 1</item> + <item quantity="other">ਇਸ ਐਪ ਤੋਂ <xliff:g id="NUMBER_1">%s</xliff:g> ਸੂਚਨਾ ਸ਼੍ਰੇਣੀਆਂ ਵਿੱਚੋਂ 1</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="other"> %d ਮਿੰਟ</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"ਬੈਟਰੀ ਵਰਤੋਂ"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"ਬੈਟਰੀ ਸੇਵਰ ਚਾਰਜਿੰਗ ਦੌਰਾਨ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"ਬੈਟਰੀ ਸੇਵਰ"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"ਬੈਟਰੀ ਸੇਵਰ ਚਾਰਜਿੰਗ ਦੌਰਾਨ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"ਬੈਟਰੀ ਸੇਵਰ"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"ਕਾਰਗੁਜ਼ਾਰੀ ਅਤੇ ਬੈਕਗ੍ਰਾਊਂਡ ਡੈਟੇ ਨੂੰ ਘਟਾਉਂਦਾ ਹੈ"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"ਬਟਨ <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -646,7 +644,7 @@ <string name="accessibility_data_saver_off" msgid="8841582529453005337">"ਡਾਟਾ ਸੇਵਰ ਬੰਦ ਹੈ"</string> <string name="switch_bar_on" msgid="1142437840752794229">"ਚਾਲੂ"</string> <string name="switch_bar_off" msgid="8803270596930432874">"ਬੰਦ"</string> - <string name="nav_bar" msgid="1993221402773877607">"ਆਵਾਗੌਣ ਪੱਟੀ"</string> + <string name="nav_bar" msgid="1993221402773877607">"ਦਿਸ਼ਾ-ਨਿਰਦੇਸ਼ ਪੱਟੀ"</string> <string name="nav_bar_layout" msgid="3664072994198772020">"ਖਾਕਾ"</string> <string name="left_nav_bar_button_type" msgid="8555981238887546528">"ਵਧੇਰੇ ਖੱਬੇ ਬਟਨ ਕਿਸਮ"</string> <string name="right_nav_bar_button_type" msgid="2481056627065649656">"ਵਧੇਰੇ ਸੱਜੇ ਬਟਨ ਕਿਸਮ"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"ਛੋਟਾ ਕਰੋ"</string> <string name="pip_phone_close" msgid="8416647892889710330">"ਬੰਦ ਕਰੋ"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ਖਾਰਜ ਕਰਨ ਲਈ ਹੇਠਾਂ ਘਸੀਟੋ"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"ਤਸਵੀਰ-ਵਿੱਚ-ਤਸਵੀਰ ਮੀਨੂ"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"ਮੀਨੂ"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ਤਸਵੀਰ-ਵਿੱਚ-ਤਸਵੀਰ \'ਚ ਹੈ"</string> <string name="pip_notification_message" msgid="5619512781514343311">"ਜੇ ਤੁਸੀਂ ਨਹੀਂ ਚਾਹੁੰਦੇ ਕਿ <xliff:g id="NAME">%s</xliff:g> ਐਪ ਇਸ ਵਿਸ਼ੇਸ਼ਤਾ ਦੀ ਵਰਤੋਂ ਕਰੇ, ਤਾਂ ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹਣ ਲਈ ਟੈਪ ਕਰੋ ਅਤੇ ਇਸਨੂੰ ਬੰਦ ਕਰੋ।"</string> <string name="pip_play" msgid="1417176722760265888">"ਚਲਾਓ"</string> @@ -737,7 +735,7 @@ <string name="pip_skip_to_prev" msgid="1955311326688637914">"ਪਿਛਲੇ \'ਤੇ ਜਾਓ"</string> <string name="thermal_shutdown_title" msgid="4458304833443861111">"ਗਰਮ ਹੋਣ ਕਾਰਨ ਫ਼ੋਨ ਬੰਦ ਹੋ ਗਿਆ"</string> <string name="thermal_shutdown_message" msgid="9006456746902370523">"ਤੁਹਾਡਾ ਫ਼ੋਨ ਹੁਣ ਸਹੀ ਚੱਲ ਰਿਹਾ ਹੈ"</string> - <string name="thermal_shutdown_dialog_message" msgid="566347880005304139">"ਤੁਹਾਡਾ ਫ਼ੋਨ ਬਹੁਤ ਗਰਮ ਸੀ, ਇਸ ਲਈ ਇਹ ਠੰਡਾ ਹੋਣ ਵਾਸਤੇ ਬੰਦ ਹੋ ਗਿਆ ਸੀ। ਤੁਹਾਡਾ ਫ਼ੋਨ ਹੁਣ ਸਹੀ ਚੱਲ ਰਿਹਾ ਹੈ।\n\nਤੁਹਾਡਾ ਫ਼ੋਨ ਬਹੁਤ ਗਰਮ ਹੋ ਸਕਦਾ ਹੈ ਜੇ:\n • ਤੁਸੀਂ ਸਰੋਤਾਂ ਦੀ ਵੱਧ ਵਰਤੋਂ ਵਾਲੀਆਂ ਐਪਾਂ (ਜਿਵੇਂ ਗੇਮਿੰਗ, ਵੀਡੀਓ, ਜਾਂ ਆਵਾਗੌਣ ਐਪਾਂ) ਵਰਤਦੇ ਹੋ \n • ਵੱਡੀਆਂ ਫ਼ਾਈਲਾਂ ਡਾਊਨਲੋਡ ਜਾਂ ਅੱਪਲੋਡ ਕਰਦੇ ਹੋ\n • ਆਪਣੇ ਫ਼ੋਨ ਨੂੰ ਉੱਚ ਤਾਪਮਾਨਾਂ ਵਿੱਚ ਵਰਤਦੇ ਹੋ"</string> + <string name="thermal_shutdown_dialog_message" msgid="566347880005304139">"ਤੁਹਾਡਾ ਫ਼ੋਨ ਬਹੁਤ ਗਰਮ ਸੀ, ਇਸ ਲਈ ਇਹ ਠੰਡਾ ਹੋਣ ਵਾਸਤੇ ਬੰਦ ਹੋ ਗਿਆ ਸੀ। ਤੁਹਾਡਾ ਫ਼ੋਨ ਹੁਣ ਸਹੀ ਚੱਲ ਰਿਹਾ ਹੈ।\n\nਤੁਹਾਡਾ ਫ਼ੋਨ ਬਹੁਤ ਗਰਮ ਹੋ ਸਕਦਾ ਹੈ ਜੇ:\n • ਤੁਸੀਂ ਸਰੋਤਾਂ ਦੀ ਵੱਧ ਵਰਤੋਂ ਵਾਲੀਆਂ ਐਪਾਂ (ਜਿਵੇਂ ਗੇਮਿੰਗ, ਵੀਡੀਓ, ਜਾਂ ਦਿਸ਼ਾ-ਨਿਰਦੇਸ਼ ਐਪਾਂ) ਵਰਤਦੇ ਹੋ \n • ਵੱਡੀਆਂ ਫ਼ਾਈਲਾਂ ਡਾਊਨਲੋਡ ਜਾਂ ਅੱਪਲੋਡ ਕਰਦੇ ਹੋ\n • ਆਪਣੇ ਫ਼ੋਨ ਨੂੰ ਉੱਚ ਤਾਪਮਾਨਾਂ ਵਿੱਚ ਵਰਤਦੇ ਹੋ"</string> <string name="high_temp_title" msgid="4589508026407318374">"ਫ਼ੋਨ ਗਰਮ ਹੋ ਰਿਹਾ ਹੈ"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"ਫ਼ੋਨ ਦੇ ਠੰਡਾ ਹੋਣ ਦੇ ਦੌਰਾਨ ਕੁਝ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਸੀਮਿਤ ਹੁੰਦੀਆਂ ਹਨ"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"ਤੁਹਾਡਾ ਫ਼ੋਨ ਸਵੈਚਲਿਤ ਰੂਪ ਵਿੱਚ ਠੰਡਾ ਹੋਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੇਗਾ। ਤੁਸੀਂ ਹਾਲੇ ਵੀ ਆਪਣੇ ਫ਼ੋਨ ਨੂੰ ਵਰਤ ਸਕਦੇ ਹੋ, ਪਰੰਤੂ ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਇਹ ਵਧੇਰੇ ਹੌਲੀ ਚੱਲੇ।\n\nਇੱਕ ਵਾਰ ਠੰਡਾ ਹੋਣ ਤੋਂ ਬਾਅਦ ਤੁਹਾਡਾ ਫ਼ੋਨ ਸਧਾਰਨ ਤੌਰ \'ਤੇ ਚੱਲੇਗਾ।"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"ਮੀਨੂ"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> ਐਪ"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"ਸੁਚੇਤਨਾਵਾਂ"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"ਬੈਟਰੀ"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string> <string name="notification_channel_general" msgid="4525309436693914482">"ਆਮ ਸੁਨੇਹੇ"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"ਸਟੋਰੇਜ"</string> @@ -765,8 +762,8 @@ <string name="instant_apps_message" msgid="8116608994995104836">"ਤਤਕਾਲ ਐਪਾਂ ਨੂੰ ਸਥਾਪਨਾ ਦੀ ਲੋੜ ਨਹੀਂ ਹੈ।"</string> <string name="app_info" msgid="6856026610594615344">"ਐਪ ਜਾਣਕਾਰੀ"</string> <string name="go_to_web" msgid="1106022723459948514">"ਵੈੱਬ \'ਤੇ ਜਾਓ"</string> - <string name="mobile_data" msgid="7094582042819250762">"ਮੋਬਾਈਲ ਡੈਟਾ"</string> - <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ਬੰਦ ਹੈ"</string> + <string name="mobile_data" msgid="7094582042819250762">"ਮੋਬਾਈਲ ਡਾਟਾ"</string> + <string name="wifi_is_off" msgid="1838559392210456893">"ਵਾਈ-ਫਾਈ ਬੰਦ ਹੈ"</string> <string name="bt_is_off" msgid="2640685272289706392">"ਬਲੂਟੁੱਥ ਬੰਦ ਹੈ"</string> <string name="dnd_is_off" msgid="6167780215212497572">"\'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਬੰਦ ਹੈ"</string> <string name="qs_dnd_prompt_auto_rule" msgid="862559028345233052">"ਸਵੈਚਲਿਤ ਨਿਯਮ (<xliff:g id="ID_1">%s</xliff:g>) ਦੁਆਰਾ \'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਚਾਲੂ ਕੀਤਾ ਗਿਆ ਸੀ।"</string> @@ -777,5 +774,6 @@ <string name="qs_dnd_replace" msgid="8019520786644276623">"ਬਦਲੋ"</string> <string name="running_foreground_services_title" msgid="381024150898615683">"ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲ ਰਹੀਆਂ ਐਪਾਂ"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"ਬੈਟਰੀ ਅਤੇ ਡਾਟਾ ਵਰਤੋਂ ਸਬੰਧੀ ਵੇਰਵਿਆਂ ਲਈ ਟੈਪ ਕਰੋ"</string> - <string name="data_usage_disable_mobile" msgid="5116269981510015864">"ਮੋਬਾਈਲ ਡੈਟਾ ਬੰਦ ਕਰੀਏ?"</string> + <string name="data_usage_disable_mobile" msgid="5116269981510015864">"ਮੋਬਾਈਲ ਡਾਟਾ ਬੰਦ ਕਰਨਾ ਹੈ?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"ਕਿਸੇ ਐਪ ਵੱਲੋਂ ਇਜਾਜ਼ਤ ਬੇਨਤੀ ਨੂੰ ਢਕੇ ਜਾਣ ਕਾਰਨ ਸੈਟਿੰਗਾਂ ਤੁਹਾਡੇ ਜਵਾਬ ਦੀ ਪੁਸ਼ਟੀ ਨਹੀਂ ਕਰ ਸਕਦੀਆਂ।"</string> </resources> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 3905ec857125..7ff9b73b2bf6 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -66,8 +66,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Odcisk cyfrowy klucza RSA komputera to:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Zawsze zezwalaj z tego komputera"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Debugowanie USB jest niedozwolone"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Użytkownik obecnie zalogowany na tym urządzeniu nie może włączyć debugowania USB. Aby użyć tej funkcji, przełącz się na użytkownika głównego."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Powiększ, aby wypełnić ekran"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Rozciągnij, aby wypełnić ekran"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Zapisywanie zrzutu ekranu..."</string> @@ -461,8 +460,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Więcej informacji"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Łączysz się z aplikacją <xliff:g id="VPN_APP">%1$s</xliff:g>, która może monitorować Twoją aktywność w sieci, w tym e-maile, aplikacje i strony internetowe."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Otwórz ustawienia VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Otwórz zaufane dane logowania"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administrator włączył rejestrowanie sieciowe, które pozwala monitorować ruch na Twoim urządzeniu.\n\nAby dowiedzieć się więcej, skontaktuj się z administratorem."</string> @@ -562,10 +560,10 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Ta aplikacja nie ma kategorii powiadomień"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Powiadomień z tej aplikacji nie można wyłączyć"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="few">1 z <xliff:g id="NUMBER_1">%d</xliff:g> kategorii powiadomień z tej aplikacji</item> - <item quantity="many">1 z <xliff:g id="NUMBER_1">%d</xliff:g> kategorii powiadomień z tej aplikacji</item> - <item quantity="other">1 z <xliff:g id="NUMBER_1">%d</xliff:g> kategorii powiadomień z tej aplikacji</item> - <item quantity="one">1 z <xliff:g id="NUMBER_0">%d</xliff:g> kategorii powiadomień z tej aplikacji</item> + <item quantity="few">1 z <xliff:g id="NUMBER_1">%s</xliff:g> kategorii powiadomień z tej aplikacji</item> + <item quantity="many">1 z <xliff:g id="NUMBER_1">%s</xliff:g> kategorii powiadomień z tej aplikacji</item> + <item quantity="other">1 z <xliff:g id="NUMBER_1">%s</xliff:g> kategorii powiadomień z tej aplikacji</item> + <item quantity="one">1 z <xliff:g id="NUMBER_0">%s</xliff:g> kategorii powiadomień z tej aplikacji</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -599,8 +597,8 @@ <item quantity="one">]%d minuta</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Wykorzystanie baterii"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Oszczędzanie baterii nie jest dostępne podczas ładowania"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Oszczędzanie baterii"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Oszczędzanie baterii nie jest dostępne podczas ładowania"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Oszczędzanie baterii"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Zmniejsza wydajność i ogranicza dane w tle"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Przycisk <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -740,7 +738,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalizuj"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Zamknij"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Przeciągnij w dół, by zamknąć"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Menu funkcji Obraz w obrazie"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"Aplikacja <xliff:g id="NAME">%s</xliff:g> działa w trybie obraz w obrazie"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Jeśli nie chcesz, by aplikacja <xliff:g id="NAME">%s</xliff:g> korzystała z tej funkcji, otwórz ustawienia i ją wyłącz."</string> <string name="pip_play" msgid="1417176722760265888">"Odtwórz"</string> @@ -768,8 +766,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menu"</string> <string name="tuner_app" msgid="3507057938640108777">"Aplikacja <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerty"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Bateria"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Zrzuty ekranu"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Wiadomości"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Pamięć wewnętrzna"</string> @@ -790,4 +787,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Aplikacje działające w tle"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Kliknij, by wyświetlić szczegóły wykorzystania baterii i transmisji danych"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Wyłączyć mobilną transmisję danych?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Aplikacja Ustawienia nie może zweryfikować Twojej odpowiedzi, ponieważ inna aplikacja zasłania prośbę o udzielenie uprawnień."</string> </resources> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index 9a281ea463a2..ac938e58dde2 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"A impressão digital da chave RSA deste computador é:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Sempre permitir a partir deste computador"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Depuração USB não permitida"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"O usuário conectado a este dispositivo não pode ativar a depuração USB. Para usar esse recurso, mude para o usuário principal \"NAME\"."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zoom p/ preencher a tela"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Ampliar p/ preencher tela"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Salvando captura de tela..."</string> @@ -459,8 +458,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Saber mais"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Você está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorar sua atividade na rede, incluindo e-mails, apps e websites."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Abrir configurações de VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Abrir credenciais confiáveis"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Seu administrador ativou o registro de rede, que monitora o tráfego no seu dispositivo.\n\nPara ver mais informações, entre em contato com o administrador."</string> @@ -560,8 +558,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Este app não tem categorias de notificação"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Notificações deste app não podem ser desativadas"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 de <xliff:g id="NUMBER_1">%d</xliff:g> categoria de notificação deste app</item> - <item quantity="other">1 de <xliff:g id="NUMBER_1">%d</xliff:g> categorias de notificação deste app</item> + <item quantity="one">1 de <xliff:g id="NUMBER_1">%s</xliff:g> categoria de notificação deste app</item> + <item quantity="other">1 de <xliff:g id="NUMBER_1">%s</xliff:g> categorias de notificação deste app</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -589,8 +587,8 @@ <item quantity="other">%d minutos</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Uso da bateria"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"A Economia de bateria não fica disponível durante o carregamento"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Economia de bateria"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"O recurso \"Economia de bateria\" não fica disponível durante o carregamento"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Economia de bateria"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduz o desempenho e os dados em segundo plano"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Botão <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -730,7 +728,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Fechar"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arraste para baixo para dispensar"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Menu Picture-in-picture"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> está em picture-in-picture"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Se você não deseja que o app <xliff:g id="NAME">%s</xliff:g> use este recurso, toque para abrir as configurações e desativá-lo."</string> <string name="pip_play" msgid="1417176722760265888">"Reproduzir"</string> @@ -758,8 +756,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menu"</string> <string name="tuner_app" msgid="3507057938640108777">"App <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Bateria"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de tela"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Mensagens gerais"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Armazenamento"</string> @@ -780,4 +777,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Apps sendo executados em segundo plano"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Tocar para ver detalhes sobre a bateria e o uso de dados"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Desativar os dados móveis?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Como um app está ocultando uma solicitação de permissão, as configurações não podem verificar sua resposta."</string> </resources> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index 83f5630b4941..7d3e9d5fca36 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"A impressão digital da chave RSA do computador é:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Permitir sempre a partir deste computador"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Depuração USB não permitida"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"O utilizador com sessão iniciada atualmente neste dispositivo não pode ativar a depuração USB. Para utilizar esta funcionalidade, mude para o utilizador principal."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zoom para preencher o ecrã"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Esticar p. caber em ec. int."</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"A guardar captura de ecrã..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Saiba mais"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Abrir as definições de VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Abrir credenciais fidedignas"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"O seu administrador ativou os registos de rede, que monitorizam o tráfego no seu dispositivo.\n\nPara obter mais informações, contacte o administrador."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Esta aplicação não tem categorias de notificação"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Não é possível desativar as notificações desta aplicação"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 de <xliff:g id="NUMBER_0">%d</xliff:g> categoria de notificação desta aplicação</item> - <item quantity="other">1 de <xliff:g id="NUMBER_1">%d</xliff:g> categorias de notificação desta aplicação</item> + <item quantity="one">1 de <xliff:g id="NUMBER_0">%s</xliff:g> categoria de notificação desta aplicação</item> + <item quantity="other">1 de <xliff:g id="NUMBER_1">%s</xliff:g> categorias de notificação desta aplicação</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="other">%d minutos</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Utiliz. da bateria"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Poupança de bateria não disponível durante o carregamento"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Poupança de bateria"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Poupança de bateria não disponível durante o carregamento"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Poupança de bateria"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduz o desempenho e os dados de segundo plano"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Botão <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Início"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Fechar"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arrastar para baixo para ignorar"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Menu de ecrã no ecrã"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"A aplicação <xliff:g id="NAME">%s</xliff:g> está no modo de ecrã no ecrã"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Se não pretende que a aplicação <xliff:g id="NAME">%s</xliff:g> utilize esta funcionalidade, toque para abrir as definições e desative-a."</string> <string name="pip_play" msgid="1417176722760265888">"Reproduzir"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menu"</string> <string name="tuner_app" msgid="3507057938640108777">"Aplicação <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Bateria"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de ecrã"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Mensagens gerais"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Armazenamento"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Aplicações em execução em segundo plano"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Toque para obter detalhes acerca da utilização da bateria e dos dados"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Pretende desativar os dados móveis?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Uma vez que uma aplicação está a ocultar um pedido de autorização, as Definições não conseguem validar a sua resposta."</string> </resources> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 9a281ea463a2..ac938e58dde2 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"A impressão digital da chave RSA deste computador é:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Sempre permitir a partir deste computador"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Depuração USB não permitida"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"O usuário conectado a este dispositivo não pode ativar a depuração USB. Para usar esse recurso, mude para o usuário principal \"NAME\"."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zoom p/ preencher a tela"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Ampliar p/ preencher tela"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Salvando captura de tela..."</string> @@ -459,8 +458,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Saber mais"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Você está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorar sua atividade na rede, incluindo e-mails, apps e websites."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Abrir configurações de VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Abrir credenciais confiáveis"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Seu administrador ativou o registro de rede, que monitora o tráfego no seu dispositivo.\n\nPara ver mais informações, entre em contato com o administrador."</string> @@ -560,8 +558,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Este app não tem categorias de notificação"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Notificações deste app não podem ser desativadas"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 de <xliff:g id="NUMBER_1">%d</xliff:g> categoria de notificação deste app</item> - <item quantity="other">1 de <xliff:g id="NUMBER_1">%d</xliff:g> categorias de notificação deste app</item> + <item quantity="one">1 de <xliff:g id="NUMBER_1">%s</xliff:g> categoria de notificação deste app</item> + <item quantity="other">1 de <xliff:g id="NUMBER_1">%s</xliff:g> categorias de notificação deste app</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -589,8 +587,8 @@ <item quantity="other">%d minutos</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Uso da bateria"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"A Economia de bateria não fica disponível durante o carregamento"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Economia de bateria"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"O recurso \"Economia de bateria\" não fica disponível durante o carregamento"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Economia de bateria"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduz o desempenho e os dados em segundo plano"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Botão <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -730,7 +728,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Fechar"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arraste para baixo para dispensar"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Menu Picture-in-picture"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> está em picture-in-picture"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Se você não deseja que o app <xliff:g id="NAME">%s</xliff:g> use este recurso, toque para abrir as configurações e desativá-lo."</string> <string name="pip_play" msgid="1417176722760265888">"Reproduzir"</string> @@ -758,8 +756,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menu"</string> <string name="tuner_app" msgid="3507057938640108777">"App <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Bateria"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturas de tela"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Mensagens gerais"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Armazenamento"</string> @@ -780,4 +777,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Apps sendo executados em segundo plano"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Tocar para ver detalhes sobre a bateria e o uso de dados"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Desativar os dados móveis?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Como um app está ocultando uma solicitação de permissão, as configurações não podem verificar sua resposta."</string> </resources> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index ec1cc4b79b28..0bcb1823887b 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -65,8 +65,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Amprenta digitală din cheia RSA a computerului este:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Permiteți întotdeauna de pe acest computer"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Remedierea erorilor prin USB nu este permisă"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Utilizatorul conectat momentan pe acest dispozitiv nu poate activa remedierea erorilor prin USB. Pentru a folosi această funcție, comutați la utilizatorul principal."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zoom pt. a umple ecranul"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Înt. pt. a umple ecranul"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Se salv. captura de ecran..."</string> @@ -461,8 +460,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Aflați mai multe"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"V-ați conectat la aplicația <xliff:g id="VPN_APP">%1$s</xliff:g>, care vă poate monitoriza activitatea în rețea, inclusiv e-mailurile, aplicațiile și site-urile accesate."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Deschideți Setări VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Deschideți datele de conectare de încredere"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administratorul dvs. a activat înregistrarea în jurnal pentru rețea, funcție ce monitorizează traficul de pe dispozitivul dvs.\n\nPentru mai multe informații, contactați administratorul."</string> @@ -562,9 +560,9 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Această aplicație nu are categorii de notificare"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Notificările din această aplicație nu pot fi dezactivate"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="few">1 din <xliff:g id="NUMBER_1">%d</xliff:g> categorii de notificare din această aplicație</item> - <item quantity="other">1 din <xliff:g id="NUMBER_1">%d</xliff:g> de categorii de notificare din această aplicație</item> - <item quantity="one">1 din <xliff:g id="NUMBER_0">%d</xliff:g> categorie de notificare din această aplicație</item> + <item quantity="few">1 din <xliff:g id="NUMBER_1">%s</xliff:g> categorii de notificare din această aplicație</item> + <item quantity="other">1 din <xliff:g id="NUMBER_1">%s</xliff:g> de categorii de notificare din această aplicație</item> + <item quantity="one">1 din <xliff:g id="NUMBER_0">%s</xliff:g> categorie de notificare din această aplicație</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -595,8 +593,8 @@ <item quantity="one">%d minut</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Utilizarea bateriei"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Economisirea bateriei nu este disponibilă pe durata încărcării"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Economisirea bateriei"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Economisirea bateriei nu este disponibilă pe durata încărcării"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Economisirea energiei"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduce performanța și datele de fundal"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Butonul <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"La început"</string> @@ -736,7 +734,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizați"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Închideți"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Trageți în jos pentru a închide"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Meniul picture-in-picture"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Meniu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> este în modul picture-in-picture"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Dacă nu doriți ca <xliff:g id="NAME">%s</xliff:g> să utilizeze această funcție, atingeți pentru a deschide setările și dezactivați-o."</string> <string name="pip_play" msgid="1417176722760265888">"Redați"</string> @@ -764,8 +762,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Meniu"</string> <string name="tuner_app" msgid="3507057938640108777">"Aplicația <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Alerte"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Baterie"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Capturi de ecran"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Mesaje generale"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Stocare"</string> @@ -786,4 +783,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Aplicațiile rulează în fundal"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Atingeți pentru mai multe detalii privind bateria și utilizarea datelor"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Dezactivați datele mobile?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Deoarece o aplicație acoperă o solicitare de permisiune, Setările nu vă pot verifica răspunsul."</string> </resources> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 9bb93d6eb9ff..101d3e8a17f0 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -66,8 +66,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Цифровой отпечаток ключа RSA:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Всегда разрешать отладку с этого компьютера"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Отладка по USB запрещена"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"В этом аккаунте нельзя включить отладку по USB. Перейдите в аккаунт основного пользователя."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Подогнать по размерам экрана"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Растянуть на весь экран"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Сохранение..."</string> @@ -463,8 +462,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Подробнее…"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Запущено приложение \"<xliff:g id="VPN_APP">%1$s</xliff:g>\". Оно может отслеживать ваши действия в сети, включая работу с электронной почтой, приложениями и сайтами."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Открыть настройки VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Открыть надежные сертификаты"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Администратор включил ведение сетевого журнала, чтобы отслеживать трафик на вашем устройстве.\n\nДля получения подробной информации обращайтесь к администратору."</string> @@ -564,10 +562,10 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"В приложении нет категорий уведомлений"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Уведомления этого приложения нельзя отключить"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 из <xliff:g id="NUMBER_1">%d</xliff:g> категории уведомлений этого приложения</item> - <item quantity="few">1 из <xliff:g id="NUMBER_1">%d</xliff:g> категорий уведомлений этого приложения</item> - <item quantity="many">1 из <xliff:g id="NUMBER_1">%d</xliff:g> категорий уведомлений этого приложения</item> - <item quantity="other">1 из <xliff:g id="NUMBER_1">%d</xliff:g> категории уведомлений этого приложения</item> + <item quantity="one">1 из <xliff:g id="NUMBER_1">%s</xliff:g> категории уведомлений этого приложения</item> + <item quantity="few">1 из <xliff:g id="NUMBER_1">%s</xliff:g> категорий уведомлений этого приложения</item> + <item quantity="many">1 из <xliff:g id="NUMBER_1">%s</xliff:g> категорий уведомлений этого приложения</item> + <item quantity="other">1 из <xliff:g id="NUMBER_1">%s</xliff:g> категории уведомлений этого приложения</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -601,8 +599,8 @@ <item quantity="other">%d минуты</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Уровень заряда"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Режим энергосбережения нельзя включить во время зарядки"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Режим энергосбережения"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Режим энергосбережения нельзя включить во время зарядки"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Режим энергосбережения"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Ограничивает производительность и фоновую передачу данных"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Кнопка <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Главный экран"</string> @@ -742,7 +740,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Свернуть"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Закрыть"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Чтобы закрыть, потяните вниз"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Меню \"Картинка в картинке\""</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Меню"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> находится в режиме \"Картинка в картинке\""</string> <string name="pip_notification_message" msgid="5619512781514343311">"Чтобы отключить эту функцию для приложения \"<xliff:g id="NAME">%s</xliff:g>\", перейдите в настройки."</string> <string name="pip_play" msgid="1417176722760265888">"Воспроизвести"</string> @@ -770,8 +768,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Меню"</string> <string name="tuner_app" msgid="3507057938640108777">"Приложение \"<xliff:g id="APP">%1$s</xliff:g>\""</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Уведомления"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Батарея"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Скриншоты"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Сообщения"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Хранилище"</string> @@ -792,4 +789,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Приложения, работающие в фоновом режиме"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Нажмите, чтобы проверить энергопотребление и трафик"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Отключить мобильный Интернет?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Невозможно принять ваше согласие, поскольку запрос скрыт другим приложением."</string> </resources> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index 108a8e08dcbe..5343bb3e2f40 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"මෙම පරිගණකයේ RSA යතුරු ඇඟිලි සටහන වන්නේ:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"සැම විටම මෙම පරිගණකයෙන් ඉඩ ලබා දෙන්න"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB නිදොස්කරණය වෙත අවසර නැහැ"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"දැනට මෙම උපාංගයට පුරා ඇති පරිශීලකයාට USB නිදොස්කරණය ක්රියාත්මක කළ නොහැක. මෙම විශේෂාංගය භාවිතා කිරීම සඳහා, මූලික පරිශීලකයා වෙත මාරු වෙන්න."</string> <string name="compat_mode_on" msgid="6623839244840638213">"තිරය පිරවීමට විශාලනය කරන්න"</string> <string name="compat_mode_off" msgid="4434467572461327898">"තිරය පිරවීමට අදින්න"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"තිර රුව සුරකිමින්…"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"තව දැන ගන්න"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"ඊ-තැපැල්, යෙදුම් සහ වෙබ් අඩවි ඇතුළු ඔබේ ජාල ක්රියාකාරකම් නිරීක්ෂණය කළ හැකි <xliff:g id="VPN_APP">%1$s</xliff:g>, වෙත ඔබ සම්බන්ධ වී ඇත."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN සැකසීම් විවෘත කරන්න"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"විශ්වාසි අක්තපත්ර විවෘත කරන්න"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"ඔබගේ පරිපාලක ඔබගේ උපාංගය මත තදබදය නිරීක්ෂණය කරන, ජාල ඇතුළු වීම ක්රියාත්මක කර ඇත.\n\nවැඩිදුර තොරතුරු සඳහා ඔබේ පරිපාලක අමතන්න."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"මෙම යෙදුම හට දැනුම්දීම් ප්රවර්ග නොමැත"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"මෙම යෙදුම වෙතින් වන දැනුම්දීම් ක්රියාවිරහිත කළ නොහැකිය"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">මෙම යෙදුමෙන් දැනුම්දීම් ප්රවර්ග <xliff:g id="NUMBER_1">%d</xliff:g>න් 1ක්</item> - <item quantity="other">මෙම යෙදුමෙන් දැනුම්දීම් ප්රවර්ග <xliff:g id="NUMBER_1">%d</xliff:g>න් 1ක්</item> + <item quantity="one">මෙම යෙදුමෙන් දැනුම්දීම් ප්රවර්ග <xliff:g id="NUMBER_1">%s</xliff:g>න් 1ක්</item> + <item quantity="other">මෙම යෙදුමෙන් දැනුම්දීම් ප්රවර්ග <xliff:g id="NUMBER_1">%s</xliff:g>න් 1ක්</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="other">මිනිත්තු %d</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"බැටරි භාවිතය"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"ආරෝපණය අතරතුර බැටරි සුරැකුම ලබා ගත නොහැකිය."</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"බැටරි සුරැකුම"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"ආරෝපණය අතරතුර බැටරි සුරැකුම ලබා ගත නොහැකිය"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"බැටරිය සුරකින්නා"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"ක්රියාකාරිත්වය සහ පසුබිම් දත්ත අඩු කරන්න"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g> බොත්තම"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home යතුර"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"කුඩා කරන්න"</string> <string name="pip_phone_close" msgid="8416647892889710330">"වසන්න"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ඉවත ලෑමට පහළට ඇදගෙන යන්න"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"පින්තූරය තුළ පින්තූරය මෙනුව"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"මෙනුව"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> පින්තූරය-තුළ-පින්තූරය තුළ වේ"</string> <string name="pip_notification_message" msgid="5619512781514343311">"ඔබට <xliff:g id="NAME">%s</xliff:g> මෙම විශේෂාංගය භාවිත කිරීමට අවශ්ය නැති නම්, සැකසීම් විවෘත කිරීමට තට්ටු කර එය ක්රියාවිරහිත කරන්න."</string> <string name="pip_play" msgid="1417176722760265888">"ධාවනය කරන්න"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"මෙනුව"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> යෙදුම"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"ඇඟවීම්"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"බැටරිය"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"තිර රු"</string> <string name="notification_channel_general" msgid="4525309436693914482">"පොදු පණිවිඩ"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"ගබඩාව"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"පසුබිමින් ධාවනය වන යෙදුම්"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"බැටරි හා දත්ත භාවිතය පිළිබඳව විස්තර සඳහා තට්ටු කරන්න"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"ජංගම දත්ත ක්රියාවිරහිත කරන්නද?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"යෙදුමක් අවසර ඉල්ලීමක් කරන නිසා, සැකසීම්වලට ඔබගේ ප්රතිචාරය සත්යාපනය කළ නොහැකිය."</string> </resources> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 724f3ef40ccb..3e69ce1e461f 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -66,8 +66,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Digitálny odtlačok RSA počítača je:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Vždy povoliť z tohto počítača"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Ladenie cez USB nie je povolené"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Používateľ, ktorý je práve prihlásený v tomto zariadení, nemôže zapnúť ladenie USB. Ak chcete použiť túto funkciu, prepnite na hlavného používateľa."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Priblížiť na celú obrazovku"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Na celú obrazovku"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Prebieha ukladanie snímky obrazovky..."</string> @@ -463,8 +462,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Ďalšie informácie"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Ste pripojený/-á k aplikácii <xliff:g id="VPN_APP">%1$s</xliff:g>, ktorá môže sledovať vašu aktivitu v sieti vrátane e-mailových správ, aplikácií a webových stránok."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Otvoriť nastavenia pripojenia VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Otvoriť dôveryhodné poverenia"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Správca aktivoval zapisovanie do denníka siete, ktoré sleduje premávku na vašom zariadení.\n\nĎalšie informácie vám poskytne správca."</string> @@ -564,10 +562,10 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Táto aplikácia nemá kategórie upozornení"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Upozornenia z tejto aplikácie sa nedajú vypnúť"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="few">1 z <xliff:g id="NUMBER_1">%d</xliff:g> kategórií upozornení z tejto aplikácie</item> - <item quantity="many">1 z <xliff:g id="NUMBER_1">%d</xliff:g> kategórie upozornení z tejto aplikácie</item> - <item quantity="other">1 z <xliff:g id="NUMBER_1">%d</xliff:g> kategórií upozornení z tejto aplikácie</item> - <item quantity="one">1 z <xliff:g id="NUMBER_0">%d</xliff:g> kategórie upozornení z tejto aplikácie</item> + <item quantity="few">1 z <xliff:g id="NUMBER_1">%s</xliff:g> kategórií upozornení z tejto aplikácie</item> + <item quantity="many">1 z <xliff:g id="NUMBER_1">%s</xliff:g> kategórie upozornení z tejto aplikácie</item> + <item quantity="other">1 z <xliff:g id="NUMBER_1">%s</xliff:g> kategórií upozornení z tejto aplikácie</item> + <item quantity="one">1 z <xliff:g id="NUMBER_0">%s</xliff:g> kategórie upozornení z tejto aplikácie</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -601,8 +599,8 @@ <item quantity="one">%d minúta</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Využitie batérie"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Počas nabíjania nie je Šetrič batérie k dispozícii"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Šetrič batérie"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Počas nabíjania nie je Šetrič batérie k dispozícii"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Šetrič batérie"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Obmedzí výkonnosť a údaje na pozadí"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Tlačidlo <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Domov"</string> @@ -742,7 +740,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalizovať"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Zavrieť"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Zrušíte presunutím nadol"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Ponuka režimu obraz v obraze"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Ponuka"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> je v režime obraz v obraze"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Ak nechcete, aby aplikácia <xliff:g id="NAME">%s</xliff:g> používala túto funkciu, klepnutím otvorte nastavenia a vypnite ju."</string> <string name="pip_play" msgid="1417176722760265888">"Prehrať"</string> @@ -770,8 +768,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Ponuka"</string> <string name="tuner_app" msgid="3507057938640108777">"Aplikácia <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozornenia"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Batéria"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Snímky obrazovky"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Všeobecné správy"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Úložisko"</string> @@ -792,4 +789,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Aplikácie sú spustené na pozadí"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Klepnutím zobrazíte podrobnosti o batérii a spotrebe dát"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Vypnúť mobilné dáta?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Nastavenia nemôžu overiť vašu odpoveď, pretože určitá aplikácia blokuje žiadosť o povolenie."</string> </resources> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 17c2997aa4a6..a50d301b79cd 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -66,8 +66,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Računalnikov prstni odtis ključa RSA je:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Vedno dovoli iz tega računalnika"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Odpravljanje napak s povezavo USB ni dovoljeno"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Uporabnik, trenutno prijavljen v napravo, ne more vklopiti odpravljanja napak s povezavo USB. Če želite uporabljati to funkcijo, preklopite na primarnega uporabnika."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Povečava čez cel zaslon"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Raztegnitev čez zaslon"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Shranjev. posnetka zaslona ..."</string> @@ -463,8 +462,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Več o tem"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Povezani ste z aplikacijo <xliff:g id="VPN_APP">%1$s</xliff:g>, ki lahko nadzira omrežno dejavnost, vključno z e-pošto, aplikacijami in spletnimi mesti."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Odpri nastavitve omrežja VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Odpri zaupanja vredne poverilnice"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Skrbnik je vklopil beleženje omrežnega prometa, ki nadzoruje promet v napravi.\n\nČe želite več informacij, se obrnite na skrbnika."</string> @@ -564,10 +562,10 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Ta aplikacija nima kategorij obvestil"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Obvestil te aplikacije ni mogoče izklopiti"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorije obvestil iz te aplikacije</item> - <item quantity="two">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorij obvestil iz te aplikacije</item> - <item quantity="few">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorij obvestil iz te aplikacije</item> - <item quantity="other">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorij obvestil iz te aplikacije</item> + <item quantity="one">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorije obvestil iz te aplikacije</item> + <item quantity="two">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorij obvestil iz te aplikacije</item> + <item quantity="few">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorij obvestil iz te aplikacije</item> + <item quantity="other">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorij obvestil iz te aplikacije</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -601,8 +599,8 @@ <item quantity="other">%d minut</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Poraba akumulatorja"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Varčevanje z energijo akumulatorja med polnjenjem ni na voljo"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Varčevanje z energijo akumulatorja"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Varčevanje z energijo akumulatorja med polnjenjem ni na voljo"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Varčevanje z energijo akumulatorja"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Omeji zmogljivost delovanja in prenos podatkov v ozadju"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Gumb <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Začetek"</string> @@ -742,7 +740,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimiraj"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Zapri"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Povlecite navzdol, da opustite"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Meni za sliko v sliki"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Meni"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> je v načinu slika v sliki"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Če ne želite, da aplikacija <xliff:g id="NAME">%s</xliff:g> uporablja to funkcijo, se dotaknite, da odprete nastavitve, in funkcijo izklopite."</string> <string name="pip_play" msgid="1417176722760265888">"Predvajaj"</string> @@ -770,8 +768,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Meni"</string> <string name="tuner_app" msgid="3507057938640108777">"Aplikacija <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Opozorila"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Akumulator"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Posnetki zaslona"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Splošna sporočila"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Shramba"</string> @@ -792,4 +789,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Aplikacije, ki se izvajajo v ozadju"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Dotaknite se za prikaz podrobnosti porabe akumulatorja in prenosa podatkov"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Želite izklopiti prenos podatkov v mobilnih omrežjih?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Ker aplikacija zakriva zahtevo za dovoljenje, z nastavitvami ni mogoče preveriti vašega odziva."</string> </resources> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index 3f0bb964e0ed..e1f25672ed09 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Shenja e gishtit të tastit \"RSA\" së kompjuterit është:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Lejo gjithmonë nga ky kompjuter"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Korrigjimi i USB-së nuk lejohet"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Përdoruesi i identifikuar aktualisht në këtë pajisje nuk mund ta aktivizojë korrigjimin e USB-së. Për ta përdorur këtë funksion, kalo te përdoruesi parësor."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zmadho për të mbushur ekranin"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Shtrije për të mbushur ekranin"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Po ruan pamjen e ekranit..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Mëso më shumë"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Je i lidhur me aplikacionin <xliff:g id="VPN_APP">%1$s</xliff:g>, i cili mund të monitorojë aktivitetin tënd në rrjet, duke përfshirë mail-et, aplikacionet dhe sajtet e uebit."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Hap cilësimet e VPN-së"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Hap kredencialet e besuara"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administratori yt ka aktivizuar regjistrimin e rrjetit, i cili monitoron trafikun në pajisjen tënde.\n\nPër më shumë informacione, kontakto me administratorin."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Ky aplikacion nuk ka kategori njoftimesh"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Njoftimet nga ky aplikacion nuk mund të çaktivizohen"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 nga <xliff:g id="NUMBER_1">%d</xliff:g> kategori njoftimi nga ky aplikacion</item> - <item quantity="one">1 nga <xliff:g id="NUMBER_0">%d</xliff:g> kategori njoftimi nga ky aplikacion</item> + <item quantity="other">1 nga <xliff:g id="NUMBER_1">%s</xliff:g> kategori njoftimi nga ky aplikacion</item> + <item quantity="one">1 nga <xliff:g id="NUMBER_0">%s</xliff:g> kategori njoftimi nga ky aplikacion</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d minutë</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Përdorimi i baterisë"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"\"Kursyesi i baterisë\" nuk është i disponueshëm gjatë karikimit"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Kursyesi i baterisë"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"\"Kursyesi i baterisë\" nuk është i disponueshëm gjatë ngarkimit"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Kursyesi i baterisë"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Pakëson veprimtarinë dhe të dhënat në sfond"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Butoni <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Kreu"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizo"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Mbyll"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Zvarrit poshtë për të larguar"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Menyja e \"Figurës brenda figurës\""</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menyja"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> është në figurë brenda figurës"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Nëse nuk dëshiron që <xliff:g id="NAME">%s</xliff:g> ta përdorë këtë funksion, trokit për të hapur cilësimet dhe për ta çaktivizuar."</string> <string name="pip_play" msgid="1417176722760265888">"Luaj"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menyja"</string> <string name="tuner_app" msgid="3507057938640108777">"Aplikacioni <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Sinjalizimet"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Bateria"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Pamjet e ekranit"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Mesazhe të përgjithshme"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Hapësira ruajtëse"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Aplikacionet që ekzekutohen në sfond"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Trokit për detaje mbi baterinë dhe përdorimin e të dhënave"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Të çaktivizohen të dhënat celulare?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Duke qenë se një aplikacion po bllokon një kërkesë për leje, \"Cilësimet\" nuk mund të verifikojnë përgjigjen tënde."</string> </resources> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 16caf06b0e77..b31eb962883c 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -65,8 +65,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Дигитални отисак RSA кључа овог рачунара је:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Увек дозволи са овог рачунара"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Отклањање грешака на USB-у није дозвољено"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Корисник који је тренутно пријављен на овај уређај не може да укључи отклањање грешака на USB-у. Да бисте користили ову функцију, пребаците на примарног корисника."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Зумирај на целом екрану"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Развуци на цео екран"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Чување снимка екрана..."</string> @@ -459,8 +458,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Сазнајте више"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Повезани сте са апликацијом <xliff:g id="VPN_APP">%1$s</xliff:g>, која може да надгледа активности на мрежи, укључујући имејлове, апликације и веб-сајтове."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Отвори подешавања VPN-а"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Отворите поуздане акредитиве"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Администратор је укључио евидентирање мреже, које прати саобраћај на уређају.\n\nКонтактирајте администратора за више информација."</string> @@ -560,9 +558,9 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Ова апликација нема категорије обавештења"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Обавештења из ове апликације не могу да се искључе"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 од <xliff:g id="NUMBER_1">%d</xliff:g> категорије обавештења за ову апликацију</item> - <item quantity="few">1 од <xliff:g id="NUMBER_1">%d</xliff:g> категорије обавештења за ову апликацију</item> - <item quantity="other">1 од <xliff:g id="NUMBER_1">%d</xliff:g> категорија обавештења за ову апликацију</item> + <item quantity="one">1 од <xliff:g id="NUMBER_1">%s</xliff:g> категорије обавештења за ову апликацију</item> + <item quantity="few">1 од <xliff:g id="NUMBER_1">%s</xliff:g> категорије обавештења за ову апликацију</item> + <item quantity="other">1 од <xliff:g id="NUMBER_1">%s</xliff:g> категорија обавештења за ову апликацију</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -593,8 +591,8 @@ <item quantity="other">%d минута</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Потрошња батерије"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Уштеда батерије није доступна током пуњења"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Уштеда батерије"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Уштеда батерије није доступна током пуњења"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Уштеда батерије"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Смањује перформансе и позадинске податке"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Дугме <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Тастер Почетна"</string> @@ -734,7 +732,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Умањи"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Затвори"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Превуците надоле да бисте одбили"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Мени Слика у слици"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Мени"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> је слика у слици"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Ако не желите да <xliff:g id="NAME">%s</xliff:g> користи ову функцију, додирните да бисте отворили подешавања и искључили је."</string> <string name="pip_play" msgid="1417176722760265888">"Пусти"</string> @@ -762,8 +760,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Мени"</string> <string name="tuner_app" msgid="3507057938640108777">"Апликација <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Обавештења"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Батерија"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Снимци екрана"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Опште поруке"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Меморијски простор"</string> @@ -784,4 +781,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Апликације покренуте у позадини"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Додирните за детаље о батерији и потрошњи података"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Желите да онемогућите мобилне податке?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Подешавања не могу да верификују ваш одговор јер апликација скрива захтев за дозволу."</string> </resources> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index eaf713b90487..74c6aafe6e02 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Fingeravtrycket för datorns RSA-nyckel är:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Tillåt alltid på den här datorn"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB-felsökning är inte tillåtet"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Användaren som är inloggad på enheten för närvarande kan inte aktivera USB-felsökning. Byt till den primära användaren om du vill använda den här funktionen."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Zooma för att fylla skärm"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Dra för att fylla skärmen"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Skärmdumpen sparas ..."</string> @@ -314,7 +313,7 @@ <string name="quick_settings_connected_battery_level" msgid="4136051440381328892">"Ansluten, batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> <string name="quick_settings_connecting" msgid="47623027419264404">"Ansluter ..."</string> <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Internetdelning"</string> - <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Trådlös surfzon"</string> + <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Surfzon"</string> <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Aviseringar"</string> <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Ficklampa"</string> <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"Mobildata"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Läs mer"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Du är ansluten till <xliff:g id="VPN_APP">%1$s</xliff:g> som kan övervaka din aktivitet på nätverket, inklusive e-postmeddelanden, appar och webbplatser."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Öppna VPN-inställningarna"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Öppna betrodda användaruppgifter"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administratören har aktiverat nätverksloggning som övervakar trafik på enheten.\n\nKontakta administratören om du vill veta mer."</string> @@ -526,7 +524,7 @@ <string name="alarm_template" msgid="3980063409350522735">"kl. <xliff:g id="WHEN">%1$s</xliff:g>"</string> <string name="alarm_template_far" msgid="4242179982586714810">"kl. <xliff:g id="WHEN">%1$s</xliff:g>"</string> <string name="accessibility_quick_settings_detail" msgid="2579369091672902101">"Snabbinställningar, <xliff:g id="TITLE">%s</xliff:g>."</string> - <string name="accessibility_status_bar_hotspot" msgid="4099381329956402865">"Trådlös surfzon"</string> + <string name="accessibility_status_bar_hotspot" msgid="4099381329956402865">"Surfzon"</string> <string name="accessibility_managed_profile" msgid="6613641363112584120">"Jobbprofil"</string> <string name="tuner_warning_title" msgid="7094689930793031682">"Kul för vissa, inte för alla"</string> <string name="tuner_warning" msgid="8730648121973575701">"Du kan använda inställningarna för systemgränssnitt för att justera användargränssnittet i Android. Dessa experimentfunktioner kan när som helst ändras, sluta fungera eller försvinna. Använd med försiktighet."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Det finns inga aviseringskategorier i appen"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Det går inte att inaktivera aviseringar från den här appen"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 av <xliff:g id="NUMBER_1">%d</xliff:g> aviseringskategorier från denna app</item> - <item quantity="one">1 av <xliff:g id="NUMBER_0">%d</xliff:g> aviseringskategorier från denna app</item> + <item quantity="other">1 av <xliff:g id="NUMBER_1">%s</xliff:g> aviseringskategorier från denna app</item> + <item quantity="one">1 av <xliff:g id="NUMBER_0">%s</xliff:g> aviseringskategorier från denna app</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d minut</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Batteriförbrukning"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Batterisparläget är inte tillgängligt vid laddning"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Batterisparläge"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Batterisparläget är inte tillgängligt vid laddning"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Batterisparläge"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Minskar prestanda och bakgrundsdata"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Knappen <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Start"</string> @@ -727,8 +725,8 @@ <string name="pip_phone_expand" msgid="5889780005575693909">"Utöka"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimera"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Stäng"</string> - <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Tryck och dra nedåt för att ignorera"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Bild-i-bild-meny"</string> + <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Tryck och dra nedåt för att avvisa"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Meny"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> visas i bild-i-bild"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Om du inte vill att den här funktionen används i <xliff:g id="NAME">%s</xliff:g> öppnar du inställningarna genom att trycka. Sedan inaktiverar du funktionen."</string> <string name="pip_play" msgid="1417176722760265888">"Spela upp"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Meny"</string> <string name="tuner_app" msgid="3507057938640108777">"Appen <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Varningar"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Batteri"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Skärmdumpar"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Allmänna meddelanden"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Lagring"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Appar körs i bakgrunden"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Tryck för information om batteri- och dataanvändning"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Vill du inaktivera mobildatan?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Svaret kan inte verifieras av Inställningar eftersom en app skymmer en begäran om behörighet."</string> </resources> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index a500f4d461f1..f64089639df0 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Alama ya kidole ya kitufe cha RSA ya kompyuta ni:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Ruhusu kutoka kwenye kompyuta hii kila wakati"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Utatuzi wa USB hauruhusiwi"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Mtumiaji aliyeingia katika akaunti kwa kutumia kifaa hiki kwa sasa hawezi kuwasha utatuzi wa USB. Ili utumie kipengele hiki, tumia akaunti ya mtumiaji wa msingi."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Kuza ili kujaza skrini"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Tanua ili kujaza skrini"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Inahifadhi picha ya skrini..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Pata maelezo zaidi"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Umeunganishwa kwenye <xliff:g id="VPN_APP">%1$s</xliff:g>, ambayo inaweza kufuatilia shughuli za mtandao wako, ikiwa ni pamoja na barua pepe, programu na tovuti."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Fungua mipangilio ya VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Fungua vitambulisho vinavyoaminika"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Msimamizi wako amewasha kumbukumbu ya kuingia mtandaoni ambayo hufuatilia shughuli kwenye kifaa chako.\n\nKwa maelezo zaidi, wasiliana na msimamizi wako."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Programu hii haina aina za arifa"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Arifa kutoka kwenye programu hii haziwezi kuzimwa"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">Aina 1 ya arifa kati ya <xliff:g id="NUMBER_1">%d</xliff:g> kutoka kwenye kifaa hiki</item> - <item quantity="one">Aina 1 ya arifa kati ya <xliff:g id="NUMBER_0">%d</xliff:g> kutoka kwenye kifaa hiki</item> + <item quantity="other">Aina 1 ya arifa kati ya <xliff:g id="NUMBER_1">%s</xliff:g> kutoka kwenye kifaa hiki</item> + <item quantity="one">Aina 1 ya arifa kati ya <xliff:g id="NUMBER_0">%s</xliff:g> kutoka kwenye kifaa hiki</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">Dakika %d</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Matumizi ya betri"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Kiokoa Betri hakipatikani unapochaji betri"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Kiokoa Betri"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Kiokoa betri hakipatikani unapochaji betri"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Kiokoa betri"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Hupunguza data ya chini chini na utendaji"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Kitufe cha <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Mwanzo"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Punguza"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Funga"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Buruta ili uondoe"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Menyu ya picha ndani ya picha"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menyu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> iko katika hali ya picha ndani ya picha nyingine"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Ikiwa hutaki <xliff:g id="NAME">%s</xliff:g> itumie kipengele hiki, gonga ili ufungue mipangilio na uizime."</string> <string name="pip_play" msgid="1417176722760265888">"Cheza"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menyu"</string> <string name="tuner_app" msgid="3507057938640108777">"Programu ya <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Arifa"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Betri"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Picha za skrini"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Ujumbe wa Jumla"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Hifadhi"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Programu zinatumika chinichini"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Gonga ili upate maelezo kuhusu betri na matumizi ya data"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Ungependa kuzima data ya mtandao wa simu?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Kwa sababu programu nyingine inazuia ombi la ruhusa, hatuwezi kuthibitisha jibu lako katika Mipangilio."</string> </resources> diff --git a/packages/SystemUI/res/values-car/dimens.xml b/packages/SystemUI/res/values-sw372dp/dimens.xml index b2e7bd1b881e..635185d7f2ad 100644 --- a/packages/SystemUI/res/values-car/dimens.xml +++ b/packages/SystemUI/res/values-sw372dp/dimens.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - * Copyright (c) 2017, The Android Open Source Project + * Copyright (c) 2006, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ */ --> <resources> - <!-- The height of the quick settings footer that holds the user switcher, settings icon, - etc. in the car setting.--> - <dimen name="qs_footer_height">74dp</dimen> + <dimen name="nav_content_padding">8dp</dimen> + <dimen name="rounded_corner_content_padding">8dp</dimen> </resources> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index 72c6bb031fbd..2d4b6d01c968 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"பின்வருவது கணினியின் RSA விசை கைரேகையாகும்:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"இந்தக் கணினியிலிருந்து எப்போதும் அனுமதி"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB பிழைத்திருத்தம் அனுமதிக்கப்படவில்லை"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"தற்போது இந்தச் சாதனத்தில் உள்நுழைந்துள்ள பயனரால் USB பிழைத்திருத்தத்தை இயக்க முடியாது. இந்த அம்சத்தை இயக்க, முதன்மைப் பயனருக்கு மாறவும்."</string> <string name="compat_mode_on" msgid="6623839244840638213">"திரையை நிரப்ப அளவை மாற்று"</string> <string name="compat_mode_off" msgid="4434467572461327898">"திரையை நிரப்ப இழு"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"ஸ்க்ரீன் ஷாட்டைச் சேமிக்கிறது…"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"மேலும் அறிக"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"<xliff:g id="VPN_APP">%1$s</xliff:g> உடன் இணைக்கப்பட்டுள்ளீர்கள். இந்தப் பயன்பாட்டால் மின்னஞ்சல்கள், பயன்பாடுகள், இணையதளங்கள் உட்பட உங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்க முடியும்."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN அமைப்புகளைத் திற"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"நம்பகமான அனுமதிச் சான்றுகளைத் திற"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"உங்கள் நிர்வாகி நெட்வொர்க் பதிவெடுத்தலை இயக்கியுள்ளார், இது சாதனத்தில் ட்ராஃபிக்கைக் கண்காணிக்கும்.\n\nமேலும் தகவலுக்கு, உங்கள் நிர்வாகியைத் தொடர்புகொள்ளவும்."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"இந்தப் பயன்பாட்டில் அறிவிப்பு வகைகள் இல்லை"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"இந்தப் பயன்பாட்டிலிருந்து அறிவிப்புகளைப் பெறுவதை முடக்க முடியாது"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">இந்தப் பயன்பாடு வழங்கும் <xliff:g id="NUMBER_1">%d</xliff:g> அறிவிப்பு வகைகளில் ஒரு அறிவிப்பு வகை</item> - <item quantity="one">இந்தப் பயன்பாடு வழங்கும் <xliff:g id="NUMBER_0">%d</xliff:g> அறிவிப்பு வகையில் ஒரு அறிவிப்பு வகை</item> + <item quantity="other">இந்தப் பயன்பாடு வழங்கும் <xliff:g id="NUMBER_1">%s</xliff:g> அறிவிப்பு வகைகளில் ஒரு அறிவிப்பு வகை</item> + <item quantity="one">இந்தப் பயன்பாடு வழங்கும் <xliff:g id="NUMBER_0">%s</xliff:g> அறிவிப்பு வகையில் ஒரு அறிவிப்பு வகை</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d நிமிடம்</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"பேட்டரி உபயோகம்"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"சார்ஜ் செய்யும் போது பேட்டரி சேமிப்பானைப் பயன்படுத்த முடியாது"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"பேட்டரி சேமிப்பான்"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"சார்ஜ் செய்யும் போது பேட்டரி சேமிப்பானைப் பயன்படுத்த முடியாது"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"பேட்டரி சேமிப்பான்"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"செயல்திறனையும் பின்புலத்தில் தரவு செயலாக்கப்படுவதையும் குறைக்கும்"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g> பொத்தான்"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"ஹோம்"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"சிறிதாக்கு"</string> <string name="pip_phone_close" msgid="8416647892889710330">"மூடு"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"நிராகரிக்க, கீழே இழுக்கவும்"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"பிக்ச்சர்-இன்-பிக்ச்சர் மெனு"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"மெனு"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> தற்போது பிக்ச்சர்-இன்-பிக்ச்சரில் உள்ளது"</string> <string name="pip_notification_message" msgid="5619512781514343311">"<xliff:g id="NAME">%s</xliff:g> இந்த அம்சத்தைப் பயன்படுத்த வேண்டாம் என நினைத்தால், அமைப்புகளைத் திறந்து அதை முடக்க, தட்டவும்."</string> <string name="pip_play" msgid="1417176722760265888">"இயக்கு"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"மெனு"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> பயன்பாடு"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"விழிப்பூட்டல்கள்"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"பேட்டரி"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"ஸ்கிரீன் ஷாட்டுகள்"</string> <string name="notification_channel_general" msgid="4525309436693914482">"பொதுச் செய்திகள்"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"சேமிப்பிடம்"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"பின்னணியில் இயங்கும் பயன்பாடுகள்"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"பேட்டரி மற்றும் தரவு உபயோக விவரங்களைக் காண, தட்டவும்"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"மொபைல் தரவை முடக்கவா?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"அனுமதிக் கோரிக்கையைப் பயன்பாடு மறைப்பதால், அமைப்புகளால் உங்கள் பதிலைச் சரிபார்க்க முடியாது."</string> </resources> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 7250e277fffd..ce00a96a2c27 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -22,7 +22,7 @@ <string name="app_label" msgid="7164937344850004466">"సిస్టమ్ UI"</string> <string name="status_bar_clear_all_button" msgid="7774721344716731603">"క్లియర్ చేయండి"</string> <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"జాబితా నుండి తీసివేయండి"</string> - <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"అనువర్తన సమాచారం"</string> + <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"యాప్ సమాచారం"</string> <string name="status_bar_no_recent_apps" msgid="7374907845131203189">"మీ ఇటీవలి స్క్రీన్లు ఇక్కడ కనిపిస్తాయి"</string> <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"ఇటీవలి అనువర్తనాలను తీసివేయండి"</string> <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759"> @@ -51,7 +51,7 @@ <string name="bluetooth_tethered" msgid="7094101612161133267">"బ్లూటూత్ టీథర్ చేయబడింది"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ఇన్పుట్ పద్ధతులను సెటప్ చేయండి"</string> <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"భౌతిక కీబోర్డ్"</string> - <string name="usb_device_permission_prompt" msgid="834698001271562057">"USB పరికరాన్ని ప్రాప్యత చేయడానికి అనువర్తనాన్ని <xliff:g id="APPLICATION">%1$s</xliff:g> అనుమతించాలా?"</string> + <string name="usb_device_permission_prompt" msgid="834698001271562057">"USB పరికరాన్ని యాక్సెస్ చేయడానికి యాప్ <xliff:g id="APPLICATION">%1$s</xliff:g> అనుమతించాలా?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"USB ఉపకరణాన్ని యాక్సెస్ చేయడానికి యాప్ <xliff:g id="APPLICATION">%1$s</xliff:g>ను అనుమతించాలా?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"ఈ USB పరికరం కనెక్ట్ చేయబడినప్పుడు <xliff:g id="ACTIVITY">%1$s</xliff:g>ని తెరవాలా?"</string> <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"ఈ USB ఉపకరణం కనెక్ట్ చేయబడినప్పుడు <xliff:g id="ACTIVITY">%1$s</xliff:g>ని తెరవాలా?"</string> @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"ఇది కంప్యూటర్ యొక్క RSA కీ వేలిముద్ర:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"ఈ కంప్యూటర్ నుండి ఎల్లప్పుడూ అనుమతించు"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB డీబగ్గింగ్కి అనుమతి లేదు"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ఈ పరికరానికి ప్రస్తుతం సైన్ ఇన్ చేసిన వినియోగదారు USB డీబగ్గింగ్ ఆన్ చేయలేరు. ఈ ఫీచర్ ఉపయోగించడానికి, ప్రాథమిక వినియోగదారుకి మారాలి."</string> <string name="compat_mode_on" msgid="6623839244840638213">"స్క్రీన్కు నింపేలా జూమ్ చేయండి"</string> <string name="compat_mode_off" msgid="4434467572461327898">"స్క్రీన్కు నింపేలా విస్తరించండి"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"స్క్రీన్షాట్ను సేవ్ చేస్తోంది…"</string> @@ -84,9 +83,9 @@ <string name="accessibility_back" msgid="567011538994429120">"వెనుకకు"</string> <string name="accessibility_home" msgid="8217216074895377641">"హోమ్"</string> <string name="accessibility_menu" msgid="316839303324695949">"మెను"</string> - <string name="accessibility_accessibility_button" msgid="7601252764577607915">"ప్రాప్యత"</string> + <string name="accessibility_accessibility_button" msgid="7601252764577607915">"యాక్సెస్ సామర్థ్యం"</string> <string name="accessibility_recent" msgid="5208608566793607626">"అవలోకనం"</string> - <string name="accessibility_search_light" msgid="1103867596330271848">"శోధించు"</string> + <string name="accessibility_search_light" msgid="1103867596330271848">"వెతుకు"</string> <string name="accessibility_camera_button" msgid="8064671582820358152">"కెమెరా"</string> <string name="accessibility_phone_button" msgid="6738112589538563574">"ఫోన్"</string> <string name="accessibility_voice_assist_button" msgid="487611083884852965">"వాయిస్ అసిస్టెంట్"</string> @@ -333,7 +332,7 @@ <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"మీరు అన్నింటినీ తీసివేసారు"</string> <string name="recents_app_info_button_label" msgid="2890317189376000030">"అనువర్తన సమాచారం"</string> <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"స్క్రీన్ పిన్నింగ్"</string> - <string name="recents_search_bar_label" msgid="8074997400187836677">"శోధించు"</string> + <string name="recents_search_bar_label" msgid="8074997400187836677">"వెతుకు"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ని ప్రారంభించడం సాధ్యపడలేదు."</string> <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> సురక్షిత-మోడ్లో నిలిపివేయబడింది."</string> <string name="recents_stack_action_button_label" msgid="6593727103310426253">"అన్నీ తీసివేయి"</string> @@ -440,8 +439,8 @@ <string name="disable_vpn" msgid="4435534311510272506">"VPNని నిలిపివేయి"</string> <string name="disconnect_vpn" msgid="1324915059568548655">"VPNను డిస్కనెక్ట్ చేయి"</string> <string name="monitoring_button_view_policies" msgid="100913612638514424">"విధానాలను వీక్షించండి"</string> - <string name="monitoring_description_named_management" msgid="5281789135578986303">"మీ పరికరం <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> నిర్వహణలో ఉంది.\n\nమీ నిర్వాహకులు మీ పరికరం అనుబంధిత సెట్టింగ్లు, కార్పొరేట్ ప్రాప్యత, అనువర్తనాలు, డేటా మరియు మీ పరికర స్థాన సమాచారం పర్యవేక్షించగలరు మరియు నిర్వహించగలరు.\n\nమరింత సమాచారం కోసం, మీ నిర్వాహకులను సంప్రదించండి."</string> - <string name="monitoring_description_management" msgid="4573721970278370790">"మీ పరికరం మీ సంస్థ నిర్వహణలో ఉంది.\n\nమీ నిర్వాహకులు మీ పరికరం అనుబంధిత సెట్టింగ్లు, కార్పొరేట్ ప్రాప్యత, అనువర్తనాలు, డేటాను మరియు మీ పరికర స్థాన సమాచారాన్ని పర్యవేక్షించగలరు మరియు నిర్వహించగలరు.\n\nమరింత సమాచారం కోసం, మీ నిర్వాహకులను సంప్రదించండి."</string> + <string name="monitoring_description_named_management" msgid="5281789135578986303">"మీ పరికరం <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> నిర్వహణలో ఉంది.\n\nమీ నిర్వాహకులు మీ పరికరం అనుబంధిత సెట్టింగ్లు, కార్పొరేట్ యాక్సెస్, యాప్లు, డేటా మరియు మీ పరికర స్థాన సమాచారం పర్యవేక్షించగలరు మరియు నిర్వహించగలరు.\n\nమరింత సమాచారం కోసం, మీ నిర్వాహకులను సంప్రదించండి."</string> + <string name="monitoring_description_management" msgid="4573721970278370790">"మీ పరికరం మీ సంస్థ నిర్వహణలో ఉంది.\n\nమీ నిర్వాహకులు మీ పరికరం అనుబంధిత సెట్టింగ్లు, కార్పొరేట్ యాక్సెస్, యాప్లు, డేటాను మరియు మీ పరికర స్థాన సమాచారాన్ని పర్యవేక్షించగలరు మరియు నిర్వహించగలరు.\n\nమరింత సమాచారం కోసం, మీ నిర్వాహకులను సంప్రదించండి."</string> <string name="monitoring_description_management_ca_certificate" msgid="5202023784131001751">"ఈ పరికరంలో మీ సంస్థ ఒక ప్రమాణపత్ర అధికారాన్ని ఇన్స్టాల్ చేసింది. మీ సురక్షిత నెట్వర్క్ ట్రాఫిక్ పర్యవేక్షించబడవచ్చు లేదా సవరించబడవచ్చు."</string> <string name="monitoring_description_managed_profile_ca_certificate" msgid="4683248196789897964">"మీ కార్యాలయ ప్రొఫైల్లో మీ సంస్థ ఒక ప్రమాణపత్ర అధికారాన్ని ఇన్స్టాల్ చేసింది. మీ సురక్షిత నెట్వర్క్ ట్రాఫిక్ పర్యవేక్షించబడవచ్చు లేదా సవరించబడవచ్చు."</string> <string name="monitoring_description_ca_certificate" msgid="7886985418413598352">"ఈ పరికరంలో ప్రమాణపత్ర అధికారం ఇన్స్టాల్ చేయబడింది. మీ సురక్షిత నెట్వర్క్ ట్రాఫిక్ పర్యవేక్షించబడవచ్చు లేదా సవరించబడవచ్చు."</string> @@ -452,13 +451,12 @@ <string name="monitoring_description_personal_profile_named_vpn" msgid="3133980926929069283">"మీ వ్యక్తిగత ప్రొఫైల్ ఇమెయిల్లు, అనువర్తనాలు మరియు వెబ్సైట్లతో సహా మీ నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడింది."</string> <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"మీ పరికరం <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g> ద్వారా నిర్వహించబడుతోంది."</string> <string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> మీ పరికరాన్ని నిర్వహించడానికి <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g>ని ఉపయోగిస్తుంది."</string> - <string name="monitoring_description_do_body" msgid="3639594537660975895">"మీ పరికరంతో అనుబంధించబడిన సెట్టింగ్లు, కార్పొరేట్ ప్రాప్యత, అనువర్తనాలు, డేటా మరియు మీ పరికరం యొక్క స్థాన సమాచారాన్ని మీ నిర్వాహకులు పర్యవేక్షించగలరు మరియు నిర్వహించగలరు."</string> + <string name="monitoring_description_do_body" msgid="3639594537660975895">"మీ పరికరంతో అనుబంధించబడిన సెట్టింగ్లు, కార్పొరేట్ యాక్సెస్, యాప్లు, డేటా మరియు మీ పరికరం యొక్క స్థాన సమాచారాన్ని మీ నిర్వాహకులు పర్యవేక్షించగలరు మరియు నిర్వహించగలరు."</string> <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string> <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"మరింత తెలుసుకోండి"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"మీరు <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఇమెయిల్లు, అనువర్తనాలు మరియు వెబ్సైట్లతో సహా మీ వ్యక్తిగత నెట్వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN సెట్టింగ్లను తెరవండి"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"విశ్వసనీయ ఆధారాలను తెరువు"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"మీ నిర్వాహకులు మీ పరికరంలోని ట్రాఫిక్ని పర్యవేక్షించగల నెట్వర్క్ లాగింగ్ని ఆన్ చేసారు.\n\nమరింత సమాచారం కావాలంటే, మీ నిర్వాహకులను సంప్రదించండి."</string> @@ -498,10 +496,10 @@ <string name="stream_notification" msgid="2563720670905665031">"నోటిఫికేషన్"</string> <string name="stream_bluetooth_sco" msgid="2055645746402746292">"బ్లూటూత్"</string> <string name="stream_dtmf" msgid="2447177903892477915">"డ్యూయల్ మల్టీ టోన్ ఫ్రీక్వెన్సీ"</string> - <string name="stream_accessibility" msgid="301136219144385106">"ప్రాప్యత"</string> + <string name="stream_accessibility" msgid="301136219144385106">"యాక్సెస్ సామర్థ్యం"</string> <string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. అన్మ్యూట్ చేయడానికి నొక్కండి."</string> - <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. వైబ్రేషన్కు సెట్ చేయడానికి నొక్కండి. ప్రాప్యత సేవలు మ్యూట్ చేయబడవచ్చు."</string> - <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. మ్యూట్ చేయడానికి నొక్కండి. ప్రాప్యత సేవలు మ్యూట్ చేయబడవచ్చు."</string> + <string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. వైబ్రేషన్కు సెట్ చేయడానికి నొక్కండి. యాక్సెస్ సామర్థ్య సేవలు మ్యూట్ చేయబడవచ్చు."</string> + <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. మ్యూట్ చేయడానికి నొక్కండి. యాక్సెస్ సామర్థ్య సేవలు మ్యూట్ చేయబడవచ్చు."</string> <string name="volume_stream_content_description_vibrate_a11y" msgid="6427727603978431301">"%1$s. వైబ్రేట్ అయ్యేలా సెట్ చేయడం కోసం నొక్కండి."</string> <string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. మ్యూట్ చేయడానికి నొక్కండి."</string> <string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s వాల్యూమ్ నియంత్రణలు చూపబడ్డాయి. తీసివేయడానికి పైకి స్వైప్ చేయండి."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"ఈ అనువర్తనానికి నోటిఫికేషన్ వర్గాలు లేవు"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"ఈ యాప్ నుండి వచ్చే నోటిఫికేషన్లను ఆఫ్ చేయలేరు"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">ఈ యాప్ నుంచి <xliff:g id="NUMBER_1">%d</xliff:g> నోటిఫికేషన్ వర్గాలలో 1</item> - <item quantity="one">ఈ యాప్ నుంచి <xliff:g id="NUMBER_0">%d</xliff:g> నోటిఫికేషన్ వర్గంలో 1</item> + <item quantity="other">ఈ యాప్ నుంచి <xliff:g id="NUMBER_1">%s</xliff:g> నోటిఫికేషన్ వర్గాలలో 1</item> + <item quantity="one">ఈ యాప్ నుంచి <xliff:g id="NUMBER_0">%s</xliff:g> నోటిఫికేషన్ వర్గంలో 1</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d నిమిషం</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"బ్యాటరీ వినియోగం"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"ఛార్జ్ అవుతున్న సమయంలో బ్యాటరీ సేవర్ అందుబాటులో ఉండదు"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"బ్యాటరీ సేవర్"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"ఛార్జ్ అవుతున్న సమయంలో బ్యాటరీ సేవర్ అందుబాటులో లేదు"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"బ్యాటరీ సేవర్"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"పనితీరుని మరియు నేపథ్య డేటాను తగ్గిస్తుంది"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"బటన్ <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -634,7 +632,7 @@ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"క్యాలెండర్"</string> <string name="tuner_full_zen_title" msgid="4540823317772234308">"వాల్యూమ్ నియంత్రణలతో చూపు"</string> <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"అంతరాయం కలిగించవద్దు"</string> - <string name="volume_dnd_silent" msgid="4363882330723050727">"వాల్యూమ్ బటన్ల సత్వరమార్గం"</string> + <string name="volume_dnd_silent" msgid="4363882330723050727">"వాల్యూమ్ బటన్ల షార్ట్కట్"</string> <string name="volume_up_silent" msgid="7141255269783588286">"వాల్యూమ్ పెంచితే అంతరాయం కలిగించవద్దు నుండి నిష్క్రమిస్తుంది"</string> <string name="battery" msgid="7498329822413202973">"బ్యాటరీ"</string> <string name="clock" msgid="7416090374234785905">"గడియారం"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"కనిష్టీకరించు"</string> <string name="pip_phone_close" msgid="8416647892889710330">"మూసివేయి"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"తీసివేయడానికి కిందికి లాగండి"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"చిత్రంలో చిత్రం మెను"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"మెను"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> చిత్రంలో చిత్రం రూపంలో ఉంది"</string> <string name="pip_notification_message" msgid="5619512781514343311">"<xliff:g id="NAME">%s</xliff:g> ఈ లక్షణాన్ని ఉపయోగించకూడదు అని మీరు అనుకుంటే, సెట్టింగ్లను తెరవడానికి నొక్కి, దీన్ని ఆఫ్ చేయండి."</string> <string name="pip_play" msgid="1417176722760265888">"ప్లే చేయి"</string> @@ -741,10 +739,10 @@ <string name="high_temp_title" msgid="4589508026407318374">"ఫోన్ వేడెక్కుతోంది"</string> <string name="high_temp_notif_message" msgid="5642466103153429279">"ఫోన్ను చల్లబరిచే క్రమంలో కొన్ని లక్షణాలు పరిమితం చేయబడ్డాయి"</string> <string name="high_temp_dialog_message" msgid="6840700639374113553">"మీ ఫోన్ స్వయంచాలకంగా చల్లబడటానికి ప్రయత్నిస్తుంది. మీరు ఇప్పటికీ మీ ఫోన్ను ఉపయోగించవచ్చు, కానీ దాని పనితీరు నెమ్మదిగా ఉండవచ్చు.\n\nమీ ఫోన్ చల్లబడిన తర్వాత, అది సాధారణ రీతిలో పని చేస్తుంది."</string> - <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"ఎడమవైపు సత్వరమార్గం"</string> - <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"కుడివైపు సత్వరమార్గం"</string> - <string name="lockscreen_unlock_left" msgid="2043092136246951985">"ఎడమవైపు సత్వరమార్గం కూడా అన్లాక్ చేస్తుంది"</string> - <string name="lockscreen_unlock_right" msgid="1529992940510318775">"కుడివైపు సత్వరమార్గం కూడా అన్లాక్ చేస్తుంది"</string> + <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"ఎడమవైపు షార్ట్కట్"</string> + <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"కుడివైపు షార్ట్కట్"</string> + <string name="lockscreen_unlock_left" msgid="2043092136246951985">"ఎడమవైపు షార్ట్కట్ కూడా అన్లాక్ చేస్తుంది"</string> + <string name="lockscreen_unlock_right" msgid="1529992940510318775">"కుడివైపు షార్ట్కట్ కూడా అన్లాక్ చేస్తుంది"</string> <string name="lockscreen_none" msgid="4783896034844841821">"ఏదీ వద్దు"</string> <string name="tuner_launch_app" msgid="1527264114781925348">"<xliff:g id="APP">%1$s</xliff:g>ని ప్రారంభించండి"</string> <string name="tuner_other_apps" msgid="4726596850501162493">"ఇతర అనువర్తనాలు"</string> @@ -756,14 +754,13 @@ <string name="tuner_menu" msgid="191640047241552081">"మెను"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> అనురవర్తనం"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"హెచ్చరికలు"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"బ్యాటరీ"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"స్క్రీన్షాట్లు"</string> <string name="notification_channel_general" msgid="4525309436693914482">"సాధారణ సందేశాలు"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"నిల్వ"</string> <string name="instant_apps" msgid="6647570248119804907">"తక్షణ అనువర్తనాలు"</string> <string name="instant_apps_message" msgid="8116608994995104836">"తక్షణ అనువర్తనాలకు ఇన్స్టాలేషన్ అవసరం లేదు."</string> - <string name="app_info" msgid="6856026610594615344">"అనువర్తన సమాచారం"</string> + <string name="app_info" msgid="6856026610594615344">"యాప్ సమాచారం"</string> <string name="go_to_web" msgid="1106022723459948514">"వెబ్కు వెళ్లు"</string> <string name="mobile_data" msgid="7094582042819250762">"మొబైల్ డేటా"</string> <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ఆఫ్లో ఉంది"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"నేపథ్యంలో అమలు అవుతున్న ఆప్లు"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"బ్యాటరీ మరియు డేటా వినియోగ వివరాల కోసం నొక్కండి"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"మొబైల్ డేటాని ఆఫ్ చేయాలా?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"అనుమతి అభ్యర్థనకు ఒక యాప్ అడ్డు తగులుతున్నందున సెట్టింగ్లు మీ ప్రతిస్పందనను ధృవీకరించలేకపోయాయి."</string> </resources> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 9e1783ad63d1..969a0a2e77be 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"ลายนิ้วมือหลัก RSA ของคอมพิวเตอร์คือ:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"อนุญาตจากคอมพิวเตอร์เครื่องนี้เสมอ"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"ไม่อนุญาตให้แก้ไขข้อบกพร่องผ่าน USB"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ผู้ใช้ที่ลงชื่อเข้าใช้อุปกรณ์อยู่ในขณะนี้ไม่สามารถเปิดการแก้ไขข้อบกพร่องผ่าน USB ได้ หากต้องการใช้ฟีเจอร์นี้ ให้เปลี่ยนไปเป็นผู้ใช้หลัก"</string> <string name="compat_mode_on" msgid="6623839244840638213">"ขยายจนเต็มหน้าจอ"</string> <string name="compat_mode_off" msgid="4434467572461327898">"ยืดจนเต็มหน้าจอ"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"กำลังบันทึกภาพหน้าจอ..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"เรียนรู้เพิ่มเติม"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"คุณเชื่อมต่อกับ <xliff:g id="VPN_APP">%1$s</xliff:g> ซึ่งสามารถตรวจสอบกิจกรรมในเครือข่ายของคุณ รวมถึงอีเมล แอป และเว็บไซต์ได้"</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"เปิดการตั้งค่า VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"เปิดข้อมูลรับรองที่เชื่อถือได้"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"ผู้ดูแลระบบได้เปิดการทำบันทึกเครือข่าย ซึ่งจะติดตามดูการรับส่งข้อมูลบนอุปกรณ์ของคุณ\n\nโปรดติดต่อผู้ดูแลระบบสำหรับข้อมูลเพิ่มเติม"</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"แอปนี้ไม่มีหมวดหมู่การแจ้งเตือน"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"ไม่สามารถปิดการแจ้งเตือนจากแอปนี้"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">การแจ้งเตือน 1 ใน <xliff:g id="NUMBER_1">%d</xliff:g> หมวดหมู่จากแอปนี้</item> - <item quantity="one">การแจ้งเตือน 1 ใน <xliff:g id="NUMBER_0">%d</xliff:g> หมวดหมู่จากแอปนี้</item> + <item quantity="other">การแจ้งเตือน 1 ใน <xliff:g id="NUMBER_1">%s</xliff:g> หมวดหมู่จากแอปนี้</item> + <item quantity="one">การแจ้งเตือน 1 ใน <xliff:g id="NUMBER_0">%s</xliff:g> หมวดหมู่จากแอปนี้</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d นาที</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"การใช้งานแบตเตอรี่"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"ไม่สามารถใช้โหมดประหยัดแบตเตอรี่ระหว่างการชาร์จ"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"โหมดประหยัดแบตเตอรี่"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"ไม่สามารถใช้โหมดประหยัดแบตเตอรี่ระหว่างการชาร์จ"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"โหมดประหยัดแบตเตอรี่"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"ลดประสิทธิภาพการทำงานและข้อมูลแบ็กกราวด์"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"ปุ่ม <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"ย่อเล็กสุด"</string> <string name="pip_phone_close" msgid="8416647892889710330">"ปิด"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ลากลงเพื่อปิด"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"เมนูการแสดงภาพซ้อนภาพ"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"เมนู"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ใช้การแสดงภาพซ้อนภาพ"</string> <string name="pip_notification_message" msgid="5619512781514343311">"หากคุณไม่ต้องการให้ <xliff:g id="NAME">%s</xliff:g> ใช้ฟีเจอร์นี้ ให้แตะเพื่อเปิดการตั้งค่าแล้วปิดฟีเจอร์"</string> <string name="pip_play" msgid="1417176722760265888">"เล่น"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"เมนู"</string> <string name="tuner_app" msgid="3507057938640108777">"แอป <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"การแจ้งเตือน"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"แบตเตอรี"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"ภาพหน้าจอ"</string> <string name="notification_channel_general" msgid="4525309436693914482">"ข้อความทั่วไป"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"พื้นที่เก็บข้อมูล"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"แอปที่กำลังทำงานในเบื้องหลัง"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"แตะเพื่อดูรายละเอียดเกี่ยวกับแบตเตอรี่และปริมาณการใช้อินเทอร์เน็ต"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"ปิดอินเทอร์เน็ตมือถือไหม"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"เนื่องจากแอปหนึ่งได้บดบังคำขอสิทธิ์ ระบบจึงไม่สามารถยืนยันคำตอบของคุณสำหรับการตั้งค่าได้"</string> </resources> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index ee1105c34f41..450d61b03e9b 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Ang RSA key fingerprint ng computer ay:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Palaging payagan mula sa computer na ito"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Hindi pinapayagan ang pagde-debug sa pamamagitan ng USB"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Hindi mao-on ng user na kasalukuyang naka-sign in sa device na ito ang pag-debug ng USB. Upang magamit ang feature na ito, lumipat sa pangunahing user."</string> <string name="compat_mode_on" msgid="6623839244840638213">"I-zoom upang punan screen"</string> <string name="compat_mode_off" msgid="4434467572461327898">"I-stretch upang mapuno screen"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Sine-save ang screenshot…"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Matuto pa"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Kumonekta ka sa <xliff:g id="VPN_APP">%1$s</xliff:g>, na maaaring sumubaybay sa iyong aktibidad sa network, kasama ang mga email, app at website."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Buksan ang mga setting ng VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Buksan ang mga pinagkakatiwalaang kredensyal"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Na-on ng iyong admin ang pag-log sa network, na sumusubaybay sa trapiko ng device mo.\n\nPara sa higit pang impormasyon, makipag-ugnayan sa iyong admin."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Walang kategorya ng notification ang app na ito"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Hindi maaaring i-off ang mga notification mula sa app na ito"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 sa <xliff:g id="NUMBER_1">%d</xliff:g> kategorya ng notification mula sa app na ito</item> - <item quantity="other">1 sa <xliff:g id="NUMBER_1">%d</xliff:g> na kategorya ng notification mula sa app na ito</item> + <item quantity="one">1 sa <xliff:g id="NUMBER_1">%s</xliff:g> kategorya ng notification mula sa app na ito</item> + <item quantity="other">1 sa <xliff:g id="NUMBER_1">%s</xliff:g> na kategorya ng notification mula sa app na ito</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="other">%d na minuto</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Paggamit ng baterya"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Hindi available ang Pangtipid sa Baterya kapag nagcha-charge"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Pangtipid sa Baterya"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Hindi available ang pangtipid sa baterya kapag nagcha-charge"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Pangtipid sa baterya"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Binabawasan ang performance at data sa background"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Button na <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"I-minimize"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Isara"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"I-drag pababa upang i-dismiss"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Menu ng picture in picture"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"Nasa picture-in-picture ang <xliff:g id="NAME">%s</xliff:g>"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Kung ayaw mong magamit ni <xliff:g id="NAME">%s</xliff:g> ang feature na ito, i-tap upang buksan ang mga setting at i-off ito."</string> <string name="pip_play" msgid="1417176722760265888">"I-play"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menu"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> app"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Mga Alerto"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Baterya"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Mga Screenshot"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Mga Pangkalahatang Mensahe"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Storage"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Tumatakbo ang mga app sa background"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"I-tap para sa mga detalye tungkol sa paggamit ng baterya at data"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"I-off ang mobile data?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Hindi ma-verify ng Mga Setting ang iyong tugon dahil may app na tumatakip sa isang kahilingan sa pagpapahintulot."</string> </resources> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 376aca5d4b2c..450a3102c020 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Bilgisayarın RSA anahtarı parmak izi:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Bu bilgisayardan her zaman izin ver"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB hata ayıklama işlevine izin verilmiyor"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Bu cihazda geçerli olarak oturum açmış olan kullanıcı, USB hata ayıklama özelliğini açamaz. Bu özelliği kullanmak için birincil kullanıcıya geçin."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Yakınlaştır (ekranı kaplasın)"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Genişlet (ekran kapansın)"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Ekran görüntüsü kaydediliyor..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Daha fazla bilgi"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"E-postalarınız, uygulamalarınız ve web siteleriniz de dahil olmak üzere ağ etkinliğinizi takip edebilen <xliff:g id="VPN_APP">%1$s</xliff:g> ağına bağlısınız."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN ayarlarını aç"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Güvenilir kimlik bilgilerini aç"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Yöneticiniz,cihazınızdaki trafiği izleyen ağ günlük kaydını açtı.\n\nDaha fazla bilgi için yöneticinizle iletişim kurun."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Bu uygulamanın bildirim kategorisi yok"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Bu uygulamanın bildirimleri kapatılamaz"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">Bu uygulamadaki <xliff:g id="NUMBER_1">%d</xliff:g> bildirim kategorisinden 1 tanesi</item> - <item quantity="one">Bu uygulamadaki <xliff:g id="NUMBER_0">%d</xliff:g> bildirim kategorisinden 1 tanesi</item> + <item quantity="other">Bu uygulamadaki <xliff:g id="NUMBER_1">%s</xliff:g> bildirim kategorisinden 1 tanesi</item> + <item quantity="one">Bu uygulamadaki <xliff:g id="NUMBER_0">%s</xliff:g> bildirim kategorisinden 1 tanesi</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d dakika</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Pil kullanımı"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Şarj sırasında Pil Tasarrufu özelliği kullanılamaz"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Pil Tasarrufu"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Şarj sırasında Pil tasarrufu özelliği kullanılamaz"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Pil tasarrufu"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Performansı ve arka plan verilerini azaltır"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g> düğmesi"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Simge durumuna getir"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Kapat"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Kapatmak için aşağıya sürükleyin"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Pencere içinde pencere menüsü"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menü"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g>, pencere içinde pencere özelliğini kullanıyor"</string> <string name="pip_notification_message" msgid="5619512781514343311">"<xliff:g id="NAME">%s</xliff:g> uygulamasının bu özelliği kullanmasını istemiyorsanız dokunarak ayarları açın ve söz konusu özelliği kapatın."</string> <string name="pip_play" msgid="1417176722760265888">"Oynat"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menü"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> uygulaması"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Uyarılar"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Pil"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Ekran görüntüleri"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Genel Mesajlar"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Depolama alanı"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Arka planda çalışan uygulamalar"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Pil ve veri kullanımı ile ilgili ayrıntılar için dokunun"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Mobil veri kapatılsın mı?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Bir uygulama bir izin isteğinin anlaşılmasını engellediğinden, Ayarlar, yanıtınızı doğrulayamıyor."</string> </resources> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 826d3ca6df6f..94c70ccd67c2 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -66,8 +66,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Цифровий відбиток ключа RSA комп’ютера:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Завжди дозволяти з цього комп’ютера"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Ви не можете вмикати налагодження USB"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Користувач поточного облікового запису не може вмикати налагодження USB. Щоб увімкнути цю функцію, увійдіть в обліковий запис основного користувача."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Масштабув. на весь екран"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Розтягнути на весь екран"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Збереження знімка екрана..."</string> @@ -463,8 +462,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Докладніше"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Під’єднано додаток <xliff:g id="VPN_APP">%1$s</xliff:g>, який може відстежувати вашу активність у мережі, як-от доступ до електронної пошти, додатків і веб-сайтів."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Відкрити налаштування мережі VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Відкрити надійні облікові дані"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Ваш адміністратор увімкнув реєстрацію в мережі, під час якої на вашому пристрої відстежується трафік.\n\nЩоб дізнатися більше, зв’яжіться з адміністратором."</string> @@ -564,10 +562,10 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"У цьому додатку немає категорій сповіщень"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Сповіщення з цього додатка не можна вимкнути"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 з <xliff:g id="NUMBER_1">%d</xliff:g> категорії сповіщень із цього додатка</item> - <item quantity="few">1 з <xliff:g id="NUMBER_1">%d</xliff:g> категорій сповіщень із цього додатка</item> - <item quantity="many">1 з <xliff:g id="NUMBER_1">%d</xliff:g> категорій сповіщень із цього додатка</item> - <item quantity="other">1 з <xliff:g id="NUMBER_1">%d</xliff:g> категорії сповіщень із цього додатка</item> + <item quantity="one">1 з <xliff:g id="NUMBER_1">%s</xliff:g> категорії сповіщень із цього додатка</item> + <item quantity="few">1 з <xliff:g id="NUMBER_1">%s</xliff:g> категорій сповіщень із цього додатка</item> + <item quantity="many">1 з <xliff:g id="NUMBER_1">%s</xliff:g> категорій сповіщень із цього додатка</item> + <item quantity="other">1 з <xliff:g id="NUMBER_1">%s</xliff:g> категорії сповіщень із цього додатка</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -601,8 +599,8 @@ <item quantity="other">%d хвилини</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Використання заряду"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Режим енергозбереження не можна ввімкнути під час заряджання"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Режим енергозбереження"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Режим економії заряду акумулятора не працює під час заряджання"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Режим економії заряду акумулятора"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Знижується продуктивність і обмежується обмін даними у фоновому режимі"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Кнопка <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -742,7 +740,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Згорнути"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Закрити"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Перетягніть униз, щоб закрити"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Меню \"Картинка в картинці\""</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Меню"</string> <string name="pip_notification_title" msgid="3204024940158161322">"У додатку <xliff:g id="NAME">%s</xliff:g> є функція \"Картинка в картинці\""</string> <string name="pip_notification_message" msgid="5619512781514343311">"Щоб додаток <xliff:g id="NAME">%s</xliff:g> не використовував цю функцію, вимкніть її в налаштуваннях."</string> <string name="pip_play" msgid="1417176722760265888">"Відтворити"</string> @@ -770,8 +768,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Меню"</string> <string name="tuner_app" msgid="3507057938640108777">"Додаток <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Сповіщення"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Акумулятор"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Знімки екрана"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Загальні повідомлення"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Пам’ять"</string> @@ -792,4 +789,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Додатки, які працюють у фоновому режимі"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Торкніться, щоб перевірити використання акумулятора й трафік"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Вимкнути мобільний трафік?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Не вдається підтвердити вашу відповідь у налаштуваннях, оскільки інший додаток заступає запит на дозвіл."</string> </resources> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index c2305504b8b9..9f44d67380e6 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"کمپیوٹر کے RSA کا کلیدی فنگر پرنٹ ہے:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"اس کمپیوٹر سے ہمیشہ اجازت دیں"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB ڈیبگ کرنے کی اجازت نہیں ہے"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"اس آلہ پر فی الحال سائن ان کردہ صارف USB ڈیبگنگ آن نہیں کر سکتا۔ اس خصوصیت کا استعمال کرنے کیلئے، ابتدائی صارف پر سوئچ کریں۔"</string> <string name="compat_mode_on" msgid="6623839244840638213">"پوری سکرین پر زوم کریں"</string> <string name="compat_mode_off" msgid="4434467572461327898">"پوری سکرین پر پھیلائیں"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"اسکرین شاٹ محفوظ ہو رہا ہے…"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"مزید جانیں"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"آپ <xliff:g id="VPN_APP">%1$s</xliff:g> سے منسلک ہیں جو ای میلز، ایپس اور ویب سائٹس سمیت آپ کے نیٹ ورک کی سرگرمی مانیٹر کر سکتی ہے۔"</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN کی ترتیبات کھولیں"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"بھروسے مند استناد کھولیں"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"آپ کے ایڈمن نے نیٹ ورک لاگنگ آن کر دی ہے، جو آپ کے آلہ پر ٹریفک کو مانیٹر کرتی ہے۔\n\nمزید معلومات کیلئے اپنے ایڈمن سے رابطہ کریں۔"</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"اس ایپ میں اطلاعاتی زمرے نہیں ہیں"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"اس ایپ کی اطلاعات کو آف نہیں کیا جا سکتا"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">اس ایپ کے <xliff:g id="NUMBER_1">%d</xliff:g> اطلاعاتی زمروں میں سے 1</item> - <item quantity="one">اس ایپ کے <xliff:g id="NUMBER_0">%d</xliff:g> اطلاعاتی زمرے میں سے 1</item> + <item quantity="other">اس ایپ کے <xliff:g id="NUMBER_1">%s</xliff:g> اطلاعاتی زمروں میں سے 1</item> + <item quantity="one">اس ایپ کے <xliff:g id="NUMBER_0">%s</xliff:g> اطلاعاتی زمرے میں سے 1</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>، <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d منٹ</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"بیٹری کا استعمال"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"چارجنگ کے دوران بیٹری سیور دستیاب نہیں ہے"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"بیٹری سیور"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"چارجنگ کے دوران بیٹری سیور دستیاب نہیں ہے"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"بیٹری سیور"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"کارکردگی اور پس منظر کا ڈیٹا کم کر دیتا ہے"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"بٹن <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"چھوٹی کریں"</string> <string name="pip_phone_close" msgid="8416647892889710330">"بند کریں"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"برخاست کرنے کیلئے نیچے گھسیٹیں"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"تصویر کے مینو میں تصویر"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"مینو"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> تصویر میں تصویر میں ہے"</string> <string name="pip_notification_message" msgid="5619512781514343311">"اگر آپ نہیں چاہتے ہیں کہ <xliff:g id="NAME">%s</xliff:g> اس خصوصیت کا استعمال کرے تو ترتیبات کھولنے کے لیے تھپتھپا کر اسے آف کرے۔"</string> <string name="pip_play" msgid="1417176722760265888">"چلائیں"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"مینو"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> ایپ"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"الرٹس"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"بیٹری"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"اسکرین شاٹس"</string> <string name="notification_channel_general" msgid="4525309436693914482">"عمومی پیغامات"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"اسٹوریج"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"ایپس پس منظر میں چل رہی ہیں"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"بیٹری اور ڈیٹا استعمال کے بارے میں تفصیلات کے لیے تھپتھپائیں"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"موبائل ڈیٹا آف کریں؟"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"چونکہ ایک ایپ اجازت کی درخواست کو مبہم کر رہی ہے، لہذا ترتیبات آپ کے جواب کی توثیق نہیں کر سکتی ہیں۔"</string> </resources> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index e9ff6d1505ff..6d7ae3c04e23 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -44,7 +44,7 @@ <string name="battery_saver_start_action" msgid="5576697451677486320">"Quvvat tejash funksiyasini yoqing"</string> <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Sozlamalar"</string> <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string> - <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Ekranni avtomatik burish"</string> + <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Ekranning avtomatik burilishi"</string> <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUTE"</string> <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string> <string name="status_bar_settings_notifications" msgid="397146176280905137">"Eslatmalar"</string> @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Kompyuterning RSA tugmasi barmoq izlari:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Doimo ushbu kompyuterdan ruxsat berilsin"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB orqali nosozliklarni tuzatishga ruxsat berilmagan"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Ayni paytda ushbu qurilmaga o‘z hisobi bilan kirgan foydalanuvchi USB orqali nosozliklarni tuzatish funksiyasini yoqa olmaydi. Bu funksiyadan foydalanish uchun asosiy foydalanuvchi profiliga o‘ting."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Ekranga moslashtirish"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Ekran hajmida cho‘zish"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Skrinshot saqlanmoqda…"</string> @@ -279,7 +278,7 @@ <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Ulangan qurilmalar topilmadi"</string> <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Yorqinlik"</string> <string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Avtomatik burilish"</string> - <string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Ekranni avtomatik burish"</string> + <string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Ekranning avtomatik burilishi"</string> <string name="accessibility_quick_settings_rotation_value" msgid="8187398200140760213">"<xliff:g id="ID_1">%s</xliff:g> rejimi"</string> <string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Aylanmaydigan qilingan"</string> <string name="quick_settings_rotation_locked_portrait_label" msgid="5102691921442135053">"Tik holat"</string> @@ -459,8 +458,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Batafsil"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"<xliff:g id="VPN_APP">%1$s</xliff:g> ilovasi ishga tushirilgan. U internetdagi harakatlaringiz, jumladan, e-pochta, ilova va veb-saytlardagi xatti-harakatlaringizni kuzatishi mumkin."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN sozlamalarini ochish"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Ishonchli sertifikatlarni ochish"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administrator qurilmangizdagi trafikni nazorat qiluvchi tarmoq jurnalini yoqdi.\n\nBatafsil ma’lumot olish uchun administratoringizga murojaat qiling."</string> @@ -560,8 +558,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Bu ilovada bildirishnomalar turkumi yo‘q"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Bu ilova bildirishnomalarini o‘chirib bo‘lmaydi"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">Bu ilovadagi <xliff:g id="NUMBER_1">%d</xliff:g> ta bildirishnomalar turkumidan 1 tasi</item> - <item quantity="one">Bu ilovadagi <xliff:g id="NUMBER_0">%d</xliff:g> ta bildirishnomalar turkumidan 1 tasi</item> + <item quantity="other">Bu ilovadagi <xliff:g id="NUMBER_1">%s</xliff:g> ta bildirishnomalar turkumidan 1 tasi</item> + <item quantity="one">Bu ilovadagi <xliff:g id="NUMBER_0">%s</xliff:g> ta bildirishnomalar turkumidan 1 tasi</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -589,8 +587,8 @@ <item quantity="one">%d daqiqa</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Batareya sarfi"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Quvvat tejash rejimidan quvvatlash vaqtida foydalanib bo‘lmaydi"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Quvvat tejash rejimi"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Quvvat tejash rejimidan quvvatlash vaqtida foydalanib bo‘lmaydi"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Quvvat tejash rejimi"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Unumdorlik pasayadi va fonda internetdan foydalanish cheklanadi"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g> tugmasi"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Bosh ekran"</string> @@ -730,7 +728,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Yig‘ish"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Yopish"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Yopish uchun pastga torting"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Tasvir ustida tasvir menyusi"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menyu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> tasvir ustida tasvir rejimida"</string> <string name="pip_notification_message" msgid="5619512781514343311">"<xliff:g id="NAME">%s</xliff:g> ilovasi uchun bu funksiyani sozlamalar orqali faolsizlantirish mumkin."</string> <string name="pip_play" msgid="1417176722760265888">"Ijro"</string> @@ -758,8 +756,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menyu"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> ilovasi"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Ogohlantirishlar"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Batareya"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Skrinshotlar"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Umumiy xabarlar"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Xotira"</string> @@ -780,4 +777,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Fonda ishlayotgan ilovalar"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Batareya va trafik sarfi tafsilotlari uchun ustiga bosing"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Mobil internet o‘chirib qo‘yilsinmi?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Ilova ruxsatnoma so‘roviga xalaqit qilayotgani tufayli, “Sozlamalar” ilovasi javobingizni tekshira olmaydi."</string> </resources> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index bc0505885086..278fb9a041f5 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Tệp tham chiếu khóa RSA của máy tính là:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Luôn cho phép từ máy tính này"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Tính năng gỡ lỗi USB không được phép"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Người dùng hiện đã đăng nhập vào thiết bị này không thể bật tính năng gỡ lỗi USB. Để sử dụng tính năng này, hãy chuyển sang người dùng chính."</string> <string name="compat_mode_on" msgid="6623839244840638213">"T.phóng để lấp đầy m.hình"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Giãn ra để lấp đầy m.hình"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Đang lưu ảnh chụp màn hình..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Tìm hiểu thêm"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Bạn đang kết nối với <xliff:g id="VPN_APP">%1$s</xliff:g>. Ứng dụng này có thể giám sát hoạt động mạng của bạn, bao gồm email, ứng dụng và trang web."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Mở cài đặt VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Mở thông tin xác thực tin cậy"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Quản trị viên đã bật tính năng ghi nhật ký mạng. Tính năng này giám sát lưu lượng truy cập trên thiết bị của bạn.\n\nĐể biết thêm thông tin, hãy liên hệ với quản trị viên của bạn."</string> @@ -560,8 +558,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Ứng dụng này không có loại thông báo"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Không thể tắt thông báo từ ứng dụng này"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">1 trên tổng số <xliff:g id="NUMBER_1">%d</xliff:g> loại thông báo từ ứng dụng này</item> - <item quantity="one">1 trên tổng số <xliff:g id="NUMBER_0">%d</xliff:g> loại thông báo từ ứng dụng này</item> + <item quantity="other">1 trên tổng số <xliff:g id="NUMBER_1">%s</xliff:g> loại thông báo từ ứng dụng này</item> + <item quantity="one">1 trên tổng số <xliff:g id="NUMBER_0">%s</xliff:g> loại thông báo từ ứng dụng này</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -589,8 +587,8 @@ <item quantity="one">%d phút</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Mức sử dụng pin"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Trình tiết kiệm pin không khả dụng trong khi sạc"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Trình tiết kiệm pin"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Không sử dụng được trình tiết kiệm pin trong khi sạc"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Trình tiết kiệm pin"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Giảm hiệu suất và dữ liệu nền"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Nút <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -730,7 +728,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Thu nhỏ"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Đóng"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Kéo xuống để loại bỏ"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Menu ảnh trong ảnh"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> đang ở chế độ ảnh trong ảnh"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Nếu bạn không muốn <xliff:g id="NAME">%s</xliff:g> sử dụng tính năng này, hãy nhấn để mở cài đặt và tắt tính năng này."</string> <string name="pip_play" msgid="1417176722760265888">"Phát"</string> @@ -758,8 +756,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Menu"</string> <string name="tuner_app" msgid="3507057938640108777">"Ứng dụng <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Cảnh báo"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Pin"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Ảnh chụp màn hình"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Thông báo chung"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Bộ nhớ"</string> @@ -780,4 +777,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Ứng dụng đang chạy trong nền"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Nhấn để biết chi tiết về mức sử dụng dữ liệu và pin"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Tắt dữ liệu di động?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Vì ứng dụng đang che khuất yêu cầu cấp quyền nên Cài đặt không thể xác minh câu trả lời của bạn."</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index e2bf586dad77..8d83ada04f23 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"这台计算机的 RSA 密钥指纹如下:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"一律允许使用这台计算机进行调试"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"不允许使用 USB 调试功能"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"目前已登录此设备的用户无法开启 USB 调试功能。要使用此功能,请切换为主要用户的帐号。"</string> <string name="compat_mode_on" msgid="6623839244840638213">"缩放以填满屏幕"</string> <string name="compat_mode_off" msgid="4434467572461327898">"拉伸以填满屏幕"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"正在保存屏幕截图..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"了解详情"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"您已连接到<xliff:g id="VPN_APP">%1$s</xliff:g>,该应用可以监控您的网络活动,包括收发电子邮件、使用应用和浏览网站。"</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"打开 VPN 设置"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"打开可信凭据列表"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"您的管理员已开启网络日志功能,该功能会监控您设备上的流量。\n\n如需更多信息,请与您的管理员联系。"</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"此应用没有通知类别"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"无法关闭来自此应用的通知"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">此应用指定的 1 个通知类别(共 <xliff:g id="NUMBER_1">%d</xliff:g> 个)</item> - <item quantity="one">此应用指定的 1 个通知类别(共 <xliff:g id="NUMBER_0">%d</xliff:g> 个)</item> + <item quantity="other">此应用指定的 1 个通知类别(共 <xliff:g id="NUMBER_1">%s</xliff:g> 个)</item> + <item quantity="one">此应用指定的 1 个通知类别(共 <xliff:g id="NUMBER_0">%s</xliff:g> 个)</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>、<xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d 分钟</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"电池使用情况"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"充电过程中无法使用省电模式"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"省电模式"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"充电过程中无法使用省电模式"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"省电模式"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"降低性能并限制后台流量"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g>按钮"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string> <string name="pip_phone_close" msgid="8416647892889710330">"关闭"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"向下拖动即可关闭"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"画中画菜单"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"菜单"</string> <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g>目前位于“画中画”中"</string> <string name="pip_notification_message" msgid="5619512781514343311">"如果您不想让“<xliff:g id="NAME">%s</xliff:g>”使用此功能,请点按以打开设置,然后关闭此功能。"</string> <string name="pip_play" msgid="1417176722760265888">"播放"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"菜单"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g>应用"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"提醒"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"电池"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"屏幕截图"</string> <string name="notification_channel_general" msgid="4525309436693914482">"常规消息"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"存储空间"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"在后台运行的应用"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"点按即可详细了解电量和流量消耗情况"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"要关闭移动数据网络吗?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"由于某个应用遮挡了权限请求界面,因此“设置”应用无法验证您的回应。"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 4483c49eaac7..3a428276ffbf 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"這部電腦的 RSA 密鑰指紋如下:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"一律允許透過這部電腦進行"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"不允許 USB 偵錯"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"目前登入此裝置的使用者無法啟用 USB 偵錯功能。如要使用此功能,請切換至主要使用者。"</string> <string name="compat_mode_on" msgid="6623839244840638213">"放大為全螢幕"</string> <string name="compat_mode_off" msgid="4434467572461327898">"放大為全螢幕"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"正在儲存螢幕擷取畫面..."</string> @@ -459,8 +458,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"瞭解詳情"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"您已連接至「<xliff:g id="VPN_APP">%1$s</xliff:g>」,此應用程式可以監控您的網絡活動,包括電郵、應用程式及網站。"</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"開啟 VPN 設定"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"開啟信任的憑證"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"您的管理員已開啟網絡記錄功能,以監控您裝置上的流量。\n\n如需瞭解詳情,請聯絡您的管理員。"</string> @@ -560,8 +558,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"此應用程式沒有通知類別"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"無法關閉此應用程式的通知"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">此應用程式的 1 個通知類別 (共 <xliff:g id="NUMBER_1">%d</xliff:g> 個)</item> - <item quantity="one">此應用程式的 1 個通知類別 (共 <xliff:g id="NUMBER_0">%d</xliff:g> 個)</item> + <item quantity="other">此應用程式的 1 個通知類別 (共 <xliff:g id="NUMBER_1">%s</xliff:g> 個)</item> + <item quantity="one">此應用程式的 1 個通知類別 (共 <xliff:g id="NUMBER_0">%s</xliff:g> 個)</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>、<xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -589,8 +587,8 @@ <item quantity="one">%d 分鐘</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"電池用量"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"充電時無法使用「省電模式」"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"省電模式"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"充電時無法使用省電模式"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"省電模式"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"降低效能並限制背景數據傳輸"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g> 鍵"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -730,7 +728,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string> <string name="pip_phone_close" msgid="8416647892889710330">"關閉"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"向下拖曳即可關閉"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"畫中畫選單"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"選單"</string> <string name="pip_notification_title" msgid="3204024940158161322">"「<xliff:g id="NAME">%s</xliff:g>」目前在畫中畫模式"</string> <string name="pip_notification_message" msgid="5619512781514343311">"如果您不想「<xliff:g id="NAME">%s</xliff:g>」使用此功能,請輕按以開啟設定,然後停用此功能。"</string> <string name="pip_play" msgid="1417176722760265888">"播放"</string> @@ -758,8 +756,7 @@ <string name="tuner_menu" msgid="191640047241552081">"選單"</string> <string name="tuner_app" msgid="3507057938640108777">"「<xliff:g id="APP">%1$s</xliff:g>」應用程式"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"通知"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"電池"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"螢幕擷取畫面"</string> <string name="notification_channel_general" msgid="4525309436693914482">"一般訊息"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"儲存空間"</string> @@ -780,4 +777,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"正在背景中執行的應用程式"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"輕按即可查看電池和數據用量詳情"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"要關閉流動數據嗎?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"由於某個應用程式已阻擋權限要求畫面,因此「設定」應用程式無法驗證您的回應。"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 16a4369a5f00..d767979b25c3 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"這台電腦的 RSA 金鑰指紋如下:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"一律允許透過這台電腦進行"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"無權使用 USB 偵錯功能"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"目前登入這個裝置的使用者無法啟用 USB 偵錯功能。如要使用這項功能,請切換到主要使用者。"</string> <string name="compat_mode_on" msgid="6623839244840638213">"放大為全螢幕"</string> <string name="compat_mode_off" msgid="4434467572461327898">"放大為全螢幕"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"正在儲存螢幕擷取畫面…"</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"瞭解詳情"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"由於你已連結至「<xliff:g id="VPN_APP">%1$s</xliff:g>」,你的網路活動 (包括收發電子郵件、使用應用程式及瀏覽網站) 可能會受到這個應用程式監控。"</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"開啟 VPN 設定"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"開啟信任的憑證"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"你的管理員已啟用網路紀錄功能,可監控你裝置的流量。\n\n如需詳細資訊,請與你的管理員聯絡。"</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"這個應用程式沒有通知類別"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"無法關閉這個應用程式發出的通知"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="other">在 <xliff:g id="NUMBER_1">%d</xliff:g> 個通知類別中,有 1 個類別是來自這個應用程式</item> - <item quantity="one">在 <xliff:g id="NUMBER_0">%d</xliff:g> 個通知類別中,有 1 個類別是來自這個應用程式</item> + <item quantity="other">在 <xliff:g id="NUMBER_1">%s</xliff:g> 個通知類別中,有 1 個類別是來自這個應用程式</item> + <item quantity="one">在 <xliff:g id="NUMBER_0">%s</xliff:g> 個通知類別中,有 1 個類別是來自這個應用程式</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>、<xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="one">%d 分鐘</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"電池用量"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"充電時無法使用節約耗電量模式"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"節約耗電量"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"充電時無法使用節約耗電量模式"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"節約耗電量"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"降低效能並限制背景資料傳輸"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g> 按鈕"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home 鍵"</string> @@ -618,7 +616,7 @@ <string name="keyboard_key_numpad_template" msgid="8729216555174634026">"數字鍵 <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_shortcut_group_system" msgid="6472647649616541064">"系統"</string> <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"主畫面"</string> - <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"近期活動"</string> + <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"最近"</string> <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"返回"</string> <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"通知"</string> <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"鍵盤快速鍵"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string> <string name="pip_phone_close" msgid="8416647892889710330">"關閉"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"向下拖曳即可關閉"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"子母畫面選單"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"選單"</string> <string name="pip_notification_title" msgid="3204024940158161322">"「<xliff:g id="NAME">%s</xliff:g>」目前在子母畫面中"</string> <string name="pip_notification_message" msgid="5619512781514343311">"如果你不想讓「<xliff:g id="NAME">%s</xliff:g>」使用這項功能,請輕觸開啟設定頁面,然後停用此功能。"</string> <string name="pip_play" msgid="1417176722760265888">"播放"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"選單"</string> <string name="tuner_app" msgid="3507057938640108777">"「<xliff:g id="APP">%1$s</xliff:g>」應用程式"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"快訊"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"電池"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"螢幕擷取畫面"</string> <string name="notification_channel_general" msgid="4525309436693914482">"一般訊息"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"儲存空間"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"在背景執行的應用程式"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"輕觸即可查看電池和數據用量詳情"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"要關閉行動數據嗎?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"由於某個應用程式覆蓋了權限要求畫面,因此「設定」應用程式無法驗證你的回應。"</string> </resources> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 7cd1bd56bf91..de61bf568e44 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -64,8 +64,7 @@ <string name="usb_debugging_message" msgid="2220143855912376496">"Izigxivizo zeminwe zokhiye we-RSA wekhompyutha ngu:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string> <string name="usb_debugging_always" msgid="303335496705863070">"Hlala uvumela njalo kusuka kule khompyutha"</string> <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Ukususa iphutha kwe-USB akuvunyelwe"</string> - <!-- no translation found for usb_debugging_secondary_user_message (6067122453571699801) --> - <skip /> + <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Umsebenzisi manje ongene ngemvume kule divayisi entsha akakwazi ukuvula ukulungisa amaphutha ku-USB. Ukuze usebenzise lesi sici, shintshela kumsebenzisi oyinhloko."</string> <string name="compat_mode_on" msgid="6623839244840638213">"Sondeza ukugcwalisa isikrini"</string> <string name="compat_mode_off" msgid="4434467572461327898">"Nweba ukugcwalisa isikrini"</string> <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Ilondoloz umfanekiso weskrini..."</string> @@ -457,8 +456,7 @@ <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Funda kabanzi"</string> <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Uxhumeke ku-<xliff:g id="VPN_APP">%1$s</xliff:g>, engaqapha umsebenzi wenethiwekhi yakho, ofaka ama-imeyili, izinhlelo zokusebenza, namawebhusayithi."</string> <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string> - <!-- no translation found for monitoring_description_vpn_settings (6434859242636063861) --> - <skip /> + <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"Vula izilungiselelo ze-VPN"</string> <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string> <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Vula ukuqinisekisa okuthenjiwe"</string> <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Umlawuli wakho uvule ukungena kwenethiwekhi, okuhlola ithrafikhi kudivayisi yakho.\n\nNgolwazi olubanzi xhumana nomlawuli wakho."</string> @@ -558,8 +556,8 @@ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Lolu hlelo lokusebenza alunazo izigaba zesaziso"</string> <string name="notification_unblockable_desc" msgid="3561016061737896906">"Izaziso kusuka kulolu hlelo lokusebenza azikwazi ukuvalwa"</string> <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663"> - <item quantity="one">1 isigaba kwezingu-<xliff:g id="NUMBER_1">%d</xliff:g> sezaziso kusukela kulolu hlelo lokusebenza</item> - <item quantity="other">1 isigaba kwezingu-<xliff:g id="NUMBER_1">%d</xliff:g> sezaziso kusukela kulolu hlelo lokusebenza</item> + <item quantity="one">1 isigaba kwezingu-<xliff:g id="NUMBER_1">%s</xliff:g> sezaziso kusukela kulolu hlelo lokusebenza</item> + <item quantity="other">1 isigaba kwezingu-<xliff:g id="NUMBER_1">%s</xliff:g> sezaziso kusukela kulolu hlelo lokusebenza</item> </plurals> <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string> <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157"> @@ -587,8 +585,8 @@ <item quantity="other">%d amaminithi</item> </plurals> <string name="battery_panel_title" msgid="7944156115535366613">"Ukusetshenziswa kwebhethri"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Isilondolozi sebhethri asitholakali ngesikhathi sokushaja"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"Isilondolozi sebhethri"</string> + <string name="battery_detail_charging_summary" msgid="4055327085770378335">"Isilondolozi sebhethri asitholakali ngesikhathi sokushaja"</string> + <string name="battery_detail_switch_title" msgid="8763441006881907058">"Isilondolozi sebhethri"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Sehlisa ukusebenza nedatha yasemuva"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"Inkinobho <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Ekhaya"</string> @@ -728,7 +726,7 @@ <string name="pip_phone_minimize" msgid="1079119422589131792">"Nciphisa"</string> <string name="pip_phone_close" msgid="8416647892889710330">"Vala"</string> <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Hudulela phansi ukuze ucashise"</string> - <string name="pip_menu_title" msgid="3328510504196964712">"Isithombe ngemenyu yesithombe ngesithombe"</string> + <string name="pip_menu_title" msgid="4707292089961887657">"Imenyu"</string> <string name="pip_notification_title" msgid="3204024940158161322">"U-<xliff:g id="NAME">%s</xliff:g> ungaphakathi kwesithombe esiphakathi kwesithombe"</string> <string name="pip_notification_message" msgid="5619512781514343311">"Uma ungafuni i-<xliff:g id="NAME">%s</xliff:g> ukuthi isebenzise lesi sici, thepha ukuze uvule izilungiselelo uphinde uyivale."</string> <string name="pip_play" msgid="1417176722760265888">"Dlala"</string> @@ -756,8 +754,7 @@ <string name="tuner_menu" msgid="191640047241552081">"Imenyu"</string> <string name="tuner_app" msgid="3507057938640108777">"<xliff:g id="APP">%1$s</xliff:g> uhlelo lokusebenza"</string> <string name="notification_channel_alerts" msgid="4496839309318519037">"Izexwayiso"</string> - <!-- no translation found for notification_channel_battery (5786118169182888462) --> - <skip /> + <string name="notification_channel_battery" msgid="5786118169182888462">"Ibhethri"</string> <string name="notification_channel_screenshot" msgid="6314080179230000938">"Izithombe-skrini"</string> <string name="notification_channel_general" msgid="4525309436693914482">"Imilayezo ejwayelekile"</string> <string name="notification_channel_storage" msgid="3077205683020695313">"Isitoreji"</string> @@ -778,4 +775,5 @@ <string name="running_foreground_services_title" msgid="381024150898615683">"Izinhlelo zokusebenza zisebenza ngasemuva"</string> <string name="running_foreground_services_msg" msgid="6326247670075574355">"Thepha ngemininingwane ekusetshenzisweni kwebhethri nedatha"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Vala idatha yeselula?"</string> + <string name="touch_filtered_warning" msgid="8671693809204767551">"Ngoba uhlelo lokusebenza lusitha isicelo semvume, Izilungiselelo azikwazi ukuqinisekisa impendulo yakho."</string> </resources> diff --git a/packages/SystemUI/res/values/colors_car.xml b/packages/SystemUI/res/values/colors_car.xml index 4faf252817ee..1b8c2fa68244 100644 --- a/packages/SystemUI/res/values/colors_car.xml +++ b/packages/SystemUI/res/values/colors_car.xml @@ -17,8 +17,11 @@ */ --> <resources> + <color name="car_qs_background_primary">#263238</color> <!-- Blue Gray 900 --> <color name="car_user_switcher_progress_bgcolor">#00000000</color> <!-- Transparent --> <color name="car_user_switcher_progress_fgcolor">#80CBC4</color> <!-- Teal 200 --> + <color name="car_user_switcher_no_user_image_bgcolor">#FAFAFA</color> <!-- Grey 50 --> + <color name="car_user_switcher_no_user_image_fgcolor">#212121</color> <!-- Grey 900 --> <color name="car_start_driving_background">#FAFAFA</color> <!-- Grey 50 --> <color name="car_start_driving_text">#212121</color> <!-- Grey 900 --> </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index c8e6021d6f89..54421f74419e 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -846,7 +846,8 @@ <dimen name="edge_margin">16dp</dimen> <dimen name="rounded_corner_radius">0dp</dimen> - <dimen name="rounded_corner_content_padding">8dp</dimen> + <dimen name="rounded_corner_content_padding">0dp</dimen> + <dimen name="nav_content_padding">0dp</dimen> <!-- Intended corner radius when drawing the mobile signal --> <dimen name="stat_sys_mobile_signal_corner_radius">0.75dp</dimen> diff --git a/packages/SystemUI/res/values/dimens_car.xml b/packages/SystemUI/res/values/dimens_car.xml index d5d4e10d12ae..5f56c4ea6f2d 100644 --- a/packages/SystemUI/res/values/dimens_car.xml +++ b/packages/SystemUI/res/values/dimens_car.xml @@ -18,10 +18,12 @@ <resources> <dimen name="car_margin">148dp</dimen> - <dimen name="car_fullscreen_user_pod_margin_side">44dp</dimen> <dimen name="car_fullscreen_user_pod_margin_above_text">24dp</dimen> + <dimen name="car_fullscreen_user_pod_margin_between">24dp</dimen> + <dimen name="car_fullscreen_user_pod_icon_text_size">96dp</dimen> <dimen name="car_fullscreen_user_pod_image_avatar_width">192dp</dimen> <dimen name="car_fullscreen_user_pod_image_avatar_height">192dp</dimen> + <dimen name="car_fullscreen_user_pod_width">264dp</dimen> <dimen name="car_fullscreen_user_pod_text_size">40sp</dimen> <!-- B1 --> <dimen name="car_navigation_button_width">64dp</dimen> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 69ccb67473ae..7ccb6b0db128 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1466,8 +1466,8 @@ <!-- Notification: Control panel: Label that shows how many channels this application has defined, describing the current notification channel as "1 out of n notification categories from this app". --> <plurals name="notification_num_channels_desc"> - <item quantity="one">1 out of <xliff:g id="number">%d</xliff:g> notification category from this app</item> - <item quantity="other">1 out of <xliff:g id="number">%d</xliff:g> notification categories from this app</item> + <item quantity="one">1 out of <xliff:g id="number">%s</xliff:g> notification category from this app</item> + <item quantity="other">1 out of <xliff:g id="number">%s</xliff:g> notification categories from this app</item> </plurals> <!-- Notification: Control panel: For bundles of notifications, this label that lists the @@ -1538,10 +1538,10 @@ <string name="battery_panel_title">Battery usage</string> <!-- Summary of battery saver not available [CHAR LIMIT=NONE] --> - <string name="battery_detail_charging_summary">Battery Saver not available during charging</string> + <string name="battery_detail_charging_summary">Battery saver not available during charging</string> <!-- Title of switch for battery saver [CHAR LIMIT=NONE] --> - <string name="battery_detail_switch_title">Battery Saver</string> + <string name="battery_detail_switch_title">Battery saver</string> <!-- Summary of switch for battery saver [CHAR LIMIT=NONE] --> <string name="battery_detail_switch_summary">Reduces performance and background data</string> @@ -2051,4 +2051,10 @@ <!-- Prompt to turn off data usage [CHAR LIMIT=NONE] --> <string name="data_usage_disable_mobile" msgid="8656552431969276305">Turn off mobile data?</string> + <!-- Warning shown when user input has been blocked due to another app overlaying screen + content. Since we don't know what the app is showing on top of the input target, we + can't verify user consent. [CHAR LIMIT=NONE] --> + <string name="touch_filtered_warning">Because an app is obscuring a permission request, Settings + can’t verify your response.</string> + </resources> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java index abc3b94777b0..775b9e8a4d3b 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java @@ -223,8 +223,9 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout @Override public void onTick(long millisUntilFinished) { int secondsRemaining = (int) Math.round(millisUntilFinished / 1000.0); - mSecurityMessageDisplay.formatMessage( - R.string.kg_too_many_failed_attempts_countdown, secondsRemaining); + mSecurityMessageDisplay.setMessage(mContext.getResources().getQuantityString( + R.plurals.kg_too_many_failed_attempts_countdown, + secondsRemaining, secondsRemaining)); } @Override diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java index ce3068d765a8..cb5afec79073 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java @@ -72,6 +72,7 @@ class KeyguardEsimArea extends Button implements View.OnClickListener { public KeyguardEsimArea(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); + mEuiccManager = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE); setOnClickListener(this); } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java index 3c9a6b9dcdec..ec5f356a1a55 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java @@ -332,8 +332,9 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit @Override public void onTick(long millisUntilFinished) { final int secondsRemaining = (int) Math.round(millisUntilFinished / 1000.0); - mSecurityMessageDisplay.formatMessage( - R.string.kg_too_many_failed_attempts_countdown, secondsRemaining); + mSecurityMessageDisplay.setMessage(mContext.getResources().getQuantityString( + R.plurals.kg_too_many_failed_attempts_countdown, + secondsRemaining, secondsRemaining)); } @Override diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java index 4c7b48d1f438..7225ba99f51c 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java @@ -60,9 +60,19 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView { KeyguardUpdateMonitorCallback mUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() { @Override public void onSimStateChanged(int subId, int slotId, State simState) { - if (DEBUG) Log.v(TAG, "onSimStateChanged(subId=" + subId + ",state=" + simState + ")"); - resetState(); - }; + if (DEBUG) Log.v(TAG, "onSimStateChanged(subId=" + subId + ",state=" + simState + ")"); + switch(simState) { + // If the SIM is removed, then we must remove the keyguard. It will be put up + // again when the PUK locked SIM is re-entered. + case ABSENT: { + KeyguardUpdateMonitor.getInstance(getContext()).reportSimUnlocked(mSubId); + mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser()); + break; + } + default: + resetState(); + } + } }; public KeyguardSimPinView(Context context) { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java index d8163ba65766..171cf23696ff 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java @@ -62,9 +62,23 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView { KeyguardUpdateMonitorCallback mUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() { @Override public void onSimStateChanged(int subId, int slotId, State simState) { - if (DEBUG) Log.v(TAG, "onSimStateChanged(subId=" + subId + ",state=" + simState + ")"); - resetState(); - }; + if (DEBUG) Log.v(TAG, "onSimStateChanged(subId=" + subId + ",state=" + simState + ")"); + switch(simState) { + // If the SIM is removed, then we must remove the keyguard. It will be put up + // again when the PUK locked SIM is re-entered. + case ABSENT: + // intentional fall-through + // If the SIM is unlocked via a key sequence through the emergency dialer, it will + // move into the READY state and the PUK lock keyguard should be removed. + case READY: { + KeyguardUpdateMonitor.getInstance(getContext()).reportSimUnlocked(mSubId); + mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser()); + break; + } + default: + resetState(); + } + } }; public KeyguardSimPukView(Context context) { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 669594b86e54..bb6213b8921f 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -1157,10 +1157,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } + private boolean shouldListenForFingerprintAssistant() { + return mAssistantVisible && mKeyguardOccluded + && !mUserFingerprintAuthenticated.get(getCurrentUser(), false) + && !mUserHasTrust.get(getCurrentUser(), false); + } + private boolean shouldListenForFingerprint() { return (mKeyguardIsVisible || !mDeviceInteractive || (mBouncer && !mKeyguardGoingAway) || mGoingToSleep || - (mAssistantVisible && mKeyguardOccluded)) + shouldListenForFingerprintAssistant()) && !mSwitchingUser && !isFingerprintDisabled(getCurrentUser()) && !mKeyguardGoingAway; } diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java index c4de63bdd303..fd2447bd47b4 100644 --- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java +++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java @@ -18,6 +18,7 @@ package com.android.systemui; import static android.provider.Settings.System.SHOW_BATTERY_PERCENT; import android.animation.ArgbEvaluator; +import android.app.ActivityManager; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; @@ -40,6 +41,7 @@ import android.widget.TextView; import com.android.settingslib.Utils; import com.android.settingslib.graph.BatteryMeterDrawableBase; +import com.android.systemui.settings.CurrentUserTracker; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; @@ -58,6 +60,7 @@ public class BatteryMeterView extends LinearLayout implements private final BatteryMeterDrawableBase mDrawable; private final String mSlotBattery; private final ImageView mBatteryIconView; + private final CurrentUserTracker mUserTracker; private TextView mBatteryPercentView; private BatteryController mBatteryController; @@ -72,6 +75,7 @@ public class BatteryMeterView extends LinearLayout implements private int mLightModeBackgroundColor; private int mLightModeFillColor; private float mDarkIntensity; + private int mUser; public BatteryMeterView(Context context) { this(context, null, 0); @@ -120,6 +124,16 @@ public class BatteryMeterView extends LinearLayout implements // Init to not dark at all. onDarkChanged(new Rect(), 0, DarkIconDispatcher.DEFAULT_ICON_TINT); + mUserTracker = new CurrentUserTracker(mContext) { + @Override + public void onUserSwitched(int newUserId) { + mUser = newUserId; + getContext().getContentResolver().unregisterContentObserver(mSettingObserver); + getContext().getContentResolver().registerContentObserver( + Settings.System.getUriFor(SHOW_BATTERY_PERCENT), false, mSettingObserver, + newUserId); + } + }; } public void setForceShowPercent(boolean show) { @@ -145,16 +159,19 @@ public class BatteryMeterView extends LinearLayout implements super.onAttachedToWindow(); mBatteryController = Dependency.get(BatteryController.class); mBatteryController.addCallback(this); + mUser = ActivityManager.getCurrentUser(); getContext().getContentResolver().registerContentObserver( - Settings.System.getUriFor(SHOW_BATTERY_PERCENT), false, mSettingObserver); + Settings.System.getUriFor(SHOW_BATTERY_PERCENT), false, mSettingObserver, mUser); updateShowPercent(); Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_BLACKLIST); Dependency.get(ConfigurationController.class).addCallback(this); + mUserTracker.startTracking(); } @Override public void onDetachedFromWindow() { super.onDetachedFromWindow(); + mUserTracker.stopTracking(); mBatteryController.removeCallback(this); getContext().getContentResolver().unregisterContentObserver(mSettingObserver); Dependency.get(TunerService.class).removeTunable(this); @@ -191,8 +208,8 @@ public class BatteryMeterView extends LinearLayout implements private void updateShowPercent() { final boolean showing = mBatteryPercentView != null; - if (0 != Settings.System.getInt(getContext().getContentResolver(), - SHOW_BATTERY_PERCENT, 0) || mForceShowPercent) { + if (0 != Settings.System.getIntForUser(getContext().getContentResolver(), + SHOW_BATTERY_PERCENT, 0, mUser) || mForceShowPercent) { if (!showing) { mBatteryPercentView = loadPercentView(); if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor); diff --git a/packages/SystemUI/src/com/android/systemui/ChargingView.java b/packages/SystemUI/src/com/android/systemui/ChargingView.java index 555cc740c373..33f8b069b751 100644 --- a/packages/SystemUI/src/com/android/systemui/ChargingView.java +++ b/packages/SystemUI/src/com/android/systemui/ChargingView.java @@ -19,9 +19,11 @@ package com.android.systemui; import android.annotation.Nullable; import android.content.Context; import android.content.res.TypedArray; +import android.os.UserHandle; import android.util.AttributeSet; import android.widget.ImageView; +import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -34,14 +36,28 @@ public class ChargingView extends ImageView implements BatteryController.BatteryStateChangeCallback, ConfigurationController.ConfigurationListener { + private static final long CHARGING_INDICATION_DELAY_MS = 1000; + + private final AmbientDisplayConfiguration mConfig; + private final Runnable mClearSuppressCharging = this::clearSuppressCharging; private BatteryController mBatteryController; private int mImageResource; private boolean mCharging; private boolean mDark; + private boolean mSuppressCharging; + + + private void clearSuppressCharging() { + mSuppressCharging = false; + removeCallbacks(mClearSuppressCharging); + updateVisibility(); + } public ChargingView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); + mConfig = new AmbientDisplayConfiguration(context); + TypedArray a = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.src}); int srcResId = a.getResourceId(0, 0); @@ -67,14 +83,30 @@ public class ChargingView extends ImageView implements super.onDetachedFromWindow(); mBatteryController.removeCallback(this); Dependency.get(ConfigurationController.class).removeCallback(this); + removeCallbacks(mClearSuppressCharging); } @Override public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { + boolean startCharging = charging && !mCharging; + if (startCharging && deviceWillWakeUpWhenPluggedIn() && mDark) { + // We're about to wake up, and thus don't want to show the indicator just for it to be + // hidden again. + clearSuppressCharging(); + mSuppressCharging = true; + postDelayed(mClearSuppressCharging, CHARGING_INDICATION_DELAY_MS); + } mCharging = charging; updateVisibility(); } + private boolean deviceWillWakeUpWhenPluggedIn() { + boolean plugTurnsOnScreen = getResources().getBoolean( + com.android.internal.R.bool.config_unplugTurnsOnScreen); + boolean aod = mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT); + return !aod && plugTurnsOnScreen; + } + @Override public void onDensityOrFontScaleChanged() { setImageResource(mImageResource); @@ -82,10 +114,13 @@ public class ChargingView extends ImageView implements public void setDark(boolean dark) { mDark = dark; + if (!dark) { + clearSuppressCharging(); + } updateVisibility(); } private void updateVisibility() { - setVisibility(mCharging && mDark ? VISIBLE : INVISIBLE); + setVisibility(mCharging && !mSuppressCharging && mDark ? VISIBLE : INVISIBLE); } } diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java index ecc211136667..49253ec536cd 100644 --- a/packages/SystemUI/src/com/android/systemui/Dependency.java +++ b/packages/SystemUI/src/com/android/systemui/Dependency.java @@ -34,7 +34,6 @@ import com.android.systemui.fragments.FragmentService; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.plugins.ActivityStarter; -import com.android.systemui.plugins.PluginActivityManager; import com.android.systemui.plugins.PluginDependencyProvider; import com.android.systemui.plugins.PluginManager; import com.android.systemui.plugins.PluginManagerImpl; @@ -295,8 +294,6 @@ public class Dependency extends SystemUI { mProviders.put(UiOffloadThread.class, UiOffloadThread::new); - mProviders.put(PluginActivityManager.class, - () -> new PluginActivityManager(mContext, getDependency(PluginManager.class))); mProviders.put(PowerUI.WarningsUI.class, () -> new PowerNotificationWarnings(mContext)); diff --git a/packages/SystemUI/src/com/android/systemui/DockedStackExistsListener.java b/packages/SystemUI/src/com/android/systemui/DockedStackExistsListener.java index 9fe730affbd9..81e4db3b2561 100644 --- a/packages/SystemUI/src/com/android/systemui/DockedStackExistsListener.java +++ b/packages/SystemUI/src/com/android/systemui/DockedStackExistsListener.java @@ -33,6 +33,7 @@ public class DockedStackExistsListener { private static final String TAG = "DockedStackExistsListener"; private static ArrayList<WeakReference<Consumer<Boolean>>> sCallbacks = new ArrayList<>(); + private static boolean mLastExists; static { try { @@ -73,6 +74,7 @@ public class DockedStackExistsListener { private static void onDockedStackExistsChanged(boolean exists) { + mLastExists = exists; synchronized (sCallbacks) { sCallbacks.removeIf(wf -> { Consumer<Boolean> l = wf.get(); @@ -83,6 +85,7 @@ public class DockedStackExistsListener { } public static void register(Consumer<Boolean> callback) { + callback.accept(mLastExists); synchronized (sCallbacks) { sCallbacks.add(new WeakReference<>(callback)); } diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java index e3eaadd2c66c..4b377153e558 100644 --- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java @@ -439,7 +439,12 @@ public class SwipeHelper implements Gefingerpoken { public void onAnimationEnd(Animator animation) { updateSwipeProgressFromOffset(animView, canBeDismissed); mDismissPendingMap.remove(animView); - if (!mCancelled) { + boolean wasRemoved = false; + if (animView instanceof ExpandableNotificationRow) { + ExpandableNotificationRow row = (ExpandableNotificationRow) animView; + wasRemoved = row.isRemoved(); + } + if (!mCancelled || wasRemoved) { mCallback.onChildDismissed(animView); } if (endAction != null) { diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java index d8da5ed71894..9adafda7adf5 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java @@ -16,7 +16,6 @@ package com.android.systemui; -import android.app.Activity; import android.app.ActivityThread; import android.app.Application; import android.content.BroadcastReceiver; @@ -30,10 +29,9 @@ import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; import android.util.ArraySet; -import android.util.BootTimingsTraceLog; +import android.util.TimingsTraceLog; import android.util.Log; -import com.android.systemui.fragments.FragmentService; import com.android.systemui.globalactions.GlobalActionsComponent; import com.android.systemui.keyboard.KeyboardUI; import com.android.systemui.keyguard.KeyguardViewMediator; @@ -42,7 +40,6 @@ import com.android.systemui.pip.PipUI; import com.android.systemui.plugins.GlobalActions; import com.android.systemui.plugins.OverlayPlugin; import com.android.systemui.plugins.Plugin; -import com.android.systemui.plugins.PluginActivityManager; import com.android.systemui.plugins.PluginListener; import com.android.systemui.plugins.PluginManager; import com.android.systemui.power.PowerUI; @@ -52,7 +49,6 @@ import com.android.systemui.stackdivider.Divider; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarWindowManager; -import com.android.systemui.tuner.TunerService; import com.android.systemui.usb.StorageNotification; import com.android.systemui.util.NotificationChannels; import com.android.systemui.util.leak.GarbageMonitor; @@ -194,7 +190,7 @@ public class SystemUIApplication extends Application implements SysUiServiceProv Log.v(TAG, "Starting SystemUI services for user " + Process.myUserHandle().getIdentifier() + "."); - BootTimingsTraceLog log = new BootTimingsTraceLog("SystemUIBootTiming", + TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming", Trace.TRACE_TAG_APP); log.traceBegin("StartServices"); final int N = services.length; @@ -283,10 +279,4 @@ public class SystemUIApplication extends Application implements SysUiServiceProv public SystemUI[] getServices() { return mServices; } - - @Override - public Activity instantiateActivity(ClassLoader cl, String className, Intent intent) { - if (!mServicesStarted) return null; - return Dependency.get(PluginActivityManager.class).instantiate(cl, className, intent); - } } diff --git a/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java b/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java new file mode 100644 index 000000000000..d1d180819eef --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.systemui.doze; + +import android.content.Context; +import android.content.res.Resources; +import android.provider.Settings; +import android.text.format.DateUtils; +import android.util.KeyValueListParser; +import android.util.Log; + +import com.android.systemui.R; + +import java.util.Arrays; + +/** + * Class to store the policy for AOD, which comes from + * {@link android.provider.Settings.Global} + */ +public class AlwaysOnDisplayPolicy { + public static final String TAG = "AlwaysOnDisplayPolicy"; + + static final String KEY_SCREEN_BRIGHTNESS_ARRAY = "screen_brightness_array"; + static final String KEY_DIMMING_SCRIM_ARRAY = "dimming_scrim_array"; + static final String KEY_PROX_SCREEN_OFF_DELAY_MS = "prox_screen_off_delay"; + static final String KEY_PROX_COOLDOWN_TRIGGER_MS = "prox_cooldown_trigger"; + static final String KEY_PROX_COOLDOWN_PERIOD_MS = "prox_cooldown_period"; + + /** + * Integer array to map ambient brightness type to real screen brightness. + * + * @see Settings.Global#ALWAYS_ON_DISPLAY_CONSTANTS + * @see #KEY_SCREEN_BRIGHTNESS_ARRAY + */ + public final int[] screenBrightnessArray; + + /** + * Integer array to map ambient brightness type to dimming scrim. + * + * @see Settings.Global#ALWAYS_ON_DISPLAY_CONSTANTS + * @see #KEY_DIMMING_SCRIM_ARRAY + */ + public final int[] dimmingScrimArray; + + /** + * Delay time(ms) from covering the prox to turning off the screen. + * + * @see Settings.Global#ALWAYS_ON_DISPLAY_CONSTANTS + * @see #KEY_PROX_SCREEN_OFF_DELAY_MS + */ + public final long proxScreenOffDelayMs; + + /** + * The threshold time(ms) to trigger the cooldown timer, which will + * turn off prox sensor for a period. + * + * @see Settings.Global#ALWAYS_ON_DISPLAY_CONSTANTS + * @see #KEY_PROX_COOLDOWN_TRIGGER_MS + */ + public final long proxCooldownTriggerMs; + + /** + * The period(ms) to turning off the prox sensor if + * {@link #KEY_PROX_COOLDOWN_TRIGGER_MS} is triggered. + * + * @see Settings.Global#ALWAYS_ON_DISPLAY_CONSTANTS + * @see #KEY_PROX_COOLDOWN_PERIOD_MS + */ + public final long proxCooldownPeriodMs; + + private final KeyValueListParser mParser; + + public AlwaysOnDisplayPolicy(Context context) { + final Resources resources = context.getResources(); + mParser = new KeyValueListParser(','); + + final String value = Settings.Global.getString(context.getContentResolver(), + Settings.Global.ALWAYS_ON_DISPLAY_CONSTANTS); + + try { + mParser.setString(value); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Bad AOD constants"); + } + + proxScreenOffDelayMs = mParser.getLong(KEY_PROX_SCREEN_OFF_DELAY_MS, + 10 * DateUtils.MINUTE_IN_MILLIS); + proxCooldownTriggerMs = mParser.getLong(KEY_PROX_COOLDOWN_TRIGGER_MS, + 2 * DateUtils.MINUTE_IN_MILLIS); + proxCooldownPeriodMs = mParser.getLong(KEY_PROX_COOLDOWN_PERIOD_MS, + 5 * DateUtils.MINUTE_IN_MILLIS); + screenBrightnessArray = parseIntArray(KEY_SCREEN_BRIGHTNESS_ARRAY, + resources.getIntArray(R.array.config_doze_brightness_sensor_to_brightness)); + dimmingScrimArray = parseIntArray(KEY_DIMMING_SCRIM_ARRAY, + resources.getIntArray(R.array.config_doze_brightness_sensor_to_scrim_opacity)); + } + + private int[] parseIntArray(final String key, final int[] defaultArray) { + final String value = mParser.getString(key, null); + if (value != null) { + return Arrays.stream(value.split(":")).map(String::trim).mapToInt( + Integer::parseInt).toArray(); + } else { + return defaultArray; + } + } + +} diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java index d374d68a456b..6f8bcff16a83 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java @@ -59,7 +59,7 @@ public class DozeFactory { DozeMachine machine = new DozeMachine(wrappedService, config, wakeLock); machine.setParts(new DozeMachine.Part[]{ - new DozePauser(handler, machine, alarmManager), + new DozePauser(handler, machine, alarmManager, new AlwaysOnDisplayPolicy(context)), new DozeFalsingManagerAdapter(FalsingManager.getInstance(context)), createDozeTriggers(context, sensorManager, host, alarmManager, config, params, handler, wakeLock, machine), @@ -76,7 +76,8 @@ public class DozeFactory { Handler handler) { Sensor sensor = DozeSensors.findSensorWithType(sensorManager, context.getString(R.string.doze_brightness_sensor_type)); - return new DozeScreenBrightness(context, service, sensorManager, sensor, host, handler); + return new DozeScreenBrightness(context, service, sensorManager, sensor, host, handler, + new AlwaysOnDisplayPolicy(context)); } private DozeTriggers createDozeTriggers(Context context, SensorManager sensorManager, diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozePauser.java b/packages/SystemUI/src/com/android/systemui/doze/DozePauser.java index a33b454c6430..76a190213ba3 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozePauser.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozePauser.java @@ -26,20 +26,22 @@ import com.android.systemui.util.AlarmTimeout; */ public class DozePauser implements DozeMachine.Part { public static final String TAG = DozePauser.class.getSimpleName(); - private static final long TIMEOUT = 10 * 1000; private final AlarmTimeout mPauseTimeout; private final DozeMachine mMachine; + private final long mTimeoutMs; - public DozePauser(Handler handler, DozeMachine machine, AlarmManager alarmManager) { + public DozePauser(Handler handler, DozeMachine machine, AlarmManager alarmManager, + AlwaysOnDisplayPolicy policy) { mMachine = machine; mPauseTimeout = new AlarmTimeout(alarmManager, this::onTimeout, TAG, handler); + mTimeoutMs = policy.proxScreenOffDelayMs; } @Override public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) { switch (newState) { case DOZE_AOD_PAUSING: - mPauseTimeout.schedule(TIMEOUT, AlarmTimeout.MODE_IGNORE_IF_SCHEDULED); + mPauseTimeout.schedule(mTimeoutMs, AlarmTimeout.MODE_IGNORE_IF_SCHEDULED); break; default: mPauseTimeout.cancel(); diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java index 30420529df56..11b4b0ef8294 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java @@ -42,7 +42,7 @@ public class DozeScreenBrightness implements DozeMachine.Part, SensorEventListen public DozeScreenBrightness(Context context, DozeMachine.Service service, SensorManager sensorManager, Sensor lightSensor, DozeHost host, - Handler handler) { + Handler handler, AlwaysOnDisplayPolicy policy) { mContext = context; mDozeService = service; mSensorManager = sensorManager; @@ -50,10 +50,8 @@ public class DozeScreenBrightness implements DozeMachine.Part, SensorEventListen mDozeHost = host; mHandler = handler; - mSensorToBrightness = context.getResources().getIntArray( - R.array.config_doze_brightness_sensor_to_brightness); - mSensorToScrimOpacity = context.getResources().getIntArray( - R.array.config_doze_brightness_sensor_to_scrim_opacity); + mSensorToBrightness = policy.screenBrightnessArray; + mSensorToScrimOpacity = policy.dimmingScrimArray; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java index 63f5d97542f6..02a725df303c 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java @@ -36,10 +36,21 @@ public class DozeScreenState implements DozeMachine.Part { @Override public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) { int screenState = newState.screenState(); + + if (newState == DozeMachine.State.FINISH) { + // Make sure not to apply the screen state after DozeService was destroyed. + mPendingScreenState = Display.STATE_UNKNOWN; + mHandler.removeCallbacks(mApplyPendingScreenState); + + applyScreenState(screenState); + return; + } + if (screenState == Display.STATE_UNKNOWN) { // We'll keep it in the existing state return; } + boolean messagePending = mHandler.hasCallbacks(mApplyPendingScreenState); if (messagePending || oldState == DozeMachine.State.INITIALIZED) { // During initialization, we hide the navigation bar. That is however only applied after diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index 566353c74b57..91cde378c41b 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -72,7 +72,7 @@ public class DozeSensors { public DozeSensors(Context context, AlarmManager alarmManager, SensorManager sensorManager, DozeParameters dozeParameters, AmbientDisplayConfiguration config, WakeLock wakeLock, Callback callback, - Consumer<Boolean> proxCallback) { + Consumer<Boolean> proxCallback, AlwaysOnDisplayPolicy policy) { mContext = context; mAlarmManager = alarmManager; mSensorManager = sensorManager; @@ -112,7 +112,7 @@ public class DozeSensors { true /* touchscreen */), }; - mProxSensor = new ProxSensor(); + mProxSensor = new ProxSensor(policy); mCallback = callback; } @@ -206,17 +206,16 @@ public class DozeSensors { private class ProxSensor implements SensorEventListener { - static final long COOLDOWN_TRIGGER = 2 * 1000; - static final long COOLDOWN_PERIOD = 5 * 1000; - boolean mRequested; boolean mRegistered; Boolean mCurrentlyFar; long mLastNear; final AlarmTimeout mCooldownTimer; + final AlwaysOnDisplayPolicy mPolicy; - public ProxSensor() { + public ProxSensor(AlwaysOnDisplayPolicy policy) { + mPolicy = policy; mCooldownTimer = new AlarmTimeout(mAlarmManager, this::updateRegistered, "prox_cooldown", mHandler); } @@ -264,11 +263,12 @@ public class DozeSensors { // Sensor has been unregistered by the proxCallback. Do nothing. } else if (!mCurrentlyFar) { mLastNear = now; - } else if (mCurrentlyFar && now - mLastNear < COOLDOWN_TRIGGER) { + } else if (mCurrentlyFar && now - mLastNear < mPolicy.proxCooldownTriggerMs) { // If the last near was very recent, we might be using more power for prox // wakeups than we're saving from turning of the screen. Instead, turn it off // for a while. - mCooldownTimer.schedule(COOLDOWN_PERIOD, AlarmTimeout.MODE_IGNORE_IF_SCHEDULED); + mCooldownTimer.schedule(mPolicy.proxCooldownPeriodMs, + AlarmTimeout.MODE_IGNORE_IF_SCHEDULED); updateRegistered(); } } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index 45831601a0f2..f7a258a2c959 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java @@ -84,7 +84,8 @@ public class DozeTriggers implements DozeMachine.Part { mWakeLock = wakeLock; mAllowPulseTriggers = allowPulseTriggers; mDozeSensors = new DozeSensors(context, alarmManager, mSensorManager, dozeParameters, - config, wakeLock, this::onSensor, this::onProximityFar); + config, wakeLock, this::onSensor, this::onProximityFar, + new AlwaysOnDisplayPolicy(context)); mUiModeManager = mContext.getSystemService(UiModeManager.class); } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java index 9b4832097528..8ddd8882788b 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java @@ -31,7 +31,6 @@ import android.content.res.Resources; import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; -import android.graphics.RectF; import android.os.Handler; import android.os.RemoteException; import android.util.Log; @@ -47,10 +46,8 @@ import android.view.accessibility.AccessibilityWindowInfo; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.policy.PipSnapAlgorithm; -import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.statusbar.FlingAnimationUtils; -import com.android.systemui.tuner.TunerService; import java.io.PrintWriter; @@ -90,6 +87,8 @@ public class PipTouchHandler { // The current movement bounds private Rect mMovementBounds = new Rect(); + // The reference inset bounds, used to determine the dismiss fraction + private Rect mInsetBounds = new Rect(); // The reference bounds used to calculate the normal/expanded target bounds private Rect mNormalBounds = new Rect(); private Rect mNormalMovementBounds = new Rect(); @@ -311,6 +310,7 @@ public class PipTouchHandler { mNormalMovementBounds = normalMovementBounds; mExpandedMovementBounds = expandedMovementBounds; mDisplayRotation = displayRotation; + mInsetBounds.set(insetBounds); updateMovementBounds(mMenuState); // If we have a deferred resize, apply it now @@ -385,7 +385,7 @@ public class PipTouchHandler { } case MotionEvent.ACTION_HOVER_ENTER: case MotionEvent.ACTION_HOVER_MOVE: { - if (!mSendingHoverAccessibilityEvents) { + if (mAccessibilityManager.isEnabled() && !mSendingHoverAccessibilityEvents) { AccessibilityEvent event = AccessibilityEvent.obtain( AccessibilityEvent.TYPE_VIEW_HOVER_ENTER); event.setImportantForAccessibility(true); @@ -398,7 +398,7 @@ public class PipTouchHandler { break; } case MotionEvent.ACTION_HOVER_EXIT: { - if (mSendingHoverAccessibilityEvents) { + if (mAccessibilityManager.isEnabled() && mSendingHoverAccessibilityEvents) { AccessibilityEvent event = AccessibilityEvent.obtain( AccessibilityEvent.TYPE_VIEW_HOVER_EXIT); event.setImportantForAccessibility(true); @@ -418,9 +418,12 @@ public class PipTouchHandler { * Updates the appearance of the menu and scrim on top of the PiP while dismissing. */ private void updateDismissFraction() { - if (mMenuController != null) { + // Skip updating the dismiss fraction when the IME is showing. This is to work around an + // issue where starting the menu activity for the dismiss overlay will steal the window + // focus, which closes the IME. + if (mMenuController != null && !mIsImeShowing) { Rect bounds = mMotionHelper.getBounds(); - final float target = mMovementBounds.bottom + bounds.height(); + final float target = mInsetBounds.bottom; float fraction = 0f; if (bounds.bottom > target) { final float distance = bounds.bottom - target; diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java index ca58080c0260..e8c129521010 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java @@ -127,6 +127,10 @@ public class PipManager implements BasePipManager { private PipNotification mPipNotification; private ParceledListSlice mCustomActions; + // Keeps track of the IME visibility to adjust the PiP when the IME is visible + private boolean mImeVisible; + private int mImeHeightAdjustment; + private final PinnedStackListener mPinnedStackListener = new PinnedStackListener(); private final Runnable mResizePinnedStackRunnable = new Runnable() { @@ -175,7 +179,22 @@ public class PipManager implements BasePipManager { public void onListenerRegistered(IPinnedStackController controller) {} @Override - public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {} + public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { + if (mState == STATE_PIP) { + if (mImeVisible != imeVisible) { + if (imeVisible) { + // Save the IME height adjustment, and offset to not occlude the IME + mPipBounds.offset(0, -imeHeight); + mImeHeightAdjustment = imeHeight; + } else { + // Apply the inverse adjustment when the IME is hidden + mPipBounds.offset(0, mImeHeightAdjustment); + } + mImeVisible = imeVisible; + resizePinnedStack(STATE_PIP); + } + } + } @Override public void onMinimizedStateChanged(boolean isMinimized) {} diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginActivityManager.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginActivityManager.java deleted file mode 100644 index 9becc38d760e..000000000000 --- a/packages/SystemUI/src/com/android/systemui/plugins/PluginActivityManager.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package com.android.systemui.plugins; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.text.TextUtils; -import android.util.ArrayMap; - -public class PluginActivityManager { - - private final Context mContext; - private final PluginManager mPluginManager; - private final ArrayMap<String, String> mActionLookup = new ArrayMap<>(); - - public PluginActivityManager(Context context, PluginManager pluginManager) { - mContext = context; - mPluginManager = pluginManager; - } - - public void addActivityPlugin(String className, String action) { - mActionLookup.put(className, action); - } - - public Activity instantiate(ClassLoader cl, String className, Intent intent) { - String action = mActionLookup.get(className); - if (TextUtils.isEmpty(action)) return null; - return mPluginManager.getOneShotPlugin(action, PluginActivity.class); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java index f66331525ab7..82c0128c10c0 100644 --- a/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java +++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java @@ -136,11 +136,12 @@ public class PluginInstanceManager<T extends Plugin> { return disableAny; } - public void disableAll() { + public boolean disableAll() { ArrayList<PluginInfo> plugins = new ArrayList<>(mPluginHandler.mPlugins); for (int i = 0; i < plugins.size(); i++) { disable(plugins.get(i)); } + return plugins.size() != 0; } private void disable(PluginInfo info) { @@ -182,6 +183,7 @@ public class PluginInstanceManager<T extends Plugin> { if (DEBUG) Log.d(TAG, "onPluginConnected"); PluginPrefs.setHasPlugins(mContext); PluginInfo<T> info = (PluginInfo<T>) msg.obj; + mManager.handleWtfs(); if (!(msg.obj instanceof PluginFragment)) { // Only call onDestroy for plugins that aren't fragments, as fragments // will get the onCreate as part of the fragment lifecycle. diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginManagerImpl.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginManagerImpl.java index a96839943cad..03747d50a6fa 100644 --- a/packages/SystemUI/src/com/android/systemui/plugins/PluginManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginManagerImpl.java @@ -36,12 +36,16 @@ import android.os.UserHandle; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.Log; +import android.util.Log.TerribleFailure; +import android.util.Log.TerribleFailureHandler; import android.widget.Toast; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.systemui.Dependency; import com.android.systemui.plugins.PluginInstanceManager.PluginContextWrapper; +import com.android.systemui.plugins.PluginInstanceManager.PluginInfo; import com.android.systemui.plugins.annotations.ProvidesInterface; import dalvik.system.PathClassLoader; @@ -70,10 +74,11 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage private boolean mListening; private boolean mHasOneShot; private Looper mLooper; + private boolean mWtfsSet; public PluginManagerImpl(Context context) { this(context, new PluginInstanceManagerFactory(), - Build.IS_DEBUGGABLE, Thread.getDefaultUncaughtExceptionHandler()); + Build.IS_DEBUGGABLE, Thread.getUncaughtExceptionPreHandler()); } @VisibleForTesting @@ -87,7 +92,7 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage PluginExceptionHandler uncaughtExceptionHandler = new PluginExceptionHandler( defaultHandler); - Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler); + Thread.setUncaughtExceptionPreHandler(uncaughtExceptionHandler); if (isDebuggable) { new Handler(mLooper).post(() -> { // Plugin dependencies that don't have another good home can go here, but @@ -119,21 +124,14 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage } PluginInstanceManager<T> p = mFactory.createPluginInstanceManager(mContext, action, null, false, mLooper, cls, this); - PluginListener<Plugin> listener = new PluginListener<Plugin>() { - @Override - public void onPluginConnected(Plugin plugin, Context pluginContext) { } - }; - mPluginMap.put(listener, p); mPluginPrefs.addAction(action); - PluginInstanceManager.PluginInfo<T> info = p.getPlugin(); + PluginInfo<T> info = p.getPlugin(); if (info != null) { mOneShotPackages.add(info.mPackage); mHasOneShot = true; startListening(); - mPluginMap.remove(listener); return info.mPlugin; } - mPluginMap.remove(listener); return null; } @@ -296,6 +294,15 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage return false; } + public void handleWtfs() { + if (!mWtfsSet) { + mWtfsSet = true; + Log.setWtfHandler((tag, what, system) -> { + throw new CrashWhilePluginActiveException(what); + }); + } + } + @VisibleForTesting public static class PluginInstanceManagerFactory { public <T extends Plugin> PluginInstanceManager createPluginInstanceManager(Context context, @@ -345,9 +352,12 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage // disable all the plugins, so we can be sure that SysUI is running as // best as possible. for (PluginInstanceManager manager : mPluginMap.values()) { - manager.disableAll(); + disabledAny |= manager.disableAll(); } } + if (disabledAny) { + throwable = new CrashWhilePluginActiveException(throwable); + } // Run the normal exception handler so we can crash and cleanup our state. mHandler.uncaughtException(thread, throwable); @@ -364,4 +374,10 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage return disabledAny | checkStack(throwable.getCause()); } } + + private class CrashWhilePluginActiveException extends RuntimeException { + public CrashWhilePluginActiveException(Throwable throwable) { + super(throwable); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java index 10514a7f0c7f..8b434a546504 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java @@ -323,7 +323,7 @@ public class QSDetail extends LinearLayout { post(new Runnable() { @Override public void run() { - handleShowingDetail(detail, x, y, true /* toggleQs */); + handleShowingDetail(detail, x, y, false /* toggleQs */); } }); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java index f91aa9a6d0b0..b4cc4b1586a2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java @@ -184,7 +184,11 @@ public class QSDetailItems extends FrameLayout { } view.setVisibility(mItemsVisible ? VISIBLE : INVISIBLE); final ImageView iv = (ImageView) view.findViewById(android.R.id.icon); - iv.setImageResource(item.icon); + if (item.iconDrawable != null) { + iv.setImageDrawable(item.iconDrawable); + } else { + iv.setImageResource(item.icon); + } iv.getOverlay().clear(); if (item.overlay != null) { item.overlay.setBounds(0, 0, mQsDetailIconOverlaySize, mQsDetailIconOverlaySize); @@ -254,6 +258,7 @@ public class QSDetailItems extends FrameLayout { public static class Item { public int icon; + public Drawable iconDrawable; public Drawable overlay; public CharSequence line1; public CharSequence line2; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java index 9eb29f8bfae8..3aa78676d755 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java @@ -45,6 +45,7 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; import com.android.keyguard.KeyguardStatusView; import com.android.settingslib.Utils; +import com.android.settingslib.drawable.UserIconDrawable; import com.android.systemui.Dependency; import com.android.systemui.FontSizeUtils; import com.android.systemui.R; @@ -404,8 +405,9 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, @Override public void onUserInfoChanged(String name, Drawable picture, String userAccount) { if (picture != null && - UserManager.get(mContext).isGuestUser(ActivityManager.getCurrentUser())) { - picture = picture.getConstantState().newDrawable().mutate(); + UserManager.get(mContext).isGuestUser(ActivityManager.getCurrentUser()) && + !(picture instanceof UserIconDrawable)) { + picture = picture.getConstantState().newDrawable(mContext.getResources()).mutate(); picture.setColorFilter( Utils.getColorAttr(mContext, android.R.attr.colorForeground), Mode.SRC_IN); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java index e574c01dd077..a48bcbd1f840 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java @@ -310,11 +310,47 @@ public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClic vpnWarning.setMovementMethod(new LinkMovementMethod()); } + // Note: if a new section is added, should update configSubtitleVisibility to include + // the handling of the subtitle + configSubtitleVisibility(managementMessage != null, + caCertsMessage != null, + networkLoggingMessage != null, + vpnMessage != null, + dialogView); + mDialog.show(); mDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); } + protected void configSubtitleVisibility(boolean showDeviceManagement, boolean showCaCerts, + boolean showNetworkLogging, boolean showVpn, View dialogView) { + // Device Management title should always been shown + // When there is a Device Management message, all subtitles should be shown + if (showDeviceManagement) { + return; + } + // Hide the subtitle if there is only 1 message shown + int mSectionCountExcludingDeviceMgt = 0; + if (showCaCerts) { mSectionCountExcludingDeviceMgt++; } + if (showNetworkLogging) { mSectionCountExcludingDeviceMgt++; } + if (showVpn) { mSectionCountExcludingDeviceMgt++; } + + // No work needed if there is no sections or more than 1 section + if (mSectionCountExcludingDeviceMgt != 1) { + return; + } + if (showCaCerts) { + dialogView.findViewById(R.id.ca_certs_subtitle).setVisibility(View.GONE); + } + if (showNetworkLogging) { + dialogView.findViewById(R.id.network_logging_subtitle).setVisibility(View.GONE); + } + if (showVpn) { + dialogView.findViewById(R.id.vpn_subtitle).setVisibility(View.GONE); + } + } + private String getSettingsButton() { return mContext.getString(R.string.monitoring_button_view_policies); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSDetail.java deleted file mode 100644 index 1fc6bf4840df..000000000000 --- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSDetail.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package com.android.systemui.qs.car; - -import android.annotation.Nullable; -import android.content.Context; -import android.content.res.Configuration; -import android.util.AttributeSet; -import android.util.SparseArray; -import android.view.View; -import android.widget.FrameLayout; - -import com.android.internal.logging.MetricsLogger; -import com.android.systemui.Dependency; -import com.android.systemui.plugins.qs.DetailAdapter; -import com.android.systemui.qs.QSDetail; -import com.android.systemui.qs.QSPanel; - -/** - * The detail view that displays below the status bar header in the auto use-case. This view - * additional details of quick settings options, such as for showing the users when user switcher - * has been selected. - */ -public class CarQSDetail extends FrameLayout { - - private final SparseArray<View> mDetailViews = new SparseArray<>(); - - private DetailAdapter mDetailAdapter; - - public CarQSDetail(Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - - for (int i = 0; i < mDetailViews.size(); i++) { - mDetailViews.valueAt(i).dispatchConfigurationChanged(newConfig); - } - } - - public void setQsPanel(QSPanel panel) { - panel.setCallback(mQsPanelCallback); - } - - public boolean isShowingDetail() { - return mDetailAdapter != null; - } - - public void handleShowingDetail(@Nullable DetailAdapter adapter) { - boolean showingDetail = adapter != null; - setClickable(showingDetail); - - // If it's already in the right state (not showing or already showing the right adapter), - // then no need to change. - if ((mDetailAdapter == null && adapter == null) || mDetailAdapter == adapter) { - return; - } - - if (showingDetail) { - int viewCacheIndex = adapter.getMetricsCategory(); - View detailView = adapter.createDetailView(mContext, mDetailViews.get(viewCacheIndex), - this); - if (detailView == null) { - throw new IllegalStateException("Must return detail view"); - } - - removeAllViews(); - addView(detailView); - mDetailViews.put(viewCacheIndex, detailView); - Dependency.get(MetricsLogger.class).visible(adapter.getMetricsCategory()); - mDetailAdapter = adapter; - setVisibility(View.VISIBLE); - } else { - if (mDetailAdapter != null) { - Dependency.get(MetricsLogger.class).hidden(mDetailAdapter.getMetricsCategory()); - } - mDetailAdapter = null; - setVisibility(View.GONE); - } - } - - private QSDetail.Callback mQsPanelCallback = new QSDetail.Callback() { - @Override - public void onToggleStateChanged(final boolean state) { - } - - @Override - public void onShowingDetail(final DetailAdapter detail, final int x, final int y) { - post(() -> handleShowingDetail(detail)); - } - - @Override - public void onScanStateChanged(final boolean state) { - } - }; -} diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java index ab79646d240b..d42b87bcef28 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java @@ -28,6 +28,7 @@ import com.android.systemui.R; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.qs.QSFooter; import com.android.systemui.qs.QSPanel; +import com.android.systemui.statusbar.car.UserGridView; import com.android.systemui.statusbar.phone.MultiUserSwitch; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.UserInfoController; @@ -44,9 +45,7 @@ public class CarQSFooter extends RelativeLayout implements QSFooter, private MultiUserSwitch mMultiUserSwitch; private ImageView mMultiUserAvatar; - - private CarQSDetail mQsDetail; - private QSPanel mQsPanel; + private UserGridView mUserGridView; public CarQSFooter(Context context, AttributeSet attrs) { super(context, attrs); @@ -61,17 +60,15 @@ public class CarQSFooter extends RelativeLayout implements QSFooter, mUserInfoController = Dependency.get(UserInfoController.class); mMultiUserSwitch.setOnClickListener(v -> { - if (mQsDetail == null || mQsPanel == null) { + if (mUserGridView == null) { Log.e(TAG, "CarQSFooter not properly set up; cannot display user switcher."); return; } - // MultiUserSwitch.onClick() shows the detail, but does not close the detail, so need - // to use the detail's showing state to determine the correct action. - if (mQsDetail.isShowingDetail()) { - mQsPanel.closeDetail(); + if (!mUserGridView.isShowing()) { + mUserGridView.show(); } else { - mMultiUserSwitch.onClick(v); + mUserGridView.hide(); } }); @@ -94,22 +91,15 @@ public class CarQSFooter extends RelativeLayout implements QSFooter, mMultiUserAvatar.setImageDrawable(picture); } - /** - * Needed for setup in order to allow the multi user switch to show the users. - * - * @param panel the QSPanel that listens to the user switch controller. This cannot be null - * during normal operation. - */ @Override public void setQSPanel(@Nullable QSPanel panel) { if (panel != null) { mMultiUserSwitch.setQsPanel(panel); } - mQsPanel = panel; } - public void setQSDetail(CarQSDetail detail) { - mQsDetail = detail; + public void setUserGridView(UserGridView view) { + mUserGridView = view; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java index 1605cad24e71..13298d378845 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java @@ -22,10 +22,12 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; +import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.plugins.qs.QS; import com.android.systemui.qs.QSFooter; -import com.android.systemui.qs.QSPanel; +import com.android.systemui.statusbar.car.UserGridView; +import com.android.systemui.statusbar.policy.UserSwitcherController; /** * A quick settings fragment for the car. For auto, there is no row for quick settings or ability @@ -35,8 +37,7 @@ import com.android.systemui.qs.QSPanel; public class CarQSFragment extends Fragment implements QS { private View mHeader; private CarQSFooter mFooter; - private QSPanel mQsPanel; - private CarQSDetail mQsDetail; + private UserGridView mUserGridView; @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @@ -49,13 +50,12 @@ public class CarQSFragment extends Fragment implements QS { super.onViewCreated(view, savedInstanceState); mHeader = view.findViewById(R.id.header); mFooter = view.findViewById(R.id.qs_footer); - mQsPanel = view.findViewById(R.id.quick_settings_panel); - mQsDetail = view.findViewById(R.id.qs_detail); - // Inform each other about their existence. - mQsDetail.setQsPanel(mQsPanel); - mFooter.setQSDetail(mQsDetail); - mFooter.setQSPanel(mQsPanel); + mUserGridView = view.findViewById(R.id.user_grid); + mUserGridView.init(null, Dependency.get(UserSwitcherController.class), + false /* showInitially */); + + mFooter.setUserGridView(mUserGridView); } @Override @@ -133,13 +133,13 @@ public class CarQSFragment extends Fragment implements QS { @Override public boolean isShowingDetail() { - return mQsDetail.isShowingDetail(); + // No detail panel to close. + return false; } @Override public void closeDetail() { - mQsDetail.setVisibility(View.GONE); - mQsPanel.closeDetail(); + // No detail panel to close. } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java index 0a0d2ce00a1b..bdc5e7d75b48 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java @@ -556,7 +556,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta @Override public int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder) { - if (viewHolder.getItemViewType() == TYPE_EDIT) { + if (viewHolder.getItemViewType() == TYPE_EDIT || viewHolder.getItemViewType() == TYPE_DIVIDER) { return makeMovementFlags(0, 0); } int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.RIGHT diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java index 12fccda907ff..bc6233d45a67 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java @@ -16,6 +16,8 @@ package com.android.systemui.qs.tiles; +import static com.android.settingslib.graph.BluetoothDeviceLayerDrawable.createLayerDrawable; + import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; @@ -32,8 +34,10 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settingslib.Utils; import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.graph.BluetoothDeviceLayerDrawable; import com.android.systemui.Dependency; import com.android.systemui.R; +import com.android.systemui.R.drawable; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.DetailAdapter; import com.android.systemui.plugins.qs.QSTile.BooleanState; @@ -127,6 +131,15 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { if (connected) { state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_connected); state.label = mController.getLastDeviceName(); + CachedBluetoothDevice lastDevice = mController.getLastDevice(); + if (lastDevice != null) { + int batteryLevel = lastDevice.getBatteryLevel(); + if (batteryLevel != BluetoothDevice.BATTERY_LEVEL_UNKNOWN) { + BluetoothDeviceLayerDrawable drawable = createLayerDrawable(mContext, + R.drawable.ic_qs_bluetooth_connected, batteryLevel); + state.icon = new DrawableIcon(drawable); + } + } state.contentDescription = mContext.getString( R.string.accessibility_bluetooth_name, state.label); } else if (state.isTransient) { @@ -278,6 +291,8 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { item.icon = R.drawable.ic_qs_bluetooth_connected; int batteryLevel = device.getBatteryLevel(); if (batteryLevel != BluetoothDevice.BATTERY_LEVEL_UNKNOWN) { + item.iconDrawable = createLayerDrawable(mContext, item.icon, + batteryLevel); item.line2 = mContext.getString( R.string.quick_settings_connected_battery_level, Utils.formatPercentage(batteryLevel)); diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java index d10e080a5443..3e1522d2b53c 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java +++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java @@ -43,14 +43,11 @@ import android.widget.Toast; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.systemui.Dependency; import com.android.systemui.EventLogConstants; import com.android.systemui.EventLogTags; import com.android.systemui.R; import com.android.systemui.RecentsComponent; import com.android.systemui.SystemUI; -import com.android.systemui.plugins.PluginActivity; -import com.android.systemui.plugins.PluginActivityManager; import com.android.systemui.recents.events.EventBus; import com.android.systemui.recents.events.activity.ConfigurationChangedEvent; import com.android.systemui.recents.events.activity.DockedTopTaskEvent; @@ -239,8 +236,6 @@ public class Recents extends SystemUI registerWithSystemUser(); } putComponent(Recents.class, this); - Dependency.get(PluginActivityManager.class).addActivityPlugin(RecentsImpl.RECENTS_ACTIVITY, - PluginActivity.ACTION_RECENTS); } @Override @@ -570,6 +565,13 @@ public class Recents extends SystemUI mImpl.showPrevAffiliatedTask(); } + @Override + public void appTransitionFinished() { + // Fallback, reset the flag once an app transition ends + EventBus.getDefault().send(new SetWaitingForTransitionStartEvent( + false /* waitingForTransitionStart */)); + } + /** * Updates on configuration change. */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index 585b151cd693..f8448661d799 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -69,6 +69,7 @@ import com.android.systemui.recents.events.activity.ToggleRecentsEvent; import com.android.systemui.recents.events.component.ActivityUnpinnedEvent; import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent; import com.android.systemui.recents.events.component.ScreenPinningRequestEvent; +import com.android.systemui.recents.events.component.SetWaitingForTransitionStartEvent; import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent; import com.android.systemui.recents.events.ui.DeleteTaskDataEvent; import com.android.systemui.recents.events.ui.HideIncompatibleAppOverlayEvent; @@ -366,7 +367,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD }); // Set the window background - getWindow().setBackgroundDrawable(mRecentsView.getBackgroundScrim()); + mRecentsView.updateBackgroundScrim(getWindow(), isInMultiWindowMode()); // Create the home intent runnable mHomeIntent = new Intent(Intent.ACTION_MAIN, null); @@ -517,6 +518,11 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD public void onEnterAnimationComplete() { super.onEnterAnimationComplete(); EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent()); + + // Workaround for b/64694148: The animation started callback is not made (see + // RecentsImpl.getThumbnailTransitionActivityOptions) so reset the transition-waiting state + // once the enter animation has completed. + EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(false)); } @Override @@ -550,6 +556,9 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD public void onMultiWindowModeChanged(boolean isInMultiWindowMode) { super.onMultiWindowModeChanged(isInMultiWindowMode); + // Set the window background + mRecentsView.updateBackgroundScrim(getWindow(), isInMultiWindowMode); + reloadTaskStack(isInMultiWindowMode, true /* sendConfigChangedEvent */); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index 86e93fdd63ad..aecf95fc677f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -35,6 +35,7 @@ import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.SystemClock; +import android.util.ArraySet; import android.util.Log; import android.util.MutableBoolean; import android.util.Pair; @@ -75,6 +76,7 @@ import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener; import com.android.systemui.recents.model.RecentsTaskLoadPlan; import com.android.systemui.recents.model.RecentsTaskLoader; import com.android.systemui.recents.model.Task; +import com.android.systemui.recents.model.Task.TaskKey; import com.android.systemui.recents.model.TaskGrouping; import com.android.systemui.recents.model.TaskStack; import com.android.systemui.recents.model.ThumbnailData; @@ -109,6 +111,8 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener // duration, then we will toggle recents after this duration. private final static int FAST_ALT_TAB_DELAY_MS = 225; + private final static ArraySet<TaskKey> EMPTY_SET = new ArraySet<>(); + public final static String RECENTS_PACKAGE = "com.android.systemui"; public final static String RECENTS_ACTIVITY = "com.android.systemui.recents.RecentsActivity"; @@ -128,6 +132,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener // Preloads the next task RecentsConfiguration config = Recents.getConfiguration(); if (config.svelteLevel == RecentsConfiguration.SVELTE_NONE) { + Rect windowRect = getWindowRect(null /* windowRectOverride */); + if (windowRect.isEmpty()) { + return; + } // Load the next task only if we aren't svelte SystemServicesProxy ssp = Recents.getSystemServices(); @@ -135,32 +143,31 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener RecentsTaskLoader loader = Recents.getTaskLoader(); RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext); loader.preloadTasks(plan, -1, false /* includeFrontMostExcludedTask */); + TaskStack stack = plan.getTaskStack(); + RecentsActivityLaunchState launchState = new RecentsActivityLaunchState(); + RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options(); - // This callback is made when a new activity is launched and the old one is paused - // so ignore the current activity and try and preload the thumbnail for the - // previous one. - VisibilityReport visibilityReport; - synchronized (mDummyStackView) { - mDummyStackView.getStack().removeAllTasks(false /* notifyStackChanges */); - mDummyStackView.setTasks(plan.getTaskStack(), false /* allowNotify */); - updateDummyStackViewLayout(plan.getTaskStack(), - getWindowRect(null /* windowRectOverride */)); + synchronized (mBackgroundLayoutAlgorithm) { + // This callback is made when a new activity is launched and the old one is + // paused so ignore the current activity and try and preload the thumbnail for + // the previous one. + updateDummyStackViewLayout(mBackgroundLayoutAlgorithm, stack, windowRect); // Launched from app is always the worst case (in terms of how many // thumbnails/tasks visible) - RecentsActivityLaunchState launchState = new RecentsActivityLaunchState(); launchState.launchedFromApp = true; - mDummyStackView.updateLayoutAlgorithm(true /* boundScroll */, launchState); - visibilityReport = mDummyStackView.computeStackVisibilityReport(); + mBackgroundLayoutAlgorithm.update(plan.getTaskStack(), EMPTY_SET, launchState); + VisibilityReport visibilityReport = + mBackgroundLayoutAlgorithm.computeStackVisibilityReport( + stack.getStackTasks()); + + launchOpts.runningTaskId = runningTaskInfo != null ? runningTaskInfo.id : -1; + launchOpts.numVisibleTasks = visibilityReport.numVisibleTasks; + launchOpts.numVisibleTaskThumbnails = visibilityReport.numVisibleThumbnails; + launchOpts.onlyLoadForCache = true; + launchOpts.onlyLoadPausedActivities = true; + launchOpts.loadThumbnails = true; } - - RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options(); - launchOpts.runningTaskId = runningTaskInfo != null ? runningTaskInfo.id : -1; - launchOpts.numVisibleTasks = visibilityReport.numVisibleTasks; - launchOpts.numVisibleTaskThumbnails = visibilityReport.numVisibleThumbnails; - launchOpts.onlyLoadForCache = true; - launchOpts.onlyLoadPausedActivities = true; - launchOpts.loadThumbnails = true; loader.loadTasks(mContext, plan, launchOpts); } } @@ -229,17 +236,15 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener boolean mLaunchedWhileDocking; // Task launching - Rect mTaskStackBounds = new Rect(); + Rect mTmpBounds = new Rect(); TaskViewTransform mTmpTransform = new TaskViewTransform(); - int mStatusBarHeight; - int mNavBarHeight; - int mNavBarWidth; int mTaskBarHeight; // Header (for transition) TaskViewHeader mHeaderBar; final Object mHeaderBarLock = new Object(); - protected TaskStackView mDummyStackView; + private TaskStackView mDummyStackView; + private TaskStackLayoutAlgorithm mBackgroundLayoutAlgorithm; // Variables to keep track of if we need to start recents after binding protected boolean mTriggeredFromAltTab; @@ -258,6 +263,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener public RecentsImpl(Context context) { mContext = context; mHandler = new Handler(); + mBackgroundLayoutAlgorithm = new TaskStackLayoutAlgorithm(context, null); // Initialize the static foreground thread ForegroundThread.get(); @@ -287,8 +293,9 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener public void onConfigurationChanged() { reloadResources(); - synchronized (mDummyStackView) { - mDummyStackView.reloadOnConfigurationChange(); + mDummyStackView.reloadOnConfigurationChange(); + synchronized (mBackgroundLayoutAlgorithm) { + mBackgroundLayoutAlgorithm.reloadOnConfigurationChange(mContext); } } @@ -373,6 +380,12 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } public void toggleRecents(int growTarget) { + // Skip preloading if the task is locked + SystemServicesProxy ssp = Recents.getSystemServices(); + if (ssp.isScreenPinningActive()) { + return; + } + // Skip this toggle if we are already waiting to trigger recents via alt-tab if (mFastAltTabTrigger.isDozing()) { return; @@ -388,7 +401,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener mTriggeredFromAltTab = false; try { - SystemServicesProxy ssp = Recents.getSystemServices(); MutableBoolean isHomeStackVisible = new MutableBoolean(true); long elapsedTime = SystemClock.elapsedRealtime() - mLastToggleTime; @@ -451,11 +463,16 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } public void preloadRecents() { + // Skip preloading if the task is locked + SystemServicesProxy ssp = Recents.getSystemServices(); + if (ssp.isScreenPinningActive()) { + return; + } + // Preload only the raw task list into a new load plan (which will be consumed by the // RecentsActivity) only if there is a task to animate to. Post this to ensure that we // don't block the touch feedback on the nav bar button which triggers this. mHandler.post(() -> { - SystemServicesProxy ssp = Recents.getSystemServices(); MutableBoolean isHomeStackVisible = new MutableBoolean(true); if (!ssp.isRecentsActivityVisible(isHomeStackVisible)) { ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask(); @@ -663,7 +680,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener mWaitingForTransitionStart = waitingForTransitionStart; if (!waitingForTransitionStart && mToggleFollowingTransitionStart) { - toggleRecents(DividerView.INVALID_RECENTS_GROW_TARGET); + mHandler.post(() -> toggleRecents(DividerView.INVALID_RECENTS_GROW_TARGET)); } mToggleFollowingTransitionStart = false; } @@ -697,12 +714,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener private void reloadResources() { Resources res = mContext.getResources(); - mStatusBarHeight = res.getDimensionPixelSize( - com.android.internal.R.dimen.status_bar_height); - mNavBarHeight = res.getDimensionPixelSize( - com.android.internal.R.dimen.navigation_bar_height); - mNavBarWidth = res.getDimensionPixelSize( - com.android.internal.R.dimen.navigation_bar_width); mTaskBarHeight = TaskStackLayoutAlgorithm.getDimensionForDevice(mContext, R.dimen.recents_task_view_header_height, R.dimen.recents_task_view_header_height, @@ -718,7 +729,8 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener mHeaderBar.setLayoutDirection(res.getConfiguration().getLayoutDirection()); } - private void updateDummyStackViewLayout(TaskStack stack, Rect windowRect) { + private void updateDummyStackViewLayout(TaskStackLayoutAlgorithm stackLayout, + TaskStack stack, Rect windowRect) { SystemServicesProxy ssp = Recents.getSystemServices(); Rect displayRect = ssp.getDisplayRect(); Rect systemInsets = new Rect(); @@ -734,18 +746,14 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener calculateWindowStableInsets(systemInsets, windowRect, displayRect); windowRect.offsetTo(0, 0); - synchronized (mDummyStackView) { - TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm(); - - // Rebind the header bar and draw it for the transition - stackLayout.setSystemInsets(systemInsets); - if (stack != null) { - stackLayout.getTaskStackBounds(displayRect, windowRect, systemInsets.top, - systemInsets.left, systemInsets.right, mTaskStackBounds); - stackLayout.reset(); - stackLayout.initialize(displayRect, windowRect, mTaskStackBounds, - TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack)); - } + // Rebind the header bar and draw it for the transition + stackLayout.setSystemInsets(systemInsets); + if (stack != null) { + stackLayout.getTaskStackBounds(displayRect, windowRect, systemInsets.top, + systemInsets.left, systemInsets.right, mTmpBounds); + stackLayout.reset(); + stackLayout.initialize(displayRect, windowRect, mTmpBounds, + TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack)); } } @@ -767,26 +775,23 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener private void updateHeaderBarLayout(TaskStack stack, Rect windowRectOverride) { Rect windowRect = getWindowRect(windowRectOverride); int taskViewWidth = 0; - boolean useGridLayout = false; - synchronized (mDummyStackView) { - useGridLayout = mDummyStackView.useGridLayout(); - updateDummyStackViewLayout(stack, windowRect); - if (stack != null) { - TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm(); - mDummyStackView.getStack().removeAllTasks(false /* notifyStackChanges */); - mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */); - // Get the width of a task view so that we know how wide to draw the header bar. - if (useGridLayout) { - TaskGridLayoutAlgorithm gridLayout = mDummyStackView.getGridAlgorithm(); - gridLayout.initialize(windowRect); - taskViewWidth = (int) gridLayout.getTransform(0 /* taskIndex */, - stack.getTaskCount(), new TaskViewTransform(), - stackLayout).rect.width(); - } else { - Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds(); - if (!taskViewBounds.isEmpty()) { - taskViewWidth = taskViewBounds.width(); - } + boolean useGridLayout = mDummyStackView.useGridLayout(); + updateDummyStackViewLayout(mDummyStackView.getStackAlgorithm(), stack, windowRect); + if (stack != null) { + TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm(); + mDummyStackView.getStack().removeAllTasks(false /* notifyStackChanges */); + mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */); + // Get the width of a task view so that we know how wide to draw the header bar. + if (useGridLayout) { + TaskGridLayoutAlgorithm gridLayout = mDummyStackView.getGridAlgorithm(); + gridLayout.initialize(windowRect); + taskViewWidth = (int) gridLayout.getTransform(0 /* taskIndex */, + stack.getTaskCount(), new TaskViewTransform(), + stackLayout).rect.width(); + } else { + Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds(); + if (!taskViewBounds.isEmpty()) { + taskViewWidth = taskViewBounds.width(); } } } @@ -866,20 +871,15 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener private Pair<ActivityOptions, AppTransitionAnimationSpecsFuture> getThumbnailTransitionActivityOptions(ActivityManager.RunningTaskInfo runningTask, Rect windowOverrideRect) { + final boolean isLowRamDevice = Recents.getConfiguration().isLowRamDevice; if (runningTask != null && runningTask.stackId == FREEFORM_WORKSPACE_STACK_ID) { ArrayList<AppTransitionAnimationSpec> specs = new ArrayList<>(); - ArrayList<Task> tasks; - TaskStackLayoutAlgorithm stackLayout; - TaskStackViewScroller stackScroller; - - synchronized (mDummyStackView) { - tasks = mDummyStackView.getStack().getStackTasks(); - stackLayout = mDummyStackView.getStackAlgorithm(); - stackScroller = mDummyStackView.getScroller(); + ArrayList<Task> tasks = mDummyStackView.getStack().getStackTasks(); + TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm(); + TaskStackViewScroller stackScroller = mDummyStackView.getScroller(); - mDummyStackView.updateLayoutAlgorithm(true /* boundScroll */); - mDummyStackView.updateToInitialState(); - } + mDummyStackView.updateLayoutAlgorithm(true /* boundScroll */); + mDummyStackView.updateToInitialState(); for (int i = tasks.size() - 1; i >= 0; i--) { Task task = tasks.get(i); @@ -896,8 +896,11 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener AppTransitionAnimationSpec[] specsArray = new AppTransitionAnimationSpec[specs.size()]; specs.toArray(specsArray); + // For low end ram devices, wait for transition flag is reset when Recents entrance + // animation is complete instead of when the transition animation starts return new Pair<>(ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView, - specsArray, mHandler, mResetToggleFlagListener, this), null); + specsArray, mHandler, isLowRamDevice ? null : mResetToggleFlagListener, this), + null); } else { // Update the destination rect Task toTask = new Task(); @@ -916,9 +919,11 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener toTask.key.id, thumbnail, rect)); }); + // For low end ram devices, wait for transition flag is reset when Recents entrance + // animation is complete instead of when the transition animation starts return new Pair<>(ActivityOptions.makeMultiThumbFutureAspectScaleAnimation(mContext, - mHandler, future.getFuture(), mResetToggleFlagListener, false /* scaleUp */), - future); + mHandler, future.getFuture(), isLowRamDevice ? null : mResetToggleFlagListener, + false /* scaleUp */), future); } } @@ -1037,10 +1042,8 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener updateHeaderBarLayout(stack, windowOverrideRect); // Prepare the dummy stack for the transition - TaskStackLayoutAlgorithm.VisibilityReport stackVr; - synchronized (mDummyStackView) { - stackVr = mDummyStackView.computeStackVisibilityReport(); - } + TaskStackLayoutAlgorithm.VisibilityReport stackVr = + mDummyStackView.computeStackVisibilityReport(); // Update the remaining launch state launchState.launchedNumVisibleTasks = stackVr.numVisibleTasks; diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java index c66b2dd8eec5..717778228989 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -47,7 +47,6 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.Paint; import android.graphics.Point; import android.graphics.PorterDuff; @@ -59,7 +58,6 @@ import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.IRemoteCallback; import android.os.Message; -import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; @@ -95,9 +93,7 @@ import com.android.systemui.recents.RecentsImpl; import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.ThumbnailData; import com.android.systemui.statusbar.policy.UserInfoController; -import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener; -import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; @@ -717,21 +713,7 @@ public class SystemServicesProxy { return thumbnailData; } - ThumbnailData thumbnailData = getThumbnail(taskId, reduced); - if (thumbnailData.thumbnail != null && !ActivityManager.ENABLE_TASK_SNAPSHOTS) { - thumbnailData.thumbnail.setHasAlpha(false); - // We use a dumb heuristic for now, if the thumbnail is purely transparent in the top - // left pixel, then assume the whole thumbnail is transparent. Generally, proper - // screenshots are always composed onto a bitmap that has no alpha. - if (Color.alpha(thumbnailData.thumbnail.getPixel(0, 0)) == 0) { - mBgProtectionCanvas.setBitmap(thumbnailData.thumbnail); - mBgProtectionCanvas.drawRect(0, 0, thumbnailData.thumbnail.getWidth(), - thumbnailData.thumbnail.getHeight(), mBgProtectionPaint); - mBgProtectionCanvas.setBitmap(null); - Log.e(TAG, "Invalid screenshot detected from getTaskThumbnail()"); - } - } - return thumbnailData; + return getThumbnail(taskId, reduced); } /** @@ -742,43 +724,17 @@ public class SystemServicesProxy { return new ThumbnailData(); } - final ThumbnailData thumbnailData; - if (ActivityManager.ENABLE_TASK_SNAPSHOTS) { - ActivityManager.TaskSnapshot snapshot = null; - try { - snapshot = ActivityManager.getService().getTaskSnapshot(taskId, reducedResolution); - } catch (RemoteException e) { - Log.w(TAG, "Failed to retrieve snapshot", e); - } - if (snapshot != null) { - thumbnailData = ThumbnailData.createFromTaskSnapshot(snapshot); - } else { - return new ThumbnailData(); - } + ActivityManager.TaskSnapshot snapshot = null; + try { + snapshot = ActivityManager.getService().getTaskSnapshot(taskId, reducedResolution); + } catch (RemoteException e) { + Log.w(TAG, "Failed to retrieve snapshot", e); + } + if (snapshot != null) { + return ThumbnailData.createFromTaskSnapshot(snapshot); } else { - ActivityManager.TaskThumbnail taskThumbnail = mAm.getTaskThumbnail(taskId); - if (taskThumbnail == null) { - return new ThumbnailData(); - } - - Bitmap thumbnail = taskThumbnail.mainThumbnail; - ParcelFileDescriptor descriptor = taskThumbnail.thumbnailFileDescriptor; - if (thumbnail == null && descriptor != null) { - thumbnail = BitmapFactory.decodeFileDescriptor(descriptor.getFileDescriptor(), - null, sBitmapOptions); - } - if (descriptor != null) { - try { - descriptor.close(); - } catch (IOException e) { - } - } - thumbnailData = new ThumbnailData(); - thumbnailData.thumbnail = thumbnail; - thumbnailData.orientation = taskThumbnail.thumbnailInfo.screenOrientation; - thumbnailData.insets.setEmpty(); + return new ThumbnailData(); } - return thumbnailData; } /** diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java index 29d0a2372769..9e6bf85445a0 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java @@ -17,11 +17,9 @@ package com.android.systemui.recents.model; import android.app.ActivityManager; -import android.app.ActivityManager.TaskThumbnail; import android.content.ComponentName; import android.content.Intent; import android.content.pm.ActivityInfo; -import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.Drawable; @@ -35,7 +33,6 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Objects; - /** * A task represents the top most task in the system's task stack. */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java index dba085e37427..7998ecb4290a 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java @@ -51,7 +51,7 @@ public class AnimateableViewBounds extends ViewOutlineProvider { * Resets the right and bottom clip for this view. */ public void reset() { - mClipRect.set(-1, -1, -1, -1); + mClipRect.set(0, 0, 0, 0); updateClipBounds(); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java index 127822aec6df..b2675d7ac858 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java @@ -140,8 +140,10 @@ public class RecentsTransitionHelper { mHandler.postDelayed(mStartScreenPinningRunnable, 350); } - // Reset the state where we are waiting for the transition to start - EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(false)); + if (!Recents.getConfiguration().isLowRamDevice) { + // Reset the state where we are waiting for the transition to start + EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(false)); + } } }; } else { @@ -163,8 +165,10 @@ public class RecentsTransitionHelper { EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent()); stackView.cancelAllTaskViewAnimations(); - // Reset the state where we are waiting for the transition to start - EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(false)); + if (!Recents.getConfiguration().isLowRamDevice) { + // Reset the state where we are waiting for the transition to start + EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(false)); + } } }; } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index ccaf3cd6df52..71f06cbf6e64 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -20,13 +20,17 @@ import static android.app.ActivityManager.StackId.INVALID_STACK_ID; import android.animation.Animator; import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.animation.ValueAnimator.AnimatorUpdateListener; import android.app.ActivityOptions.OnAnimationStartedListener; import android.content.Context; import android.content.res.ColorStateList; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.util.ArraySet; import android.util.AttributeSet; @@ -37,6 +41,7 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewDebug; import android.view.ViewPropertyAnimator; +import android.view.Window; import android.view.WindowInsets; import android.widget.FrameLayout; import android.widget.TextView; @@ -117,7 +122,15 @@ public class RecentsView extends FrameLayout { private float mBusynessFactor; private GradientDrawable mBackgroundScrim; - private Animator mBackgroundScrimAnimator; + private ColorDrawable mMultiWindowBackgroundScrim; + private ValueAnimator mBackgroundScrimAnimator; + private Point mTmpDisplaySize = new Point(); + + private final AnimatorUpdateListener mUpdateBackgroundScrimAlpha = (animation) -> { + int alpha = (Integer) animation.getAnimatedValue(); + mBackgroundScrim.setAlpha(alpha); + mMultiWindowBackgroundScrim.setAlpha(alpha); + }; private RecentsTransitionHelper mTransitionHelper; @ViewDebug.ExportedProperty(deepExport=true, prefix="touch_") @@ -146,10 +159,7 @@ public class RecentsView extends FrameLayout { mTouchHandler = new RecentsViewTouchHandler(this); mFlingAnimationUtils = new FlingAnimationUtils(context, 0.3f); mBackgroundScrim = new GradientDrawable(context); - mBackgroundScrim.setCallback(this); - - boolean usingDarkText = Color.luminance( - Utils.getColorAttr(mContext, R.attr.wallpaperTextColor)) < 0.5f; + mMultiWindowBackgroundScrim = new ColorDrawable(); LayoutInflater inflater = LayoutInflater.from(context); mEmptyView = (TextView) inflater.inflate(R.layout.recents_empty, this, false); @@ -244,6 +254,7 @@ public class RecentsView extends FrameLayout { } else { mBackgroundScrim.setAlpha(0); } + mMultiWindowBackgroundScrim.setAlpha(mBackgroundScrim.getAlpha()); } } @@ -300,8 +311,14 @@ public class RecentsView extends FrameLayout { /** * Returns the window background scrim. */ - public Drawable getBackgroundScrim() { - return mBackgroundScrim; + public void updateBackgroundScrim(Window window, boolean isInMultiWindow) { + if (isInMultiWindow) { + mBackgroundScrim.setCallback(null); + window.setBackgroundDrawable(mMultiWindowBackgroundScrim); + } else { + mMultiWindowBackgroundScrim.setCallback(null); + window.setBackgroundDrawable(mBackgroundScrim); + } } /** @@ -401,6 +418,9 @@ public class RecentsView extends FrameLayout { */ public void setScrimColors(ColorExtractor.GradientColors scrimColors, boolean animated) { mBackgroundScrim.setColors(scrimColors, animated); + int alpha = mMultiWindowBackgroundScrim.getAlpha(); + mMultiWindowBackgroundScrim.setColor(scrimColors.getMainColor()); + mMultiWindowBackgroundScrim.setAlpha(alpha); } @Override @@ -470,8 +490,10 @@ public class RecentsView extends FrameLayout { // Needs to know the screen size since the gradient never scales up or down // even when bounds change. - mBackgroundScrim.setScreenSize(right - left, bottom - top); + mContext.getDisplay().getRealSize(mTmpDisplaySize); + mBackgroundScrim.setScreenSize(mTmpDisplaySize.x, mTmpDisplaySize.y); mBackgroundScrim.setBounds(left, top, right, bottom); + mMultiWindowBackgroundScrim.setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y); if (RecentsDebugFlags.Static.EnableStackActionButton) { // Layout the stack action button such that its drawable is start-aligned with the @@ -916,12 +938,12 @@ public class RecentsView extends FrameLayout { // Calculate the absolute alpha to animate from final int fromAlpha = mBackgroundScrim.getAlpha(); final int toAlpha = (int) (alpha * 255); - mBackgroundScrimAnimator = ObjectAnimator.ofInt(mBackgroundScrim, Utilities.DRAWABLE_ALPHA, - fromAlpha, toAlpha); + mBackgroundScrimAnimator = ValueAnimator.ofInt(fromAlpha, toAlpha); mBackgroundScrimAnimator.setDuration(duration); mBackgroundScrimAnimator.setInterpolator(toAlpha > fromAlpha ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT); + mBackgroundScrimAnimator.addUpdateListener(mUpdateBackgroundScrimAlpha); mBackgroundScrimAnimator.start(); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java index 6e57044467bb..81bf6affc94a 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java @@ -34,6 +34,8 @@ import com.android.systemui.recents.Recents; import com.android.systemui.recents.RecentsActivityLaunchState; import com.android.systemui.recents.RecentsConfiguration; import com.android.systemui.recents.RecentsDebugFlags; +import com.android.systemui.recents.events.EventBus; +import com.android.systemui.recents.events.component.SetWaitingForTransitionStartEvent; import com.android.systemui.recents.misc.ReferenceCountedTrigger; import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.TaskStack; @@ -241,6 +243,7 @@ public class TaskStackAnimationHelper { return; } + final boolean isLowRamDevice = Recents.getConfiguration().isLowRamDevice; int taskViewEnterFromAppDuration = res.getInteger( R.integer.recents_task_enter_from_app_duration); int taskViewEnterFromAffiliatedAppDuration = res.getInteger( @@ -248,6 +251,13 @@ public class TaskStackAnimationHelper { int dockGestureAnimDuration = appRes.getInteger( R.integer.long_press_dock_anim_duration); + // Since low ram devices have an animation when entering app -> recents, do not allow + // toggle until the animation is complete + if (launchState.launchedFromApp && !launchState.launchedViaDockGesture && isLowRamDevice) { + postAnimationTrigger.addLastDecrementRunnable(() -> EventBus.getDefault() + .send(new SetWaitingForTransitionStartEvent(false))); + } + // Create enter animations for each of the views from front to back List<TaskView> taskViews = mStackView.getTaskViews(); int taskViewCount = taskViews.size(); @@ -296,7 +306,7 @@ public class TaskStackAnimationHelper { AnimationProps taskAnimation = new AnimationProps() .setInterpolator(AnimationProps.ALPHA, ENTER_FROM_HOME_ALPHA_INTERPOLATOR) .setListener(postAnimationTrigger.decrementOnAnimationEnd()); - if (Recents.getConfiguration().isLowRamDevice) { + if (isLowRamDevice) { taskAnimation.setInterpolator(AnimationProps.BOUNDS, Interpolators.FAST_OUT_SLOW_IN) .setDuration(AnimationProps.BOUNDS, 150) diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java index d810ea4b3b1c..eaa32eefe795 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java @@ -354,7 +354,6 @@ public class TaskStackLayoutAlgorithm { TaskViewTransform mFrontOfStackTransform = new TaskViewTransform(); public TaskStackLayoutAlgorithm(Context context, TaskStackLayoutAlgorithmCallbacks cb) { - Resources res = context.getResources(); mContext = context; mCb = cb; mFreeformLayoutAlgorithm = new FreeformWorkspaceLayoutAlgorithm(context); @@ -519,7 +518,7 @@ public class TaskStackLayoutAlgorithm { * Computes the minimum and maximum scroll progress values and the progress values for each task * in the stack. */ - void update(TaskStack stack, ArraySet<Task.TaskKey> ignoreTasksSet, + public void update(TaskStack stack, ArraySet<Task.TaskKey> ignoreTasksSet, RecentsActivityLaunchState launchState) { SystemServicesProxy ssp = Recents.getSystemServices(); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java index 27cfdc133bc8..0b20b105617d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java @@ -89,6 +89,9 @@ public class TaskStackViewScroller { mContext = context; mCb = cb; mScroller = new OverScroller(context); + if (Recents.getConfiguration().isLowRamDevice) { + mScroller.setFriction(0.06f); + } mLayoutAlgorithm = layoutAlgorithm; mFlingAnimationUtils = new FlingAnimationUtils(context, 0.3f); } @@ -195,7 +198,6 @@ public class TaskStackViewScroller { return Float.compare(getScrollAmountOutOfBounds(mStackScrollP), 0f) != 0; } - /** * Scrolls the closest task and snaps into place. Only used in recents for low ram devices. * @param velocity of scroll @@ -208,19 +210,30 @@ public class TaskStackViewScroller { || stackScroll > mLayoutAlgorithm.mMaxScrollP) { return; } - TaskStackLowRamLayoutAlgorithm algorithm = mLayoutAlgorithm.mTaskStackLowRamLayoutAlgorithm; - float newScrollP = algorithm.getClosestTaskP(stackScroll, - mLayoutAlgorithm.mNumStackTasks, velocity); - float flingThreshold = ViewConfiguration.get(mContext).getScaledMinimumFlingVelocity(); + float flingThreshold = ViewConfiguration.get(mContext).getScaledMinimumFlingVelocity(); if (Math.abs(velocity) > flingThreshold) { + int minY = algorithm.percentageToScroll(mLayoutAlgorithm.mMinScrollP); + int maxY = algorithm.percentageToScroll(mLayoutAlgorithm.mMaxScrollP); + + // Calculate the fling and snap to closest task from final y position, computeScroll() + // never runs when cancelled with animateScroll() and the overscroll is not calculated + // here + fling(0 /* downScrollP */, 0 /* downY */, algorithm.percentageToScroll(stackScroll), + -velocity, minY, maxY, 0 /* overscroll */); + float pos = algorithm.scrollToPercentage(mScroller.getFinalY()); + + float newScrollP = algorithm.getClosestTaskP(pos, mLayoutAlgorithm.mNumStackTasks, + velocity); ValueAnimator animator = ObjectAnimator.ofFloat(stackScroll, newScrollP); mFlingAnimationUtils.apply(animator, algorithm.percentageToScroll(stackScroll), algorithm.percentageToScroll(newScrollP), velocity); animateScroll(newScrollP, (int) animator.getDuration(), animator.getInterpolator(), null /* postRunnable */); } else { + float newScrollP = algorithm.getClosestTaskP(stackScroll, + mLayoutAlgorithm.mNumStackTasks, velocity); animateScroll(newScrollP, 300, Interpolators.ACCELERATE_DECELERATE, null /* postRunnable */); } diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 45835d51ff90..bf98a835f104 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -596,7 +596,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, Runnable endAction = () -> { commitSnapFlags(snapTarget); mWindowManagerProxy.setResizing(false); - mDockSide = WindowManager.DOCKED_INVALID; + updateDockSide(); mCurrentAnimator = null; mEntranceAnimationRunning = false; mExitAnimationRunning = false; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index bbf9eb1499c0..634927503747 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -81,6 +81,7 @@ public class CommandQueue extends IStatusBar.Stub { private static final int MSG_SHOW_GLOBAL_ACTIONS = 34 << MSG_SHIFT; private static final int MSG_TOGGLE_PANEL = 35 << MSG_SHIFT; private static final int MSG_SHOW_SHUTDOWN_UI = 36 << MSG_SHIFT; + private static final int MSG_SET_TOP_APP_HIDES_STATUS_BAR = 37 << MSG_SHIFT; public static final int FLAG_EXCLUDE_NONE = 0; public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0; @@ -132,6 +133,7 @@ public class CommandQueue extends IStatusBar.Stub { default void startAssist(Bundle args) { } default void onCameraLaunchGestureDetected(int source) { } default void showPictureInPictureMenu() { } + default void setTopAppHidesStatusBar(boolean topAppHidesStatusBar) { } default void addQsTile(ComponentName tile) { } default void remQsTile(ComponentName tile) { } @@ -441,6 +443,13 @@ public class CommandQueue extends IStatusBar.Stub { } @Override + public void setTopAppHidesStatusBar(boolean hidesStatusBar) { + mHandler.removeMessages(MSG_SET_TOP_APP_HIDES_STATUS_BAR); + mHandler.obtainMessage(MSG_SET_TOP_APP_HIDES_STATUS_BAR, hidesStatusBar ? 1 : 0, 0) + .sendToTarget(); + } + + @Override public void showShutdownUi(boolean isReboot, String reason) { synchronized (mLock) { mHandler.removeMessages(MSG_SHOW_SHUTDOWN_UI); @@ -640,6 +649,11 @@ public class CommandQueue extends IStatusBar.Stub { mCallbacks.get(i).handleShowShutdownUi(msg.arg1 != 0, (String) msg.obj); } break; + case MSG_SET_TOP_APP_HIDES_STATUS_BAR: + for (int i = 0; i < mCallbacks.size(); i++) { + mCallbacks.get(i).setTopAppHidesStatusBar(msg.arg1 != 0); + } + break; } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java index 334991fd3516..1bbf84855eba 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java @@ -30,6 +30,7 @@ import com.android.systemui.Gefingerpoken; import com.android.systemui.Interpolators; import com.android.systemui.R; import com.android.systemui.classifier.FalsingManager; +import com.android.systemui.statusbar.phone.StatusBar; /** * A utility class to enable the downward swipe on the lockscreen to go to the full shade and expand @@ -149,6 +150,9 @@ public class DragDownHelper implements Gefingerpoken { } private boolean isFalseTouch() { + if (!mDragDownCallback.isFalsingCheckNeeded()) { + return false; + } return mFalsingManager.isFalseTouch() || !mDraggedFarEnough; } @@ -249,5 +253,6 @@ public class DragDownHelper implements Gefingerpoken { void onCrossedThreshold(boolean above); void onTouchSlopExceeded(); void setEmptyDragAmount(float amount); + boolean isFalsingCheckNeeded(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index 74737c4c2948..569e58d78fae 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -184,8 +184,15 @@ public class KeyguardIndicationController { mVisible = visible; mIndicationArea.setVisibility(visible ? View.VISIBLE : View.GONE); if (visible) { - hideTransientIndication(); + // If this is called after an error message was already shown, we should not clear it. + // Otherwise the error message won't be shown + if (!mHandler.hasMessages(MSG_HIDE_TRANSIENT)) { + hideTransientIndication(); + } updateIndication(); + } else if (!visible) { + // If we unlock and return to keyguard quickly, previous error should not be shown + hideTransientIndication(); } } @@ -389,7 +396,6 @@ public class KeyguardIndicationController { hideTransientIndication(); } else if (msg.what == MSG_CLEAR_FP_MSG) { mLockIcon.setTransientFpError(false); - hideTransientIndication(); } } }; @@ -443,10 +449,10 @@ public class KeyguardIndicationController { int errorColor = Utils.getColorError(mContext); if (mStatusBarKeyguardViewManager.isBouncerShowing()) { mStatusBarKeyguardViewManager.showBouncerMessage(helpString, errorColor); - } else if (updateMonitor.isDeviceInteractive() - || mDozing && updateMonitor.isScreenOn()) { + } else if (updateMonitor.isScreenOn()) { mLockIcon.setTransientFpError(true); showTransientIndication(helpString, errorColor); + hideTransientIndicationDelayed(TRANSIENT_FP_ERROR_TIMEOUT); mHandler.removeMessages(MSG_CLEAR_FP_MSG); mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CLEAR_FP_MSG), TRANSIENT_FP_ERROR_TIMEOUT); @@ -459,7 +465,8 @@ public class KeyguardIndicationController { @Override public void onFingerprintError(int msgId, String errString) { KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext); - if (!updateMonitor.isUnlockingWithFingerprintAllowed() + if ((!updateMonitor.isUnlockingWithFingerprintAllowed() + && msgId != FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) || msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) { return; } @@ -472,7 +479,7 @@ public class KeyguardIndicationController { if (mLastSuccessiveErrorMessage != msgId) { mStatusBarKeyguardViewManager.showBouncerMessage(errString, errorColor); } - } else if (updateMonitor.isDeviceInteractive()) { + } else if (updateMonitor.isScreenOn()) { showTransientIndication(errString, errorColor); // We want to keep this message around in case the screen was off hideTransientIndicationDelayed(HIDE_DELAY_MS); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java index 194cdc77c02a..81a99bc1e70c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar; import android.content.Context; import android.content.res.ColorStateList; import android.graphics.Canvas; +import android.graphics.ColorFilter; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.graphics.drawable.RippleDrawable; @@ -34,6 +35,7 @@ public class NotificationBackgroundView extends View { private int mClipTopAmount; private int mActualHeight; private int mClipBottomAmount; + private int mTintColor; public NotificationBackgroundView(Context context, AttributeSet attrs) { super(context, attrs); @@ -87,6 +89,7 @@ public class NotificationBackgroundView extends View { mBackground = background; if (mBackground != null) { mBackground.setCallback(this); + setTint(mTintColor); } if (mBackground instanceof RippleDrawable) { ((RippleDrawable) mBackground).setForceSoftware(true); @@ -105,6 +108,7 @@ public class NotificationBackgroundView extends View { } else { mBackground.clearColorFilter(); } + mTintColor = tintColor; invalidate(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java index 6060134de6da..172c62a99db2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java @@ -53,7 +53,7 @@ public class FullscreenUserSwitcher { mParent = containerStub.inflate(); mContainer = mParent.findViewById(R.id.container); mUserGridView = mContainer.findViewById(R.id.user_grid); - mUserGridView.init(statusBar, mUserSwitcherController); + mUserGridView.init(statusBar, mUserSwitcherController, true /* showInitially */); mUserGridView.setUserSelectionListener(record -> { if (!record.isCurrent) { toggleSwitchInProgress(true); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java index cfa986467ccb..e551801ca434 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java @@ -16,14 +16,21 @@ package com.android.systemui.statusbar.car; +import android.animation.Animator; +import android.animation.Animator.AnimatorListener; +import android.animation.ValueAnimator; import android.content.Context; -import android.graphics.Color; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Paint.Align; import android.graphics.drawable.Drawable; -import android.os.UserHandle; +import android.graphics.drawable.GradientDrawable; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; +import android.support.v4.view.animation.FastOutSlowInInterpolator; import android.util.AttributeSet; -import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -31,9 +38,7 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; -import com.android.internal.util.UserIcons; import com.android.systemui.R; -import com.android.systemui.statusbar.UserUtil; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.UserSwitcherController; @@ -42,21 +47,44 @@ import com.android.systemui.statusbar.policy.UserSwitcherController; * One of the uses of this is for the lock screen in auto. */ public class UserGridView extends ViewPager { + private static final int EXPAND_ANIMATION_TIME_MS = 200; + private static final int HIDE_ANIMATION_TIME_MS = 133; + private StatusBar mStatusBar; private UserSwitcherController mUserSwitcherController; private Adapter mAdapter; private UserSelectionListener mUserSelectionListener; + private ValueAnimator mHeightAnimator; + private int mTargetHeight; + private int mHeightChildren; + private boolean mShowing; public UserGridView(Context context, AttributeSet attrs) { super(context, attrs); } - public void init(StatusBar statusBar, UserSwitcherController userSwitcherController) { + public void init(StatusBar statusBar, UserSwitcherController userSwitcherController, + boolean showInitially) { mStatusBar = statusBar; mUserSwitcherController = userSwitcherController; mAdapter = new Adapter(mUserSwitcherController); addOnLayoutChangeListener(mAdapter); setAdapter(mAdapter); + mShowing = showInitially; + } + + public boolean isShowing() { + return mShowing; + } + + public void show() { + mShowing = true; + animateHeightChange(getMeasuredHeight(), mHeightChildren); + } + + public void hide() { + mShowing = false; + animateHeightChange(getMeasuredHeight(), 0); } public void onUserSwitched(int newUserId) { @@ -77,16 +105,85 @@ public class UserGridView extends ViewPager { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // Wrap content doesn't work in ViewPagers, so simulate the behavior in code. int height = 0; - for(int i = 0; i < getChildCount(); i++) { - View child = getChildAt(i); - child.measure(widthMeasureSpec, - MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - height = Math.max(child.getMeasuredHeight(), height); + if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) { + height = MeasureSpec.getSize(heightMeasureSpec); + } else { + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + child.measure(widthMeasureSpec, + MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + height = Math.max(child.getMeasuredHeight(), height); + } + + mHeightChildren = height; + + // Override the height if it's not showing. + if (!mShowing) { + height = 0; + } + + // Respect the AT_MOST request from parent. + if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) { + height = Math.min(MeasureSpec.getSize(heightMeasureSpec), height); + } } heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); } + private void animateHeightChange(int oldHeight, int newHeight) { + // If there is no change in height or an animation is already in progress towards the + // desired height, then there's no need to make any changes. + if (oldHeight == newHeight || newHeight == mTargetHeight) { + return; + } + + // Animation in progress is not going towards the new target, so cancel it. + if (mHeightAnimator != null){ + mHeightAnimator.cancel(); + } + + mTargetHeight = newHeight; + mHeightAnimator = ValueAnimator.ofInt(oldHeight, mTargetHeight); + mHeightAnimator.addUpdateListener(valueAnimator -> { + ViewGroup.LayoutParams layoutParams = getLayoutParams(); + layoutParams.height = (Integer) valueAnimator.getAnimatedValue(); + requestLayout(); + }); + mHeightAnimator.addListener(new AnimatorListener() { + @Override + public void onAnimationStart(Animator animator) {} + + @Override + public void onAnimationEnd(Animator animator) { + // ValueAnimator does not guarantee that the update listener will get an update + // to the final value, so here, the final value is set. Though the final calculated + // height (mTargetHeight) could be set, WRAP_CONTENT is more appropriate. + ViewGroup.LayoutParams layoutParams = getLayoutParams(); + layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT; + requestLayout(); + mHeightAnimator = null; + } + + @Override + public void onAnimationCancel(Animator animator) {} + + @Override + public void onAnimationRepeat(Animator animator) {} + }); + + mHeightAnimator.setInterpolator(new FastOutSlowInInterpolator()); + if (oldHeight < newHeight) { + // Expanding + mHeightAnimator.setDuration(EXPAND_ANIMATION_TIME_MS); + } else { + // Hiding + mHeightAnimator.setDuration(HIDE_ANIMATION_TIME_MS); + } + mHeightAnimator.start(); + } + /** * This is a ViewPager.PagerAdapter which deletegates the work to a * UserSwitcherController.BaseUserAdapter. Java doesn't support multiple inheritance so we have @@ -95,7 +192,9 @@ public class UserGridView extends ViewPager { */ private final class Adapter extends PagerAdapter implements View.OnLayoutChangeListener { private final int mPodWidth; - private final int mPodMargin; + private final int mPodMarginBetween; + private final int mPodImageAvatarWidth; + private final int mPodImageAvatarHeight; private final WrappedBaseUserAdapter mUserAdapter; private int mContainerWidth; @@ -103,10 +202,15 @@ public class UserGridView extends ViewPager { public Adapter(UserSwitcherController controller) { super(); mUserAdapter = new WrappedBaseUserAdapter(controller, this); - mPodWidth = getResources().getDimensionPixelSize( + + Resources res = getResources(); + mPodWidth = res.getDimensionPixelSize(R.dimen.car_fullscreen_user_pod_width); + mPodMarginBetween = res.getDimensionPixelSize( + R.dimen.car_fullscreen_user_pod_margin_between); + mPodImageAvatarWidth = res.getDimensionPixelSize( R.dimen.car_fullscreen_user_pod_image_avatar_width); - mPodMargin = getResources().getDimensionPixelSize( - R.dimen.car_fullscreen_user_pod_margin_side); + mPodImageAvatarHeight = res.getDimensionPixelSize( + R.dimen.car_fullscreen_user_pod_image_avatar_height); } @Override @@ -116,9 +220,12 @@ public class UserGridView extends ViewPager { private int getIconsPerPage() { // We need to know how many pods we need in this page. Each pod has its own width and - // margins on both sides. We can then divide the measured width of the parent by the + // a margin between them. We can then divide the measured width of the parent by the // sum of pod width and margin to get the number of pods that will completely fit. - return mContainerWidth / (mPodWidth + mPodMargin * 2); + // There is one less margin than the number of pods (eg. for 5 pods, there are 4 + // margins), so need to add the margin to the measured width to account for that. + return (mContainerWidth + mPodMarginBetween) / + (mPodWidth + mPodMarginBetween); } @Override @@ -132,19 +239,58 @@ public class UserGridView extends ViewPager { int iconsPerPage = getIconsPerPage(); int limit = Math.min(mUserAdapter.getCount(), (position + 1) * iconsPerPage); for (int i = position * iconsPerPage; i < limit; i++) { - pods.addView(makeUserPod(inflater, context, i, pods)); + View v = makeUserPod(inflater, context, i, pods); + pods.addView(v); + // This is hacky, but the dividers on the pod container LinearLayout don't seem + // to work for whatever reason. Instead, set a right margin on the pod if it's not + // the right-most pod and there is more than one pod in the container. + if (i < limit - 1 && limit > 1) { + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + params.setMargins(0, 0, mPodMarginBetween, 0); + v.setLayoutParams(params); + } } container.addView(pods); return pods; } - private Drawable getUserIcon(Context context, UserSwitcherController.UserRecord record) { - if (record.isAddUser) { - Drawable icon = context.getDrawable(R.drawable.ic_add_circle_qs); - icon.setTint(Color.WHITE); - return icon; - } - return UserIcons.getDefaultUserIcon(record.resolveId(), /* light= */ true); + /** + * Returns the default user icon. This icon is a circle with a letter in it. The letter is + * the first character in the username. + * + * @param userName the username of the user for which the icon is to be created + */ + private Bitmap getDefaultUserIcon(CharSequence userName) { + CharSequence displayText = userName.subSequence(0, 1); + Bitmap out = Bitmap.createBitmap(mPodImageAvatarWidth, mPodImageAvatarHeight, + Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(out); + + // Draw the circle background. + GradientDrawable shape = new GradientDrawable(); + shape.setShape(GradientDrawable.RADIAL_GRADIENT); + shape.setGradientRadius(1.0f); + shape.setColor(getContext().getColor(R.color.car_user_switcher_no_user_image_bgcolor)); + shape.setBounds(0, 0, mPodImageAvatarWidth, mPodImageAvatarHeight); + shape.draw(canvas); + + // Draw the letter in the center. + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + paint.setColor(getContext().getColor(R.color.car_user_switcher_no_user_image_fgcolor)); + paint.setTextAlign(Align.CENTER); + paint.setTextSize(getResources().getDimensionPixelSize( + R.dimen.car_fullscreen_user_pod_icon_text_size)); + Paint.FontMetricsInt metrics = paint.getFontMetricsInt(); + // The Y coordinate is measured by taking half the height of the pod, but that would + // draw the character putting the bottom of the font in the middle of the pod. To + // correct this, half the difference between the top and bottom distance metrics of the + // font gives the offset of the font. Bottom is a positive value, top is negative, so + // the different is actually a sum. The "half" operation is then factored out. + canvas.drawText(displayText.toString(), mPodImageAvatarWidth / 2, + (mPodImageAvatarHeight - (metrics.bottom + metrics.top)) / 2, paint); + + return out; } private View makeUserPod(LayoutInflater inflater, Context context, @@ -161,8 +307,12 @@ public class UserGridView extends ViewPager { } ImageView iconView = (ImageView) view.findViewById(R.id.user_avatar); - if (record == null || record.picture == null) { - iconView.setImageDrawable(getUserIcon(context, record)); + if (record == null || (record.picture == null && !record.isAddUser)) { + iconView.setImageBitmap(getDefaultUserIcon(nameView.getText())); + } else if (record.isAddUser) { + Drawable icon = context.getDrawable(R.drawable.ic_add_circle_qs); + icon.setTint(context.getColor(R.color.car_user_switcher_no_user_image_bgcolor)); + iconView.setImageDrawable(icon); } else { iconView.setImageBitmap(record.picture); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java index bf926c625e4f..f9671182ab8c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java @@ -193,7 +193,7 @@ public class NotificationInflater { int flag = FLAG_REINFLATE_CONTENT_VIEW; if ((reInflateFlags & flag) != 0) { - boolean isNewView = !compareRemoteViews(result.newContentView, entry.cachedContentView); + boolean isNewView = !canReapplyRemoteView(result.newContentView, entry.cachedContentView); ApplyCallback applyCallback = new ApplyCallback() { @Override public void setResultView(View v) { @@ -215,7 +215,7 @@ public class NotificationInflater { flag = FLAG_REINFLATE_EXPANDED_VIEW; if ((reInflateFlags & flag) != 0) { if (result.newExpandedView != null) { - boolean isNewView = !compareRemoteViews(result.newExpandedView, + boolean isNewView = !canReapplyRemoteView(result.newExpandedView, entry.cachedBigContentView); ApplyCallback applyCallback = new ApplyCallback() { @Override @@ -240,7 +240,7 @@ public class NotificationInflater { flag = FLAG_REINFLATE_HEADS_UP_VIEW; if ((reInflateFlags & flag) != 0) { if (result.newHeadsUpView != null) { - boolean isNewView = !compareRemoteViews(result.newHeadsUpView, + boolean isNewView = !canReapplyRemoteView(result.newHeadsUpView, entry.cachedHeadsUpContentView); ApplyCallback applyCallback = new ApplyCallback() { @Override @@ -264,7 +264,7 @@ public class NotificationInflater { flag = FLAG_REINFLATE_PUBLIC_VIEW; if ((reInflateFlags & flag) != 0) { - boolean isNewView = !compareRemoteViews(result.newPublicView, + boolean isNewView = !canReapplyRemoteView(result.newPublicView, entry.cachedPublicContentView); ApplyCallback applyCallback = new ApplyCallback() { @Override @@ -288,7 +288,7 @@ public class NotificationInflater { if ((reInflateFlags & flag) != 0) { NotificationContentView newParent = redactAmbient ? publicLayout : privateLayout; boolean isNewView = !canReapplyAmbient(row, redactAmbient) || - !compareRemoteViews(result.newAmbientView, entry.cachedAmbientContentView); + !canReapplyRemoteView(result.newAmbientView, entry.cachedAmbientContentView); ApplyCallback applyCallback = new ApplyCallback() { @Override public void setResultView(View v) { @@ -486,14 +486,21 @@ public class NotificationInflater { return builder.createContentView(useLarge); } - // Returns true if the RemoteViews are the same. - private static boolean compareRemoteViews(final RemoteViews a, final RemoteViews b) { - return (a == null && b == null) || - (a != null && b != null - && b.getPackage() != null - && a.getPackage() != null - && a.getPackage().equals(b.getPackage()) - && a.getLayoutId() == b.getLayoutId()); + /** + * @param newView The new view that will be applied + * @param oldView The old view that was applied to the existing view before + * @return {@code true} if the RemoteViews are the same and the view can be reused to reapply. + */ + @VisibleForTesting + static boolean canReapplyRemoteView(final RemoteViews newView, + final RemoteViews oldView) { + return (newView == null && oldView == null) || + (newView != null && oldView != null + && oldView.getPackage() != null + && newView.getPackage() != null + && newView.getPackage().equals(oldView.getPackage()) + && newView.getLayoutId() == oldView.getLayoutId() + && !oldView.isReapplyDisallowed()); } public void setInflationCallback(InflationCallback callback) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java index 844a2c495501..3115361c6927 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java @@ -16,7 +16,10 @@ package com.android.systemui.statusbar.notification; +import android.content.Context; import android.graphics.Color; +import android.os.UserHandle; +import android.provider.Settings; import android.view.View; import android.widget.ImageView; @@ -57,4 +60,10 @@ public class NotificationUtils { offsetView.getLocationOnScreen(sLocationOffset); return sLocationOffset[1] - sLocationBase[1]; } + + public static boolean isHapticFeedbackDisabled(Context context) { + return Settings.System.getIntForUser(context.getContentResolver(), + Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0; + } + } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java index f3c2bc56b409..f379a4636623 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java @@ -75,6 +75,10 @@ public class BarTransitions { return mMode; } + public void setAutoDim(boolean autoDim) { + // Default is don't care. + } + /** * @param alwaysOpaque if {@code true}, the bar's background will always be opaque, regardless * of what mode it is currently set to. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java index 2bc26654fd87..a83e6591c48b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java @@ -174,16 +174,6 @@ public class ButtonDispatcher { mCurrentView = currentView.findViewById(mId); } - public void setCarMode(boolean carMode) { - final int N = mViews.size(); - for (int i = 0; i < N; i++) { - final View view = mViews.get(i); - if (view instanceof ButtonInterface) { - ((ButtonInterface) view).setCarMode(carMode); - } - } - } - public void setVertical(boolean vertical) { mVertical = vertical; final int N = mViews.size(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java index 4339ade13ce0..8c923cbcde0b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java @@ -14,6 +14,9 @@ package com.android.systemui.statusbar.phone; +import static android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS; +import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO; + import static com.android.systemui.statusbar.phone.StatusBar.reinflateSignalCluster; import android.annotation.Nullable; @@ -144,42 +147,52 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue final int old1 = mDisabled1; final int diff1 = state1 ^ old1; mDisabled1 = state1; - if ((diff1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) { - if ((state1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) { + if ((diff1 & DISABLE_SYSTEM_INFO) != 0) { + if ((state1 & DISABLE_SYSTEM_INFO) != 0) { hideSystemIconArea(animate); } else { showSystemIconArea(animate); } } - if ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) { - if ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) { + if ((diff1 & DISABLE_NOTIFICATION_ICONS) != 0) { + if ((state1 & DISABLE_NOTIFICATION_ICONS) != 0) { hideNotificationIconArea(animate); } else { showNotificationIconArea(animate); } } + if (!BarTransitions.HIGH_END) { + int mask = DISABLE_NOTIFICATION_ICONS | DISABLE_SYSTEM_INFO; + getView().setVisibility((mDisabled1 & mask) == mask ? View.GONE : View.VISIBLE); + } } protected int adjustDisableFlags(int state) { if (!mStatusBarComponent.isLaunchTransitionFadingAway() && !mKeyguardMonitor.isKeyguardFadingAway() && shouldHideNotificationIcons()) { - state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS; - state |= StatusBarManager.DISABLE_SYSTEM_INFO; + state |= DISABLE_NOTIFICATION_ICONS; + state |= DISABLE_SYSTEM_INFO; } if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) { if (mNetworkController.hasEmergencyCryptKeeperText()) { - state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS; + state |= DISABLE_NOTIFICATION_ICONS; } if (!mNetworkController.isRadioOn()) { - state |= StatusBarManager.DISABLE_SYSTEM_INFO; + state |= DISABLE_SYSTEM_INFO; } } return state; } private boolean shouldHideNotificationIcons() { - return !mStatusBar.isClosed() && mStatusBarComponent.hideStatusBarIconsWhenExpanded(); + if (!mStatusBar.isClosed() && mStatusBarComponent.hideStatusBarIconsWhenExpanded()) { + return true; + } + if (mStatusBarComponent.hideStatusBarIconsForBouncer()) { + return true; + } + return false; } public void hideSystemIconArea(boolean animate) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java index c45c05e14a22..021b4518efbe 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java @@ -54,6 +54,7 @@ public class DozeScrimController { private boolean mFullyPulsing; private float mAodFrontScrimOpacity = 0; + private Runnable mSetDozeInFrontAlphaDelayed; public DozeScrimController(ScrimController scrimController, Context context) { mContext = context; @@ -69,8 +70,7 @@ public class DozeScrimController { mDozingAborted = false; abortAnimations(); mScrimController.setDozeBehindAlpha(1f); - mScrimController.setDozeInFrontAlpha( - mDozeParameters.getAlwaysOn() ? mAodFrontScrimOpacity : 1f); + setDozeInFrontAlpha(mDozeParameters.getAlwaysOn() ? mAodFrontScrimOpacity : 1f); } else { cancelPulsing(); if (animate) { @@ -83,7 +83,7 @@ public class DozeScrimController { } else { abortAnimations(); mScrimController.setDozeBehindAlpha(0f); - mScrimController.setDozeInFrontAlpha(0f); + setDozeInFrontAlpha(0f); } } } @@ -97,7 +97,7 @@ public class DozeScrimController { mAodFrontScrimOpacity = scrimOpacity; if (mDozing && !isPulsing() && !mDozingAborted && !mWakeAndUnlocking && mDozeParameters.getAlwaysOn()) { - mScrimController.setDozeInFrontAlpha(mAodFrontScrimOpacity); + setDozeInFrontAlpha(mAodFrontScrimOpacity); } } @@ -107,7 +107,7 @@ public class DozeScrimController { if (!mWakeAndUnlocking) { mWakeAndUnlocking = true; mScrimController.setDozeBehindAlpha(0f); - mScrimController.setDozeInFrontAlpha(0f); + setDozeInFrontAlpha(0f); } } @@ -127,7 +127,7 @@ public class DozeScrimController { // be invoked when we're done so that the caller can drop the pulse wakelock. mPulseCallback = callback; mPulseReason = reason; - mScrimController.setDozeInFrontAlpha(1f); + setDozeInFrontAlpha(1f); mHandler.post(mPulseIn); } @@ -138,9 +138,8 @@ public class DozeScrimController { cancelPulsing(); if (mDozing && !mWakeAndUnlocking) { mScrimController.setDozeBehindAlpha(1f); - mScrimController.setDozeInFrontAlpha( - mDozeParameters.getAlwaysOn() && !mDozingAborted ? - mAodFrontScrimOpacity : 1f); + setDozeInFrontAlpha(mDozeParameters.getAlwaysOn() && !mDozingAborted + ? mAodFrontScrimOpacity : 1f); } } @@ -295,6 +294,25 @@ public class DozeScrimController { : mScrimController.getDozeBehindAlpha(); } + private void setDozeInFrontAlpha(float opacity) { + setDozeInFrontAlphaDelayed(opacity, 0 /* delay */); + + } + + private void setDozeInFrontAlphaDelayed(float opacity, long delayMs) { + if (mSetDozeInFrontAlphaDelayed != null) { + mHandler.removeCallbacks(mSetDozeInFrontAlphaDelayed); + mSetDozeInFrontAlphaDelayed = null; + } + if (delayMs <= 0) { + mScrimController.setDozeInFrontAlpha(opacity); + } else { + mHandler.postDelayed(mSetDozeInFrontAlphaDelayed = () -> { + setDozeInFrontAlpha(opacity); + }, delayMs); + } + } + private final Runnable mPulseIn = new Runnable() { @Override public void run() { @@ -364,7 +382,9 @@ public class DozeScrimController { // Signal that the pulse is all finished so we can turn the screen off now. DozeScrimController.this.pulseFinished(); if (mDozeParameters.getAlwaysOn()) { - mScrimController.setDozeInFrontAlpha(mAodFrontScrimOpacity); + // Setting power states can happen after we push out the frame. Make sure we + // stay fully opaque until the power state request reaches the lower levels. + setDozeInFrontAlphaDelayed(mAodFrontScrimOpacity, 30); } } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java index cb96dea08ae0..316d229e4f1a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java @@ -32,6 +32,8 @@ import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle; +import java.io.PrintWriter; + /** * Controller which coordinates all the fingerprint unlocking actions with the UI. */ @@ -264,6 +266,7 @@ public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback { @Override public void onStartedGoingToSleep(int why) { + resetMode(); mPendingAuthenticatedUserId = -1; } @@ -346,6 +349,10 @@ public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback { } public void finishKeyguardFadingAway() { + resetMode(); + } + + private void resetMode() { mMode = MODE_NONE; mStatusBarWindowManager.setForceDozeBrightness(false); if (mStatusBar.getNavigationBarView() != null) { @@ -375,4 +382,10 @@ public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback { public boolean hasScreenTurnedOnSinceAuthenticating() { return mHasScreenTurnedOnSinceAuthenticating; } + + public void dump(PrintWriter pw) { + pw.println(" FingerprintUnlockController:"); + pw.print(" mMode="); pw.println(mMode); + pw.print(" mWakeLock="); pw.println(mWakeLock); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java index 82e6a3562c8d..c85571c1895d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java @@ -111,6 +111,7 @@ public class HeadsUpTouchHelper implements Gefingerpoken { // flicker of one frame as it's not expanded yet. mHeadsUpManager.unpinAll(); mPanel.clearNotificationEffects(); + endMotion(); return true; } break; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index 6cfa83843666..f0588626e79d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -72,7 +72,6 @@ import com.android.systemui.plugins.IntentButtonProvider; import com.android.systemui.plugins.IntentButtonProvider.IntentButton; import com.android.systemui.plugins.IntentButtonProvider.IntentButton.IconState; import com.android.systemui.plugins.PluginListener; -import com.android.systemui.plugins.PluginManager; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.KeyguardAffordanceView; @@ -82,10 +81,8 @@ import com.android.systemui.statusbar.policy.ExtensionController; import com.android.systemui.statusbar.policy.ExtensionController.Extension; import com.android.systemui.statusbar.policy.FlashlightController; import com.android.systemui.statusbar.policy.PreviewInflater; -import com.android.systemui.tuner.LockscreenFragment; import com.android.systemui.tuner.LockscreenFragment.LockButtonFactory; import com.android.systemui.tuner.TunerService; -import com.android.systemui.tuner.TunerService.Tunable; /** * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status @@ -510,6 +507,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL // force the crossfade animation if an orientation change // happens to occur during the launch. ActivityOptions o = ActivityOptions.makeBasic(); + o.setDisallowEnterPictureInPictureWhileLaunching(true); o.setRotationAnimationHint( WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS); try { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java index e65bab6b4032..f7aa818f0abf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java @@ -151,7 +151,7 @@ public class KeyguardClockPositionAlgorithm { progress = Math.max(0.0f, Math.min(progress, 1.0f)); progress = mAccelerateInterpolator.getInterpolation(progress); progress *= Math.pow(1 + mEmptyDragAmount / mDensity / 300, 0.3f); - return progress; + return interpolate(progress, 1, mDarkAmount); } private int getClockNotificationsPadding() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java index b0ac6ecae5bb..d3a6280212cd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java @@ -127,6 +127,11 @@ public class LightBarTransitionsController implements Dumpable, Callbacks { } public void setIconsDark(boolean dark, boolean animate) { + if (!BarTransitions.HIGH_END) { + setIconTintInternal(0.0f); + mNextDarkIntensity = 0.0f; + return; + } if (!animate) { setIconTintInternal(dark ? 1.0f : 0.0f); mNextDarkIntensity = dark ? 1.0f : 0.0f; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java index c24129079d4f..5c9446ce8672 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java @@ -207,9 +207,9 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange if (mAccessibilityController == null) { return; } - boolean clickToUnlock = mAccessibilityController.isTouchExplorationEnabled(); + boolean clickToUnlock = mAccessibilityController.isAccessibilityEnabled(); boolean clickToForceLock = mUnlockMethodCache.isTrustManaged() - && !mAccessibilityController.isAccessibilityEnabled(); + && !clickToUnlock; boolean longClickToForceLock = mUnlockMethodCache.isTrustManaged() && !clickToForceLock; setClickable(clickToForceLock || clickToUnlock); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java index c44e1db367b8..cfe0a4a6005b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java @@ -504,7 +504,7 @@ public class NavigationBarFragment extends Fragment implements Callbacks { // If we recently long-pressed the other button then they were // long-pressed 'together' if ((time - mLastLockToAppLongPress) < LOCK_TO_APP_GESTURE_TOLERENCE) { - activityManager.stopLockTaskMode(); + activityManager.stopSystemLockTaskMode(); // When exiting refresh disabled flags. mNavigationBarView.setDisabledFlags(mDisabledFlags1, true); return true; @@ -522,7 +522,7 @@ public class NavigationBarFragment extends Fragment implements Callbacks { } else if (touchExplorationEnabled && inLockTaskMode) { // When in accessibility mode a long press that is recents (not back) // should stop lock task. - activityManager.stopLockTaskMode(); + activityManager.stopSystemLockTaskMode(); // When exiting refresh disabled flags. mNavigationBarView.setDisabledFlags(mDisabledFlags1, true); return true; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java index cb925d5f7e16..f3ca66ffa9b3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java @@ -32,6 +32,7 @@ public final class NavigationBarTransitions extends BarTransitions { private final LightBarTransitionsController mLightTransitionsController; private boolean mLightsOut; + private boolean mAutoDim; public NavigationBarTransitions(NavigationBarView view) { super(view, R.drawable.nav_background); @@ -44,7 +45,19 @@ public final class NavigationBarTransitions extends BarTransitions { public void init() { applyModeBackground(-1, getMode(), false /*animate*/); - applyMode(getMode(), false /*animate*/, true /*force*/); + applyLightsOut(false /*animate*/, true /*force*/); + } + + @Override + public void setAutoDim(boolean autoDim) { + if (mAutoDim == autoDim) return; + mAutoDim = autoDim; + applyLightsOut(true, false); + } + + @Override + protected boolean isLightsOut(int mode) { + return super.isLightsOut(mode) || mAutoDim; } public LightBarTransitionsController getLightTransitionsController() { @@ -54,13 +67,12 @@ public final class NavigationBarTransitions extends BarTransitions { @Override protected void onTransition(int oldMode, int newMode, boolean animate) { super.onTransition(oldMode, newMode, animate); - applyMode(newMode, animate, false /*force*/); + applyLightsOut(animate, false /*force*/); } - private void applyMode(int mode, boolean animate, boolean force) { - + private void applyLightsOut(boolean animate, boolean force) { // apply to lights out - applyLightsOut(isLightsOut(mode), animate, force); + applyLightsOut(isLightsOut(getMode()), animate, force); } private void applyLightsOut(boolean lightsOut, boolean animate, boolean force) { @@ -86,7 +98,6 @@ public final class NavigationBarTransitions extends BarTransitions { } } - public void reapplyDarkIntensity() { applyDarkIntensity(mLightTransitionsController.getCurrentDarkIntensity()); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index 57c88275113c..9a7039a515a1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -683,8 +683,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav if (isCarMode != mInCarMode) { mInCarMode = isCarMode; - getHomeButton().setCarMode(isCarMode); - if (ALTERNATE_CAR_MODE_UI) { mUseCarModeUi = isCarMode; uiCarModeChanged = true; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java index e0d9748c48bf..88a562648a63 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java @@ -16,14 +16,19 @@ package com.android.systemui.statusbar.phone; +import static com.android.systemui.statusbar.notification.NotificationUtils.isHapticFeedbackDisabled; + import android.content.Context; import android.content.res.Configuration; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.drawable.Icon; +import android.os.AsyncTask; +import android.os.UserHandle; import android.os.VibrationEffect; import android.os.Vibrator; +import android.provider.Settings; import android.support.v4.util.ArrayMap; import android.support.v4.util.ArraySet; import android.util.AttributeSet; @@ -34,6 +39,7 @@ import com.android.systemui.Interpolators; import com.android.systemui.R; import com.android.systemui.statusbar.AlphaOptimizedFrameLayout; import com.android.systemui.statusbar.StatusBarIconView; +import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.stack.AnimationFilter; import com.android.systemui.statusbar.stack.AnimationProperties; import com.android.systemui.statusbar.stack.StackStateAnimator; @@ -623,9 +629,10 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout { boolean wasInShelf = icon.isInShelf(); boolean inShelf = iconAppearAmount == 1.0f; icon.setIsInShelf(inShelf); - if (mVibrateOnAnimation && !justAdded && mAnimationsEnabled - && wasInShelf != inShelf) { - mVibrator.vibrate(VibrationEffect.get(VibrationEffect.EFFECT_TICK)); + if (shouldVibrateChange(wasInShelf != inShelf)) { + AsyncTask.execute( + () -> mVibrator.vibrate(VibrationEffect.get( + VibrationEffect.EFFECT_TICK))); } } justAdded = false; @@ -634,6 +641,25 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout { justUndarkened = false; } + private boolean shouldVibrateChange(boolean inShelfChanged) { + if (!mVibrateOnAnimation) { + return false; + } + if (justAdded) { + return false; + } + if (!mAnimationsEnabled) { + return false; + } + if (!inShelfChanged) { + return false; + } + if (isHapticFeedbackDisabled(mContext)) { + return false; + } + return true; + } + public boolean hasCustomTransformHeight() { return isLastExpandIcon && customTransformHeight != NO_VALUE; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 04be35789807..078e8189f5b3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -32,6 +32,7 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; +import android.os.PowerManager; import android.util.AttributeSet; import android.util.FloatProperty; import android.util.MathUtils; @@ -108,6 +109,7 @@ public class NotificationPanelView extends PanelView implements return object.mDarkAmount; } }; + private final PowerManager mPowerManager; private KeyguardAffordanceHelper mAffordanceHelper; private KeyguardUserSwitcher mKeyguardUserSwitcher; @@ -242,6 +244,7 @@ public class NotificationPanelView extends PanelView implements super(context, attrs); setWillNotDraw(!DEBUG); mFalsingManager = FalsingManager.getInstance(context); + mPowerManager = context.getSystemService(PowerManager.class); } public void setStatusBar(StatusBar bar) { @@ -1974,6 +1977,11 @@ public class NotificationPanelView extends PanelView implements @Override protected void startUnlockHintAnimation() { + if (mPowerManager.isPowerSaveMode()) { + onUnlockHintStarted(); + onUnlockHintFinished(); + return; + } super.startUnlockHintAnimation(); startHighlightIconAnimation(getCenterIcon()); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java index d3ee55098474..afe5c917a856 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.phone; +import static com.android.systemui.statusbar.notification.NotificationUtils.isHapticFeedbackDisabled; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; @@ -23,9 +25,12 @@ import android.animation.ValueAnimator; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; +import android.os.AsyncTask; import android.os.SystemClock; +import android.os.UserHandle; import android.os.VibrationEffect; import android.os.Vibrator; +import android.provider.Settings; import android.util.AttributeSet; import android.util.Log; import android.view.InputDevice; @@ -45,6 +50,7 @@ import com.android.systemui.classifier.FalsingManager; import com.android.systemui.doze.DozeLog; import com.android.systemui.statusbar.FlingAnimationUtils; import com.android.systemui.statusbar.StatusBarState; +import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.policy.HeadsUpManager; import java.io.FileDescriptor; @@ -59,6 +65,7 @@ public abstract class PanelView extends FrameLayout { private float mMinExpandHeight; private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger(); private boolean mPanelUpdateWhenAnimatorEnds; + private boolean mVibrateOnOpening; private final void logf(String fmt, Object... args) { Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args)); @@ -203,6 +210,8 @@ public abstract class PanelView extends FrameLayout { mNotificationsDragEnabled = getResources().getBoolean(R.bool.config_enableNotificationShadeDrag); mVibrator = mContext.getSystemService(Vibrator.class); + mVibrateOnOpening = mContext.getResources().getBoolean( + R.bool.config_vibrateOnIconAnimation); } protected void loadDimens() { @@ -394,7 +403,10 @@ public abstract class PanelView extends FrameLayout { runPeekAnimation(INITIAL_OPENING_PEEK_DURATION, getOpeningHeight(), false /* collapseWhenFinished */); notifyBarPanelExpansionChanged(); - mVibrator.vibrate(VibrationEffect.get(VibrationEffect.EFFECT_CLICK)); + if (mVibrateOnOpening && !isHapticFeedbackDisabled(mContext)) { + AsyncTask.execute(() -> + mVibrator.vibrate(VibrationEffect.get(VibrationEffect.EFFECT_TICK, false))); + } } protected abstract float getOpeningHeight(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 1d6448094132..702afa3a38b1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -48,6 +48,7 @@ import com.android.systemui.statusbar.ScrimView; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import com.android.systemui.statusbar.stack.ViewState; +import java.io.PrintWriter; import java.util.function.Consumer; /** @@ -768,4 +769,22 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, scheduleUpdate(); } } + + public void dump(PrintWriter pw) { + pw.println(" ScrimController:"); + + pw.print(" frontScrim:"); pw.print(" viewAlpha="); pw.print(mScrimInFront.getViewAlpha()); + pw.print(" alpha="); pw.print(mCurrentInFrontAlpha); + pw.print(" dozeAlpha="); pw.print(mDozeInFrontAlpha); + pw.print(" tint=0x"); pw.println(Integer.toHexString(mScrimInFront.getTint())); + + pw.print(" backScrim:"); pw.print(" viewAlpha="); pw.print(mScrimBehind.getViewAlpha()); + pw.print(" alpha="); pw.print(mCurrentBehindAlpha); + pw.print(" dozeAlpha="); pw.print(mDozeBehindAlpha); + pw.print(" tint=0x"); pw.println(Integer.toHexString(mScrimBehind.getTint())); + + pw.print(" mBouncerShowing="); pw.println(mBouncerShowing); + pw.print(" mTracking="); pw.println(mTracking); + pw.print(" mForceHideScrims="); pw.println(mForceHideScrims); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 59e7005e7daf..7aebfdc5c3bc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -19,7 +19,6 @@ package com.android.systemui.statusbar.phone; import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN; import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; import static android.app.StatusBarManager.windowStateToString; -import static android.content.res.Configuration.UI_MODE_TYPE_CAR; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE; @@ -105,7 +104,6 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.Vibrator; import android.provider.Settings; -import android.service.notification.NotificationListenerService; import android.service.notification.NotificationListenerService.RankingMap; import android.service.notification.StatusBarNotification; import android.service.vr.IVrManager; @@ -144,7 +142,6 @@ import android.widget.Toast; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.colorextraction.ColorExtractor; -import com.android.internal.graphics.ColorUtils; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; @@ -429,7 +426,7 @@ public class StatusBar extends SystemUI implements DemoMode, private int mStatusBarWindowState = WINDOW_STATE_SHOWING; protected StatusBarWindowManager mStatusBarWindowManager; protected UnlockMethodCache mUnlockMethodCache; - private DozeServiceHost mDozeServiceHost; + private DozeServiceHost mDozeServiceHost = new DozeServiceHost(); private boolean mWakeUpComingFromTouch; private PointF mWakeUpTouchLocation; @@ -561,14 +558,12 @@ public class StatusBar extends SystemUI implements DemoMode, protected DozeScrimController mDozeScrimController; private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class); - private final Runnable mAutohide = new Runnable() { - @Override - public void run() { - int requested = mSystemUiVisibility & ~STATUS_OR_NAV_TRANSIENT; - if (mSystemUiVisibility != requested) { - notifyUiVisibilityChanged(requested); - } - }}; + private final Runnable mAutohide = () -> { + int requested = mSystemUiVisibility & ~STATUS_OR_NAV_TRANSIENT; + if (mSystemUiVisibility != requested) { + notifyUiVisibilityChanged(requested); + } + }; private boolean mWaitingForKeyguardExit; protected boolean mDozing; @@ -641,6 +636,12 @@ public class StatusBar extends SystemUI implements DemoMode, // Fingerprint (as computed by getLoggingFingerprint() of the last logged state. private int mLastLoggedStateFingerprint; + private boolean mTopHidesStatusBar; + private boolean mStatusBarWindowHidden; + private boolean mHideIconsForBouncer; + private boolean mIsOccluded; + private boolean mWereIconsJustHidden; + private boolean mBouncerWasShowingWhenHidden; public boolean isStartedGoingToSleep() { return mStartedGoingToSleep; @@ -733,7 +734,8 @@ public class StatusBar extends SystemUI implements DemoMode, private KeyguardUserSwitcher mKeyguardUserSwitcher; private UserSwitcherController mUserSwitcherController; private NetworkController mNetworkController; - private KeyguardMonitorImpl mKeyguardMonitor; + private KeyguardMonitorImpl mKeyguardMonitor + = (KeyguardMonitorImpl) Dependency.get(KeyguardMonitor.class); private BatteryController mBatteryController; protected boolean mPanelExpanded; private IOverlayManager mOverlayManager; @@ -741,7 +743,7 @@ public class StatusBar extends SystemUI implements DemoMode, private boolean mIsKeyguard; private LogMaker mStatusBarStateLog; private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger(); - private NotificationIconAreaController mNotificationIconAreaController; + protected NotificationIconAreaController mNotificationIconAreaController; private boolean mReinflateNotificationsOnUserSwitched; private HashMap<String, Entry> mPendingNotifications = new HashMap<>(); private boolean mClearAllEnabled; @@ -788,14 +790,12 @@ public class StatusBar extends SystemUI implements DemoMode, public void start() { mNetworkController = Dependency.get(NetworkController.class); mUserSwitcherController = Dependency.get(UserSwitcherController.class); - mKeyguardMonitor = (KeyguardMonitorImpl) Dependency.get(KeyguardMonitor.class); mScreenLifecycle = Dependency.get(ScreenLifecycle.class); mScreenLifecycle.addObserver(mScreenObserver); mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class); mWakefulnessLifecycle.addObserver(mWakefulnessObserver); mBatteryController = Dependency.get(BatteryController.class); mAssistManager = Dependency.get(AssistManager.class); - mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class); mSystemServicesProxy = SystemServicesProxy.getInstance(mContext); mOverlayManager = IOverlayManager.Stub.asInterface( ServiceManager.getService(Context.OVERLAY_SERVICE)); @@ -981,7 +981,6 @@ public class StatusBar extends SystemUI implements DemoMode, startKeyguard(); KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateCallback); - mDozeServiceHost = new DozeServiceHost(); putComponent(DozeHost.class, mDozeServiceHost); notifyUserAboutHiddenNotifications(); @@ -1171,7 +1170,8 @@ public class StatusBar extends SystemUI implements DemoMode, ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame, Dependency.get(ExtensionController.class).newExtension(QS.class) .withPlugin(QS.class) - .withUiMode(UI_MODE_TYPE_CAR, () -> new CarQSFragment()) + .withFeature( + PackageManager.FEATURE_AUTOMOTIVE, () -> new CarQSFragment()) .withDefault(() -> new QSFragment()) .build()); final QSTileHost qsh = SystemUIFactory.getInstance().createQSTileHost(mContext, this, @@ -1328,7 +1328,7 @@ public class StatusBar extends SystemUI implements DemoMode, // Clock and bottom icons mNotificationPanel.onOverlayChanged(); // The status bar on the keyguard is a special layout. - mKeyguardStatusBar.onOverlayChanged(); + if (mKeyguardStatusBar != null) mKeyguardStatusBar.onOverlayChanged(); // Recreate Indication controller because internal references changed mKeyguardIndicationController = SystemUIFactory.getInstance().createKeyguardIndicationController(mContext, @@ -1373,7 +1373,7 @@ public class StatusBar extends SystemUI implements DemoMode, } private void inflateSignalClusters() { - reinflateSignalCluster(mKeyguardStatusBar); + if (mKeyguardStatusBar != null) reinflateSignalCluster(mKeyguardStatusBar); } public static SignalClusterView reinflateSignalCluster(View view) { @@ -2677,7 +2677,8 @@ public class StatusBar extends SystemUI implements DemoMode, @Override public void startActivity(Intent intent, boolean dismissShade, Callback callback) { - startActivityDismissingKeyguard(intent, false, dismissShade, callback); + startActivityDismissingKeyguard(intent, false, dismissShade, + false /* disallowEnterPictureInPictureWhileLaunching */, callback); } public void setQsExpanded(boolean expanded) { @@ -2828,6 +2829,7 @@ public class StatusBar extends SystemUI implements DemoMode, public void setPanelExpanded(boolean isExpanded) { mPanelExpanded = isExpanded; + updateHideIconsForBouncer(false /* animate */); mStatusBarWindowManager.setPanelExpanded(isExpanded); mVisualStabilityManager.setPanelExpanded(isExpanded); if (isExpanded && getBarState() != StatusBarState.KEYGUARD) { @@ -2893,6 +2895,40 @@ public class StatusBar extends SystemUI implements DemoMode, return mAmbientIndicationContainer; } + public void setOccluded(boolean occluded) { + mIsOccluded = occluded; + updateHideIconsForBouncer(false /* animate */); + } + + public boolean hideStatusBarIconsForBouncer() { + return mHideIconsForBouncer || mWereIconsJustHidden; + } + + /** + * @param animate should the change of the icons be animated. + */ + private void updateHideIconsForBouncer(boolean animate) { + boolean shouldHideIconsForBouncer = !mPanelExpanded && mTopHidesStatusBar && mIsOccluded + && (mBouncerShowing || mStatusBarWindowHidden); + if (mHideIconsForBouncer != shouldHideIconsForBouncer) { + mHideIconsForBouncer = shouldHideIconsForBouncer; + if (!shouldHideIconsForBouncer && mBouncerWasShowingWhenHidden) { + // We're delaying the showing, since most of the time the fullscreen app will + // hide the icons again and we don't want them to fade in and out immediately again. + mWereIconsJustHidden = true; + mHandler.postDelayed(() -> { + mWereIconsJustHidden = false; + recomputeDisableFlags(true); + }, 500); + } else { + recomputeDisableFlags(animate); + } + } + if (shouldHideIconsForBouncer) { + mBouncerWasShowingWhenHidden = mBouncerShowing; + } + } + /** * All changes to the status bar and notifications funnel through here and are batched. */ @@ -3219,6 +3255,10 @@ public class StatusBar extends SystemUI implements DemoMode, mStatusBarView.collapsePanel(false /* animate */, false /* delayed */, 1.0f /* speedUpFactor */); } + if (mStatusBarView != null) { + mStatusBarWindowHidden = state == WINDOW_STATE_HIDDEN; + updateHideIconsForBouncer(false /* animate */); + } } } @@ -3280,6 +3320,7 @@ public class StatusBar extends SystemUI implements DemoMode, } else { cancelAutohide(); } + touchAutoDim(); } protected int computeStatusBarMode(int oldVal, int newVal) { @@ -3365,6 +3406,7 @@ public class StatusBar extends SystemUI implements DemoMode, dismissVolumeDialog(); } checkBarModes(); + touchAutoDim(); } private void dismissVolumeDialog() { @@ -3396,6 +3438,16 @@ public class StatusBar extends SystemUI implements DemoMode, mHandler.postDelayed(mAutohide, AUTOHIDE_TIMEOUT_MS); } + public void touchAutoDim() { + if (mNavigationBar != null) { + mNavigationBar.getBarTransitions().setAutoDim(false); + } + mHandler.removeCallbacks(mAutoDim); + if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED) { + mHandler.postDelayed(mAutoDim, AUTOHIDE_TIMEOUT_MS); + } + } + void checkUserAutohide(View v, MotionEvent event) { if ((mSystemUiVisibility & STATUS_OR_NAV_TRANSIENT) != 0 // a transient bar is revealed && event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar @@ -3537,6 +3589,14 @@ public class StatusBar extends SystemUI implements DemoMode, DozeLog.dump(pw); + if (mFingerprintUnlockController != null) { + mFingerprintUnlockController.dump(pw); + } + + if (mScrimController != null) { + mScrimController.dump(pw); + } + if (DUMPTRUCK) { synchronized (mNotificationData) { mNotificationData.dump(pw, " "); @@ -3623,11 +3683,13 @@ public class StatusBar extends SystemUI implements DemoMode, public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, boolean dismissShade) { - startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, null /* callback */); + startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, + false /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */); } public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, - final boolean dismissShade, final Callback callback) { + final boolean dismissShade, final boolean disallowEnterPictureInPictureWhileLaunching, + final Callback callback) { if (onlyProvisioned && !isDeviceProvisioned()) return; final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity( @@ -3640,6 +3702,8 @@ public class StatusBar extends SystemUI implements DemoMode, Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); int result = ActivityManager.START_CANCELED; ActivityOptions options = new ActivityOptions(getActivityOptions()); + options.setDisallowEnterPictureInPictureWhileLaunching( + disallowEnterPictureInPictureWhileLaunching); if (intent == KeyguardBottomAreaView.INSECURE_CAMERA_INTENT) { // Normally an activity will set it's requested rotation // animation on its window. However when launching an activity @@ -4565,7 +4629,7 @@ public class StatusBar extends SystemUI implements DemoMode, if (mKeyguardUserSwitcher != null) { mKeyguardUserSwitcher.setKeyguard(true, fromShadeLocked); } - mStatusBarView.removePendingHideExpandedRunnables(); + if (mStatusBarView != null) mStatusBarView.removePendingHideExpandedRunnables(); if (mAmbientIndicationContainer != null) { mAmbientIndicationContainer.setVisibility(View.VISIBLE); } @@ -4603,7 +4667,7 @@ public class StatusBar extends SystemUI implements DemoMode, /** * Switches theme from light to dark and vice-versa. */ - private void updateTheme() { + protected void updateTheme() { final boolean inflated = mStackScroller != null; // The system wallpaper defines if QS should be light or dark. @@ -4802,6 +4866,7 @@ public class StatusBar extends SystemUI implements DemoMode, updateReportRejectedTouchVisibility(); updateDozing(); updateTheme(); + touchAutoDim(); mNotificationShelf.setStatusBarState(state); } @@ -4943,6 +5008,11 @@ public class StatusBar extends SystemUI implements DemoMode, mNotificationPanel.setEmptyDragAmount(amount); } + @Override + public boolean isFalsingCheckNeeded() { + return mState == StatusBarState.KEYGUARD; + } + /** * If secure with redaction: Show bouncer, go to unlocked shade. * @@ -5152,9 +5222,18 @@ public class StatusBar extends SystemUI implements DemoMode, public void setBouncerShowing(boolean bouncerShowing) { mBouncerShowing = bouncerShowing; if (mStatusBarView != null) mStatusBarView.setBouncerShowing(bouncerShowing); + updateHideIconsForBouncer(true /* animate */); recomputeDisableFlags(true /* animate */); } + public void cancelCurrentTouch() { + if (mNotificationPanel.isTracking()) { + mStatusBarWindow.cancelCurrentTouch(); + if (mState == StatusBarState.SHADE) { + animateCollapsePanels(); + } + } + } WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() { @Override @@ -5247,8 +5326,7 @@ public class StatusBar extends SystemUI implements DemoMode, private void maybePrepareWakeUpFromAod() { int wakefulness = mWakefulnessLifecycle.getWakefulness(); - if (mDozing && (wakefulness == WAKEFULNESS_WAKING - || wakefulness == WAKEFULNESS_ASLEEP) && !isPulsing()) { + if (mDozing && wakefulness == WAKEFULNESS_WAKING && !isPulsing()) { mScrimController.prepareWakeUpFromAod(); } } @@ -5328,8 +5406,9 @@ public class StatusBar extends SystemUI implements DemoMode, } vibrateForCameraGesture(); if (!mStatusBarKeyguardViewManager.isShowing()) { - startActivity(KeyguardBottomAreaView.INSECURE_CAMERA_INTENT, - true /* dismissShade */); + startActivityDismissingKeyguard(KeyguardBottomAreaView.INSECURE_CAMERA_INTENT, + false /* onlyProvisioned */, true /* dismissShade */, + true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */); } else { if (!mDeviceInteractive) { // Avoid flickering of the scrim when we instant launch the camera and the bouncer @@ -5673,7 +5752,8 @@ public class StatusBar extends SystemUI implements DemoMode, protected KeyguardManager mKeyguardManager; private LockPatternUtils mLockPatternUtils; - private DeviceProvisionedController mDeviceProvisionedController; + private DeviceProvisionedController mDeviceProvisionedController + = Dependency.get(DeviceProvisionedController.class); protected SystemServicesProxy mSystemServicesProxy; // UI-specific methods @@ -6549,6 +6629,18 @@ public class StatusBar extends SystemUI implements DemoMode, mHandler.obtainMessage(msg, deviceId, 0).sendToTarget(); } + @Override + public void setTopAppHidesStatusBar(boolean topAppHidesStatusBar) { + mTopHidesStatusBar = topAppHidesStatusBar; + if (!topAppHidesStatusBar && mWereIconsJustHidden) { + // Immediately update the icon hidden state, since that should only apply if we're + // staying fullscreen. + mWereIconsJustHidden = false; + recomputeDisableFlags(true); + } + updateHideIconsForBouncer(true /* animate */); + } + protected void sendCloseSystemWindows(String reason) { try { ActivityManager.getService().closeSystemDialogs(reason); @@ -7479,4 +7571,10 @@ public class StatusBar extends SystemUI implements DemoMode, } } // End Extra BaseStatusBarMethods. + + private final Runnable mAutoDim = () -> { + if (mNavigationBar != null) { + mNavigationBar.getBarTransitions().setAutoDim(true); + } + }; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index b4b859c2409c..bbce751dcdfd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -302,6 +302,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } public void setOccluded(boolean occluded, boolean animate) { + mStatusBar.setOccluded(occluded); if (occluded && !mOccluded && mShowing) { if (mStatusBar.isInLaunchTransition()) { mOccluded = true; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java index eaa6a33b05d7..ed96b4115888 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java @@ -30,6 +30,7 @@ import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; +import android.view.WindowManager.LayoutParams; import com.android.keyguard.R; import com.android.systemui.Dumpable; @@ -230,6 +231,7 @@ public class StatusBarWindowManager implements RemoteInputController.Callback, D applyModalFlag(state); applyBrightness(state); applyHasTopUi(state); + applySleepToken(state); if (mLp.copyFrom(mLpChanged) != 0) { mWindowManager.updateViewLayout(mStatusBarView, mLp); } @@ -273,6 +275,14 @@ public class StatusBarWindowManager implements RemoteInputController.Callback, D mHasTopUiChanged = isExpanded(state); } + private void applySleepToken(State state) { + if (state.dozing) { + mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN; + } else { + mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN; + } + } + public void setKeyguardShowing(boolean showing) { mCurrentState.keyguardShowing = showing; apply(mCurrentState); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java index 03f42a6f760d..d7f11f710501 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java @@ -422,7 +422,7 @@ public class StatusBarWindowView extends FrameLayout { mFloatingActionMode.finish(); } cleanupFloatingActionModeViews(); - mFloatingToolbar = new FloatingToolbar(mContext, mFakeWindow); + mFloatingToolbar = new FloatingToolbar(mFakeWindow); final FloatingActionMode mode = new FloatingActionMode(mContext, callback, originatingView, mFloatingToolbar); mFloatingActionModeOriginatingView = originatingView; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java index 7e92edf76b74..1411a544c346 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java @@ -154,6 +154,11 @@ public class UnlockMethodCache { public void onStrongAuthStateChanged(int userId) { update(false /* updateAlways */); } + + @Override + public void onScreenTurnedOff() { + update(false /* updateAlways */); + } }; public boolean isTrustManaged() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java index 9daa199ee92a..b693ebbf09a4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java @@ -39,6 +39,7 @@ public interface BluetoothController extends CallbackController<Callback>, Dumpa int getMaxConnectionState(CachedBluetoothDevice device); int getBondState(CachedBluetoothDevice device); + CachedBluetoothDevice getLastDevice(); public interface Callback { void onBluetoothStateChange(boolean enabled); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java index fc7495213165..3b15c2b8253f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java @@ -121,6 +121,11 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa } @Override + public CachedBluetoothDevice getLastDevice() { + return mLastDevice; + } + + @Override public int getMaxConnectionState(CachedBluetoothDevice device) { return getCachedState(device).mMaxConnectionState; } @@ -296,10 +301,13 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa @Override public void run() { - mBondState = mDevice.get().getBondState(); - mMaxConnectionState = mDevice.get().getMaxConnectionState(); - mUiHandler.removeMessages(H.MSG_PAIRED_DEVICES_CHANGED); - mUiHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); + CachedBluetoothDevice device = mDevice.get(); + if (device != null) { + mBondState = device.getBondState(); + mMaxConnectionState = device.getMaxConnectionState(); + mUiHandler.removeMessages(H.MSG_PAIRED_DEVICES_CHANGED); + mUiHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java index 13ee23fb7af9..06040e2b0bcc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java @@ -28,6 +28,8 @@ import android.view.Surface; import android.view.View; import com.android.systemui.R; +import com.android.systemui.SysUiServiceProvider; +import com.android.systemui.statusbar.phone.StatusBar; /** * The "dead zone" consumes unintentional taps along the top edge of the navigation bar. @@ -44,6 +46,7 @@ public class DeadZone extends View { public static final int VERTICAL = 1; // Consume taps along the left edge. private static final boolean CHATTY = true; // print to logcat when we eat a click + private final StatusBar mStatusBar; private boolean mShouldFlash; private float mFlashFrac = 0f; @@ -88,6 +91,7 @@ public class DeadZone extends View { + (mVertical ? " vertical" : " horizontal")); setFlashOnTouchCapture(context.getResources().getBoolean(R.bool.config_dead_zone_flash)); + mStatusBar = SysUiServiceProvider.getComponent(context, StatusBar.class); } static float lerp(float a, float b, float f) { @@ -132,6 +136,7 @@ public class DeadZone extends View { if (DEBUG) { Slog.v(TAG, this + " ACTION_DOWN: " + event.getX() + "," + event.getY()); } + if (mStatusBar != null) mStatusBar.touchAutoDim(); int size = (int) getSize(event.getEventTime()); // In the vertical orientation consume taps along the left edge. // In horizontal orientation consume taps along the top edge. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java index ede8411f3c9f..cade5dc46388 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionController.java @@ -56,6 +56,7 @@ public interface ExtensionController { ExtensionBuilder<T> withDefault(Supplier<T> def); ExtensionBuilder<T> withCallback(Consumer<T> callback); ExtensionBuilder<T> withUiMode(int mode, Supplier<T> def); + ExtensionBuilder<T> withFeature(String feature, Supplier<T> def); Extension build(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java index cc10775a8385..6d75cfcb38f3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java @@ -38,8 +38,9 @@ public class ExtensionControllerImpl implements ExtensionController { public static final int SORT_ORDER_PLUGIN = 0; public static final int SORT_ORDER_TUNER = 1; - public static final int SORT_ORDER_UI_MODE = 2; - public static final int SORT_ORDER_DEFAULT = 3; + public static final int SORT_ORDER_FEATURE = 2; + public static final int SORT_ORDER_UI_MODE = 3; + public static final int SORT_ORDER_DEFAULT = 4; private final Context mDefaultContext; @@ -92,6 +93,7 @@ public class ExtensionControllerImpl implements ExtensionController { return this; } + @Override public ExtensionController.ExtensionBuilder<T> withUiMode(int uiMode, Supplier<T> supplier) { mExtension.addUiMode(uiMode, supplier); @@ -99,6 +101,13 @@ public class ExtensionControllerImpl implements ExtensionController { } @Override + public ExtensionController.ExtensionBuilder<T> withFeature(String feature, + Supplier<T> supplier) { + mExtension.addFeature(feature, supplier); + return this; + } + + @Override public ExtensionController.ExtensionBuilder<T> withCallback( Consumer<T> callback) { mExtension.mCallbacks.add(callback); @@ -107,7 +116,7 @@ public class ExtensionControllerImpl implements ExtensionController { @Override public ExtensionController.Extension build() { - // Manually sort, plugins first, tuners second, defaults last. + // Sort items in ascending order Collections.sort(mExtension.mProducers, Comparator.comparingInt(Item::sortOrder)); mExtension.notifyChanged(); return mExtension; @@ -188,6 +197,10 @@ public class ExtensionControllerImpl implements ExtensionController { mProducers.add(new UiModeItem(uiMode, mode)); } + public void addFeature(String feature, Supplier<T> mode) { + mProducers.add(new FeatureItem<>(feature, mode)); + } + private class PluginItem<P extends Plugin> implements Item<T>, PluginListener<P> { private final PluginConverter<T, P> mConverter; private T mItem; @@ -305,6 +318,32 @@ public class ExtensionControllerImpl implements ExtensionController { } } + private class FeatureItem<T> implements Item<T> { + private final String mFeature; + private final Supplier<T> mSupplier; + + public FeatureItem(String feature, Supplier<T> supplier) { + mSupplier = supplier; + mFeature = feature; + } + + @Override + public T get() { + return mDefaultContext.getPackageManager().hasSystemFeature(mFeature) + ? mSupplier.get() : null; + } + + @Override + public void destroy() { + + } + + @Override + public int sortOrder() { + return SORT_ORDER_FEATURE; + } + } + private class Default<T> implements Item<T> { private final Supplier<T> mSupplier; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java index 65bfabd19fbb..05017718d42b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java @@ -304,11 +304,6 @@ public class KeyButtonView extends ImageView implements ButtonInterface { public void setVertical(boolean vertical) { //no op } - - @Override - public void setCarMode(boolean carMode) { - // no op - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index 188f21600925..4e592dbed322 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -40,6 +40,7 @@ import android.os.Bundle; import android.os.Handler; import android.service.notification.StatusBarNotification; import android.support.annotation.NonNull; +import android.support.annotation.VisibleForTesting; import android.util.AttributeSet; import android.util.FloatProperty; import android.util.Log; @@ -3545,6 +3546,7 @@ public class NotificationStackScrollLayout extends ViewGroup * See {@link AmbientState#setDimmed}. */ public void setDimmed(boolean dimmed, boolean animate) { + dimmed &= onKeyguard(); mAmbientState.setDimmed(dimmed); if (animate && mAnimationsEnabled) { mDimmedNeedsAnimation = true; @@ -3556,6 +3558,11 @@ public class NotificationStackScrollLayout extends ViewGroup requestChildrenUpdate(); } + @VisibleForTesting + boolean isDimmed() { + return mAmbientState.isDimmed(); + } + private void setDimAmount(float dimAmount) { mDimAmount = dimAmount; updateBackgroundDimming(); @@ -4539,7 +4546,10 @@ public class NotificationStackScrollLayout extends ViewGroup anim.start(); } } else if (mMenuExposedView instanceof ExpandableNotificationRow) { - ((ExpandableNotificationRow) mMenuExposedView).resetTranslation(); + ExpandableNotificationRow row = (ExpandableNotificationRow) mMenuExposedView; + if (!row.isRemoved()) { + row.resetTranslation(); + } } mMenuExposedView = null; } diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerZenModePanel.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerZenModePanel.java index 1ea23bb65107..4d95969a63b5 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerZenModePanel.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerZenModePanel.java @@ -22,9 +22,11 @@ import android.provider.Settings.Global; import android.util.AttributeSet; import android.view.View; import android.view.View.OnClickListener; +import android.view.ViewGroup; import android.widget.Checkable; import android.widget.LinearLayout; import android.widget.TextView; + import com.android.systemui.Prefs; import com.android.systemui.R; import com.android.systemui.statusbar.policy.ZenModeController; @@ -65,6 +67,11 @@ public class TunerZenModePanel extends LinearLayout implements OnClickListener { mDone = mButtons.findViewById(android.R.id.button1); mDone.setOnClickListener(this); ((TextView) mDone).setText(R.string.quick_settings_done); + // Hide the resizing space because it causes issues in the volume panel. + ViewGroup detail_header = findViewById(R.id.tuner_zen_switch); + detail_header.getChildAt(0).setVisibility(View.GONE); + // No background so it can blend with volume panel. + findViewById(R.id.edit_container).setBackground(null); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java index f5447a293503..3ebefbb50fb9 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java @@ -31,8 +31,12 @@ import android.os.ServiceManager; import android.os.SystemProperties; import android.util.Log; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; +import android.view.Window; +import android.view.WindowManager; import android.widget.CheckBox; +import android.widget.Toast; import com.android.internal.app.AlertActivity; import com.android.internal.app.AlertController; @@ -48,6 +52,10 @@ public class UsbDebuggingActivity extends AlertActivity @Override public void onCreate(Bundle icicle) { + Window window = getWindow(); + window.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); + window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); + super.onCreate(icicle); if (SystemProperties.getInt("service.adb.tcp.port", 0) == 0) { @@ -79,6 +87,29 @@ public class UsbDebuggingActivity extends AlertActivity ap.mView = checkbox; setupAlert(); + + // adding touch listener on affirmative button - checks if window is obscured + // if obscured, do not let user give permissions (could be tapjacking involved) + final View.OnTouchListener filterTouchListener = (View v, MotionEvent event) -> { + // Filter obscured touches by consuming them. + if (((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) + || ((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED) != 0)) { + if (event.getAction() == MotionEvent.ACTION_UP) { + Toast.makeText(v.getContext(), + R.string.touch_filtered_warning, + Toast.LENGTH_SHORT).show(); + } + return true; + } + return false; + }; + mAlert.getButton(BUTTON_POSITIVE).setOnTouchListener(filterTouchListener); + + } + + @Override + public void onWindowAttributesChanged(WindowManager.LayoutParams params) { + super.onWindowAttributesChanged(params); } private class UsbDisconnectedReceiver extends BroadcastReceiver { diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index 6e631fa9b926..0fd6c7440c94 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -298,7 +298,8 @@ public class VolumeDialogImpl implements VolumeDialog, TunerService.Tunable { } private void updateWindowWidthH() { - final ViewGroup.LayoutParams lp = mDialogView.getLayoutParams(); + final ViewGroup.MarginLayoutParams lp = + (ViewGroup.MarginLayoutParams) mDialogView.getLayoutParams(); final DisplayMetrics dm = mContext.getResources().getDisplayMetrics(); if (D.BUG) Log.d(TAG, "updateWindowWidth dm.w=" + dm.widthPixels); int w = dm.widthPixels; @@ -307,7 +308,7 @@ public class VolumeDialogImpl implements VolumeDialog, TunerService.Tunable { if (w > max) { w = max; } - lp.width = w; + lp.width = w - lp.getMarginEnd() - lp.getMarginStart(); mDialogView.setLayoutParams(lp); } @@ -713,6 +714,8 @@ public class VolumeDialogImpl implements VolumeDialog, TunerService.Tunable { final boolean visible = mState.zenMode != Global.ZEN_MODE_OFF && (mAudioManager.isStreamAffectedByRingerMode(mActiveStream) || mExpanded) && !mZenPanel.isEditing(); + + TransitionManager.endTransitions(mDialogView); TransitionManager.beginDelayedTransition(mDialogView, getTransition()); if (wasVisible != visible && !visible) { prepareForCollapse(); @@ -840,6 +843,11 @@ public class VolumeDialogImpl implements VolumeDialog, TunerService.Tunable { row.icon.setContentDescription(getStreamLabelH(ss)); } + // ensure tracking is disabled if zenMuted + if (zenMuted) { + row.tracking = false; + } + // update slider final boolean enableSlider = !zenMuted; final int vlevel = row.ss.muted && (!isRingStream && !zenMuted) ? 0 diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenRadioLayout.java b/packages/SystemUI/src/com/android/systemui/volume/ZenRadioLayout.java index 5dbcd8a73aac..360907b0d22b 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/ZenRadioLayout.java +++ b/packages/SystemUI/src/com/android/systemui/volume/ZenRadioLayout.java @@ -46,9 +46,16 @@ public class ZenRadioLayout extends LinearLayout { throw new IllegalStateException("Expected matching children"); } boolean hasChanges = false; + View lastView = null; for (int i = 0; i < size; i++) { View radio = radioGroup.getChildAt(i); View content = radioContent.getChildAt(i); + if (lastView != null) { + radio.setAccessibilityTraversalAfter(lastView.getId()); + } + View contentClick = findFirstClickable(content); + if (contentClick != null) contentClick.setAccessibilityTraversalAfter(radio.getId()); + lastView = findLastClickable(content); if (radio.getLayoutParams().height != content.getMeasuredHeight()) { hasChanges = true; radio.getLayoutParams().height = content.getMeasuredHeight(); @@ -59,4 +66,28 @@ public class ZenRadioLayout extends LinearLayout { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } + + private View findFirstClickable(View content) { + if (content.isClickable()) return content; + if (content instanceof ViewGroup) { + ViewGroup group = (ViewGroup) content; + for (int i = 0; i < group.getChildCount(); i++) { + View v = findFirstClickable(group.getChildAt(i)); + if (v != null) return v; + } + } + return null; + } + + private View findLastClickable(View content) { + if (content.isClickable()) return content; + if (content instanceof ViewGroup) { + ViewGroup group = (ViewGroup) content; + for (int i = group.getChildCount() - 1; i >= 0; i--) { + View v = findLastClickable(group.getChildAt(i)); + if (v != null) return v; + } + } + return null; + } } diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk index 5e71dd4684c5..27c16d53ce78 100644 --- a/packages/SystemUI/tests/Android.mk +++ b/packages/SystemUI/tests/Android.mk @@ -54,7 +54,8 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ SystemUI-proto \ SystemUI-tags \ legacy-android-test \ - testables + testables \ + truth-prebuilt \ LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common android.car diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml index adb3baf40bb3..67fae5bb0dfb 100644 --- a/packages/SystemUI/tests/AndroidManifest.xml +++ b/packages/SystemUI/tests/AndroidManifest.xml @@ -42,6 +42,7 @@ <uses-permission android:name="android.permission.TRUST_LISTENER" /> <uses-permission android:name="android.permission.USE_FINGERPRINT" /> <uses-permission android:name="android.permission.DEVICE_POWER" /> + <uses-permission android:name="android.permission.READ_CONTACTS" /> <application> <uses-library android:name="android.test.runner" /> diff --git a/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java b/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java index d0f0bfd88883..6417eb706f7c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java +++ b/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java @@ -17,6 +17,7 @@ package com.android.systemui.colorextraction; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import android.app.WallpaperColors; import android.app.WallpaperManager; @@ -25,7 +26,6 @@ import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import com.android.internal.colorextraction.ColorExtractor; -import com.android.internal.colorextraction.types.Tonal; import com.android.systemui.SysuiTestCase; import org.junit.Test; @@ -48,18 +48,21 @@ public class SysuiColorExtractorTests extends SysuiTestCase { @Test public void getColors_usesGreyIfWallpaperNotVisible() { - SysuiColorExtractor extractor = new SysuiColorExtractor(getContext(), - new Tonal(getContext()), false); + ColorExtractor.GradientColors colors = new ColorExtractor.GradientColors(); + colors.setMainColor(Color.RED); + colors.setSecondaryColor(Color.RED); + + SysuiColorExtractor extractor = getTestableExtractor(colors); simulateEvent(extractor); extractor.setWallpaperVisible(false); ColorExtractor.GradientColors fallbackColors = extractor.getFallbackColors(); - for (int which : sWhich) { - for (int type : sTypes) { - assertEquals("Not using fallback!", extractor.getColors(which, type), - fallbackColors); - } + for (int type : sTypes) { + assertEquals("Not using fallback!", + extractor.getColors(WallpaperManager.FLAG_SYSTEM, type), fallbackColors); + assertNotEquals("Wallpaper visibility event should not affect lock wallpaper.", + extractor.getColors(WallpaperManager.FLAG_LOCK, type), fallbackColors); } } @@ -69,13 +72,7 @@ public class SysuiColorExtractorTests extends SysuiTestCase { colors.setMainColor(Color.RED); colors.setSecondaryColor(Color.RED); - SysuiColorExtractor extractor = new SysuiColorExtractor(getContext(), - (inWallpaperColors, outGradientColorsNormal, outGradientColorsDark, - outGradientColorsExtraDark) -> { - outGradientColorsNormal.set(colors); - outGradientColorsDark.set(colors); - outGradientColorsExtraDark.set(colors); - }, false); + SysuiColorExtractor extractor = getTestableExtractor(colors); simulateEvent(extractor); extractor.setWallpaperVisible(true); @@ -87,6 +84,16 @@ public class SysuiColorExtractorTests extends SysuiTestCase { } } + private SysuiColorExtractor getTestableExtractor(ColorExtractor.GradientColors colors) { + return new SysuiColorExtractor(getContext(), + (inWallpaperColors, outGradientColorsNormal, outGradientColorsDark, + outGradientColorsExtraDark) -> { + outGradientColorsNormal.set(colors); + outGradientColorsDark.set(colors); + outGradientColorsExtraDark.set(colors); + }, false); + } + private void simulateEvent(SysuiColorExtractor extractor) { // Let's fake a color event extractor.onColorsChanged(new WallpaperColors(Color.valueOf(Color.GREEN), null, null, 0), diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/AlwaysOnDisplayPolicyTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/AlwaysOnDisplayPolicyTest.java new file mode 100644 index 000000000000..abc2d0e5c845 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/AlwaysOnDisplayPolicyTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.doze; + +import static com.google.common.truth.Truth.assertThat; + +import android.provider.Settings; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; +import android.text.format.DateUtils; + +import com.android.systemui.R; +import com.android.systemui.SysuiTestCase; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class AlwaysOnDisplayPolicyTest extends SysuiTestCase { + private static final String ALWAYS_ON_DISPLAY_CONSTANTS_VALUE = "prox_screen_off_delay=1000" + + ",prox_cooldown_trigger=2000" + + ",prox_cooldown_period=3000" + + ",screen_brightness_array=1:2:3:4:5" + + ",dimming_scrim_array=5:4:3:2:1"; + + private String mPreviousConfig; + + @Before + public void setUp() { + mPreviousConfig = Settings.Global.getString(mContext.getContentResolver(), + Settings.Global.ALWAYS_ON_DISPLAY_CONSTANTS); + } + + @After + public void tearDown() { + Settings.Global.putString(mContext.getContentResolver(), + Settings.Global.ALWAYS_ON_DISPLAY_CONSTANTS, mPreviousConfig); + } + + @Test + public void testPolicy_valueNull_containsDefaultValue() throws Exception { + Settings.Global.putString(mContext.getContentResolver(), + Settings.Global.ALWAYS_ON_DISPLAY_CONSTANTS, null); + + AlwaysOnDisplayPolicy policy = new AlwaysOnDisplayPolicy(mContext); + + assertThat(policy.proxScreenOffDelayMs).isEqualTo(10 * DateUtils.MINUTE_IN_MILLIS); + assertThat(policy.proxCooldownTriggerMs).isEqualTo(2 * DateUtils.MINUTE_IN_MILLIS); + assertThat(policy.proxCooldownPeriodMs).isEqualTo(5 * DateUtils.MINUTE_IN_MILLIS); + assertThat(policy.screenBrightnessArray).isEqualTo(mContext.getResources().getIntArray( + R.array.config_doze_brightness_sensor_to_brightness)); + assertThat(policy.dimmingScrimArray).isEqualTo(mContext.getResources().getIntArray( + R.array.config_doze_brightness_sensor_to_scrim_opacity)); + } + + @Test + public void testPolicy_valueNotNull_containsValue() throws Exception { + Settings.Global.putString(mContext.getContentResolver(), + Settings.Global.ALWAYS_ON_DISPLAY_CONSTANTS, ALWAYS_ON_DISPLAY_CONSTANTS_VALUE); + + AlwaysOnDisplayPolicy policy = new AlwaysOnDisplayPolicy(mContext); + + assertThat(policy.proxScreenOffDelayMs).isEqualTo(1000); + assertThat(policy.proxCooldownTriggerMs).isEqualTo(2000); + assertThat(policy.proxCooldownPeriodMs).isEqualTo(3000); + assertThat(policy.screenBrightnessArray).isEqualTo(new int[]{1, 2, 3, 4, 5}); + assertThat(policy.dimmingScrimArray).isEqualTo(new int[]{5, 4, 3, 2, 1}); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java index c2758068a4ed..46e1d5562714 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java @@ -60,7 +60,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mSensorManager = new FakeSensorManager(mContext); mSensor = mSensorManager.getFakeLightSensor(); mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager, - mSensor.getSensor(), mHostFake, null /* handler */); + mSensor.getSensor(), mHostFake, null /* handler */, + new AlwaysOnDisplayPolicy(mContext)); } @Test @@ -135,7 +136,8 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { @Test public void testNullSensor() throws Exception { mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager, - null /* sensor */, mHostFake, null /* handler */); + null /* sensor */, mHostFake, null /* handler */, + new AlwaysOnDisplayPolicy(mContext)); mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java index c787eff8a6ec..521d2e342218 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java @@ -20,23 +20,22 @@ import static com.android.systemui.doze.DozeMachine.State.DOZE; import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD; import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSING; import static com.android.systemui.doze.DozeMachine.State.DOZE_REQUEST_PULSE; +import static com.android.systemui.doze.DozeMachine.State.FINISH; import static com.android.systemui.doze.DozeMachine.State.INITIALIZED; import static com.android.systemui.doze.DozeMachine.State.UNINITIALIZED; +import static com.android.systemui.utils.os.FakeHandler.Mode.QUEUEING; import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; -import android.os.Handler; import android.os.Looper; -import android.os.Message; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.view.Display; import com.android.systemui.SysuiTestCase; +import com.android.systemui.utils.os.FakeHandler; import org.junit.Before; import org.junit.Test; @@ -48,13 +47,13 @@ public class DozeScreenStateTest extends SysuiTestCase { DozeServiceFake mServiceFake; DozeScreenState mScreen; - private ImmediateHandler mHandler; + FakeHandler mHandlerFake; @Before public void setUp() throws Exception { mServiceFake = new DozeServiceFake(); - mHandler = spy(new ImmediateHandler(Looper.getMainLooper())); - mScreen = new DozeScreenState(mServiceFake, mHandler); + mHandlerFake = new FakeHandler(Looper.getMainLooper()); + mScreen = new DozeScreenState(mServiceFake, mHandlerFake); } @Test @@ -105,27 +104,34 @@ public class DozeScreenStateTest extends SysuiTestCase { } @Test - public void test_postedToHandler() { + public void test_initialScreenStatePostedToHandler() { + mHandlerFake.setMode(QUEUEING); + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mServiceFake.screenStateSet = false; mScreen.transitionTo(INITIALIZED, DOZE_AOD); - verify(mHandler).sendMessageAtTime(any(), anyLong()); + assertFalse(mServiceFake.screenStateSet); + + mHandlerFake.dispatchQueuedMessages(); + + assertTrue(mServiceFake.screenStateSet); + assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState); } - private static class ImmediateHandler extends Handler { - - public ImmediateHandler(Looper looper) { - super(looper); - } - - @Override - public boolean sendMessageAtTime(Message msg, long uptimeMillis) { - Runnable callback = msg.getCallback(); - if (callback != null) { - callback.run(); - return false; - } - return super.sendMessageAtTime(msg, uptimeMillis); - } + @Test + public void test_noScreenStateSetAfterFinish() { + mHandlerFake.setMode(QUEUEING); + + mScreen.transitionTo(UNINITIALIZED, INITIALIZED); + mScreen.transitionTo(INITIALIZED, DOZE_AOD); + mScreen.transitionTo(DOZE_AOD, FINISH); + + mServiceFake.screenStateSet = false; + + mHandlerFake.dispatchQueuedMessages(); + + assertFalse(mServiceFake.screenStateSet); } + }
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java index 34026b0b6145..75f97a2efa8f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java @@ -19,10 +19,16 @@ package com.android.systemui.doze; import android.os.PowerManager; import android.view.Display; +/** + * Fake implementation of {@link DozeMachine.Service} for tests. + * + * Useful instead of mocking because it allows verifying state instead of interactions. + */ public class DozeServiceFake implements DozeMachine.Service { public boolean finished; public int screenState; + public boolean screenStateSet; public boolean requestedWakeup; public int screenBrightness; @@ -38,6 +44,7 @@ public class DozeServiceFake implements DozeMachine.Service { @Override public void setDozeScreenState(int state) { screenState = state; + screenStateSet = true; } @Override @@ -53,6 +60,8 @@ public class DozeServiceFake implements DozeMachine.Service { public void reset() { finished = false; screenState = Display.STATE_UNKNOWN; + screenStateSet = false; + requestedWakeup = false; screenBrightness = PowerManager.BRIGHTNESS_DEFAULT; } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java index bba982c3b060..94dbc2ad7147 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java @@ -26,6 +26,8 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; +import android.support.test.annotation.UiThreadTest; +import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -34,10 +36,11 @@ import android.testing.TestableLooper.RunWithLooper; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.systemui.Dependency; import com.android.systemui.SysuiTestCase; -import com.android.systemui.plugins.PluginInstanceManager.PluginInfo; import com.android.systemui.plugins.annotations.ProvidesInterface; +import com.android.systemui.plugins.PluginInstanceManager.PluginInfo; import com.android.systemui.plugins.PluginManagerImpl.PluginInstanceManagerFactory; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -64,7 +67,7 @@ public class PluginManagerTest extends SysuiTestCase { public void setup() throws Exception { mDependency.injectTestDependency(Dependency.BG_LOOPER, TestableLooper.get(this).getLooper()); - mRealExceptionHandler = Thread.getDefaultUncaughtExceptionHandler(); + mRealExceptionHandler = Thread.getUncaughtExceptionPreHandler(); mMockExceptionHandler = mock(UncaughtExceptionHandler.class); mMockFactory = mock(PluginInstanceManagerFactory.class); mMockPluginInstance = mock(PluginInstanceManager.class); @@ -164,9 +167,9 @@ public class PluginManagerTest extends SysuiTestCase { } private void resetExceptionHandler() { - mPluginExceptionHandler = Thread.getDefaultUncaughtExceptionHandler(); + mPluginExceptionHandler = Thread.getUncaughtExceptionPreHandler(); // Set back the real exception handler so the test can crash if it wants to. - Thread.setDefaultUncaughtExceptionHandler(mRealExceptionHandler); + Thread.setUncaughtExceptionPreHandler(mRealExceptionHandler); } @ProvidesInterface(action = TestPlugin.ACTION, version = TestPlugin.VERSION) diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java index a8487b3eff4e..4f98836eeec7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java @@ -29,6 +29,7 @@ import android.provider.Settings; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.SmallTest; import android.text.SpannableStringBuilder; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; @@ -395,6 +396,57 @@ public class QSSecurityFooterTest extends SysuiTestCase { mFooter.getVpnMessage(false, true, VPN_PACKAGE, null)); } + @Test + public void testConfigSubtitleVisibility() { + View view = LayoutInflater.from(mContext) + .inflate(R.layout.quick_settings_footer_dialog, null); + + // Device Management subtitle should be shown when there is Device Management section only + // Other sections visibility will be set somewhere else so it will not be tested here + mFooter.configSubtitleVisibility(true, false, false, false, view); + assertEquals(View.VISIBLE, + view.findViewById(R.id.device_management_subtitle).getVisibility()); + + // If there are multiple sections, all subtitles should be shown + mFooter.configSubtitleVisibility(true, true, false, false, view); + assertEquals(View.VISIBLE, + view.findViewById(R.id.device_management_subtitle).getVisibility()); + assertEquals(View.VISIBLE, + view.findViewById(R.id.ca_certs_subtitle).getVisibility()); + + // If there are multiple sections, all subtitles should be shown + mFooter.configSubtitleVisibility(true, true, true, true, view); + assertEquals(View.VISIBLE, + view.findViewById(R.id.device_management_subtitle).getVisibility()); + assertEquals(View.VISIBLE, + view.findViewById(R.id.ca_certs_subtitle).getVisibility()); + assertEquals(View.VISIBLE, + view.findViewById(R.id.network_logging_subtitle).getVisibility()); + assertEquals(View.VISIBLE, + view.findViewById(R.id.vpn_subtitle).getVisibility()); + + // If there are multiple sections, all subtitles should be shown, event if there is no + // Device Management section + mFooter.configSubtitleVisibility(false, true, true, true, view); + assertEquals(View.VISIBLE, + view.findViewById(R.id.ca_certs_subtitle).getVisibility()); + assertEquals(View.VISIBLE, + view.findViewById(R.id.network_logging_subtitle).getVisibility()); + assertEquals(View.VISIBLE, + view.findViewById(R.id.vpn_subtitle).getVisibility()); + + // If there is only 1 section, the title should be hidden + mFooter.configSubtitleVisibility(false, true, false, false, view); + assertEquals(View.GONE, + view.findViewById(R.id.ca_certs_subtitle).getVisibility()); + mFooter.configSubtitleVisibility(false, false, true, false, view); + assertEquals(View.GONE, + view.findViewById(R.id.network_logging_subtitle).getVisibility()); + mFooter.configSubtitleVisibility(false, false, false, true, view); + assertEquals(View.GONE, + view.findViewById(R.id.vpn_subtitle).getVisibility()); + } + private CharSequence addLink(CharSequence description) { final SpannableStringBuilder message = new SpannableStringBuilder(); message.append(description); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/car/CarQsFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/car/CarQsFragmentTest.java index f770631ceb7c..4f87b02ed35f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/car/CarQsFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/car/CarQsFragmentTest.java @@ -28,7 +28,6 @@ import com.android.keyguard.CarrierText; import com.android.systemui.Dependency; import com.android.systemui.SysuiBaseFragmentTest; import com.android.systemui.statusbar.policy.Clock; -import com.android.systemui.statusbar.policy.UserSwitcherController; import org.junit.Before; import org.junit.Test; @@ -58,8 +57,6 @@ public class CarQsFragmentTest extends SysuiBaseFragmentTest { mDependency.injectTestDependency(Dependency.BG_LOOPER, TestableLooper.get(this).getLooper()); - mDependency.injectMockDependency(UserSwitcherController.class); - injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java index fb64a7f7f425..54a96cd76715 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java @@ -198,6 +198,18 @@ public class NotificationInflaterTest extends SysuiTestCase { runningTask.abort(); } + @Test + public void doesntReapplyDisallowedRemoteView() throws Exception { + mBuilder.setStyle(new Notification.MediaStyle()); + RemoteViews mediaView = mBuilder.createContentView(); + mBuilder.setStyle(new Notification.DecoratedCustomViewStyle()); + mBuilder.setCustomContentView(new RemoteViews(getContext().getPackageName(), + R.layout.custom_view_dark)); + RemoteViews decoratedMediaView = mBuilder.createContentView(); + Assert.assertFalse("The decorated media style doesn't allow a view to be reapplied!", + NotificationInflater.canReapplyRemoteView(mediaView, decoratedMediaView)); + } + public static void runThenWaitForInflation(Runnable block, NotificationInflater inflater) throws Exception { runThenWaitForInflation(block, false /* expectingException */, inflater); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarTransitionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarTransitionsTest.java new file mode 100644 index 000000000000..0c1baaa1b476 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarTransitionsTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package com.android.systemui.statusbar.phone; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.support.test.filters.SmallTest; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper.RunWithLooper; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.statusbar.CommandQueue; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidTestingRunner.class) +@RunWithLooper +@SmallTest +public class NavigationBarTransitionsTest extends SysuiTestCase { + + private NavigationBarTransitions mTransitions; + + @Before + public void setup() { + mContext.putComponent(CommandQueue.class, mock(CommandQueue.class)); + NavigationBarView navBar = spy(new NavigationBarView(mContext, null)); + when(navBar.getCurrentView()).thenReturn(navBar); + when(navBar.findViewById(anyInt())).thenReturn(navBar); + mTransitions = new NavigationBarTransitions(navBar); + } + + @Test + public void setIsLightsOut_NoAutoDim() { + mTransitions.setAutoDim(false); + + assertFalse(mTransitions.isLightsOut(BarTransitions.MODE_OPAQUE)); + + assertTrue(mTransitions.isLightsOut(BarTransitions.MODE_LIGHTS_OUT)); + } + + @Test + public void setIsLightsOut_AutoDim() { + mTransitions.setAutoDim(true); + + assertTrue(mTransitions.isLightsOut(BarTransitions.MODE_OPAQUE)); + + assertTrue(mTransitions.isLightsOut(BarTransitions.MODE_LIGHTS_OUT)); + } + +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index a706368a0880..ac367d20b5c8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -26,21 +26,19 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; -import static org.mockito.Mockito.when; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.app.Notification; import android.app.trust.TrustManager; +import android.content.Context; import android.hardware.fingerprint.FingerprintManager; import android.metrics.LogMaker; +import android.os.Binder; import android.os.Handler; import android.os.HandlerThread; import android.os.IPowerManager; @@ -51,20 +49,25 @@ import android.os.UserHandle; import android.service.notification.StatusBarNotification; import android.support.test.filters.SmallTest; import android.support.test.metricshelper.MetricsAsserts; -import android.support.test.runner.AndroidJUnit4; import android.testing.AndroidTestingRunner; +import android.testing.LayoutInflaterBuilder; import android.testing.TestableLooper; import android.testing.TestableLooper.MessageHandler; import android.testing.TestableLooper.RunWithLooper; import android.util.DisplayMetrics; +import android.view.View; import android.view.ViewGroup.LayoutParams; +import android.widget.FrameLayout; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.testing.FakeMetricsLogger; import com.android.internal.statusbar.IStatusBarService; import com.android.keyguard.KeyguardHostView.OnDismissAction; +import com.android.keyguard.KeyguardStatusView; +import com.android.systemui.R; import com.android.systemui.SysuiTestCase; +import com.android.systemui.assist.AssistManager; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.statusbar.ActivatableNotificationView; @@ -73,7 +76,11 @@ import com.android.systemui.statusbar.KeyguardIndicationController; import com.android.systemui.statusbar.NotificationData; import com.android.systemui.statusbar.NotificationData.Entry; import com.android.systemui.statusbar.StatusBarState; +import com.android.systemui.statusbar.policy.DateView; +import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.HeadsUpManager; +import com.android.systemui.statusbar.policy.KeyguardMonitor; +import com.android.systemui.statusbar.policy.KeyguardMonitorImpl; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; import org.junit.Before; @@ -106,12 +113,20 @@ public class StatusBarTest extends SysuiTestCase { @Before public void setup() throws Exception { + mContext.setTheme(R.style.Theme_SystemUI_Light); + mDependency.injectMockDependency(AssistManager.class); + mDependency.injectMockDependency(DeviceProvisionedController.class); + mDependency.injectTestDependency(KeyguardMonitor.class, mock(KeyguardMonitorImpl.class)); + CommandQueue commandQueue = mock(CommandQueue.class); + when(commandQueue.asBinder()).thenReturn(new Binder()); + mContext.putComponent(CommandQueue.class, commandQueue); mContext.addMockSystemService(TrustManager.class, mock(TrustManager.class)); mContext.addMockSystemService(FingerprintManager.class, mock(FingerprintManager.class)); mStatusBarKeyguardViewManager = mock(StatusBarKeyguardViewManager.class); mUnlockMethodCache = mock(UnlockMethodCache.class); mKeyguardIndicationController = mock(KeyguardIndicationController.class); mStackScroller = mock(NotificationStackScrollLayout.class); + when(mStackScroller.generateLayoutParams(any())).thenReturn(new LayoutParams(0, 0)); mMetricsLogger = new FakeMetricsLogger(); mHeadsUpManager = mock(HeadsUpManager.class); mNotificationData = mock(NotificationData.class); @@ -133,6 +148,7 @@ public class StatusBarTest extends SysuiTestCase { mNotificationData, mPowerManager, mSystemServicesProxy, mNotificationPanelView, mBarService); mStatusBar.mContext = mContext; + mStatusBar.mComponents = mContext.getComponents(); doAnswer(invocation -> { OnDismissAction onDismissAction = (OnDismissAction) invocation.getArguments()[0]; onDismissAction.onDismiss(); @@ -484,6 +500,16 @@ public class StatusBarTest extends SysuiTestCase { mStatusBar.dump(null, new PrintWriter(new ByteArrayOutputStream()), null); } + @Test + @RunWithLooper(setAsMainLooper = true) + public void testUpdateKeyguardState_DoesNotCrash() { + mStatusBar.mStatusBarWindow = mock(StatusBarWindowView.class); + mStatusBar.mState = StatusBarState.KEYGUARD; + mStatusBar.mDozeScrimController = mock(DozeScrimController.class); + mStatusBar.mNotificationIconAreaController = mock(NotificationIconAreaController.class); + mStatusBar.updateKeyguardState(false, false); + } + static class TestableStatusBar extends StatusBar { public TestableStatusBar(StatusBarKeyguardViewManager man, UnlockMethodCache unlock, KeyguardIndicationController key, @@ -502,6 +528,7 @@ public class StatusBarTest extends SysuiTestCase { mNotificationPanel = panelView; mBarService = barService; mWakefulnessLifecycle = createAwakeWakefulnessLifecycle(); + mScrimController = mock(ScrimController.class); } private WakefulnessLifecycle createAwakeWakefulnessLifecycle() { @@ -511,6 +538,11 @@ public class StatusBarTest extends SysuiTestCase { return wakefulnessLifecycle; } + @Override + protected void updateTheme() { + // Do nothing for now, until we have more mocking and StatusBar is smaller. + } + public void setBarStateForTest(int state) { mState = state; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java index 4cc8bcae541a..4e7550b20659 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java @@ -137,4 +137,26 @@ public class BluetoothControllerImplTest extends SysuiTestCase { verify(callback).onBluetoothDevicesChanged(); mainLooper.destroy(); } + + @Test + public void testNullAsync_DoesNotCrash() throws Exception { + CachedBluetoothDevice device = mock(CachedBluetoothDevice.class); + when(device.getMaxConnectionState()).thenReturn(BluetoothProfile.STATE_CONNECTED); + BluetoothController.Callback callback = mock(BluetoothController.Callback.class); + mBluetoothControllerImpl.addCallback(callback); + + // Grab the main looper, we'll need it later. + TestableLooper mainLooper = new TestableLooper(Looper.getMainLooper()); + + try { + // Trigger the state getting. + assertEquals(BluetoothProfile.STATE_DISCONNECTED, + mBluetoothControllerImpl.getMaxConnectionState(null)); + + mTestableLooper.processMessages(1); + mainLooper.processAllMessages(); + } finally { + mainLooper.destroy(); + } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java index a8319a8ee538..bb7b197c2a05 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java @@ -21,6 +21,8 @@ import android.net.ConnectivityManager; import android.net.NetworkCapabilities; import android.net.wifi.WifiManager; import android.os.Looper; +import android.provider.Settings; +import android.provider.Settings.Global; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SignalStrength; @@ -105,6 +107,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { @Before public void setUp() throws Exception { + Settings.Global.putInt(mContext.getContentResolver(), Global.AIRPLANE_MODE_ON, 0); mMockWm = mock(WifiManager.class); mMockTm = mock(TelephonyManager.class); mMockSm = mock(SubscriptionManager.class); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java new file mode 100644 index 000000000000..1c010b66056a --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.systemui.statusbar.stack; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.annotation.UiThread; +import android.support.test.annotation.UiThreadTest; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; +import android.view.NotificationHeaderView; +import android.view.View; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.statusbar.NotificationTestHelper; +import com.android.systemui.statusbar.StatusBarState; +import com.android.systemui.statusbar.phone.ScrimController; +import com.android.systemui.statusbar.phone.StatusBar; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class NotificationStackScrollLayoutTest extends SysuiTestCase { + + private NotificationStackScrollLayout mStackScroller; + private StatusBar mBar; + + @Before + @UiThreadTest + public void setUp() throws Exception { + mStackScroller = new NotificationStackScrollLayout(getContext()); + mBar = mock(StatusBar.class); + mStackScroller.setStatusBar(mBar); + mStackScroller.setScrimController(mock(ScrimController.class)); + } + + @Test + public void testNotDimmedOnKeyguard() { + when(mBar.getBarState()).thenReturn(StatusBarState.SHADE); + mStackScroller.setDimmed(true /* dimmed */, false /* animate */); + mStackScroller.setDimmed(true /* dimmed */, true /* animate */); + Assert.assertFalse(mStackScroller.isDimmed()); + } + +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBluetoothController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBluetoothController.java index 9ec096ad49e0..44c49835def4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBluetoothController.java +++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBluetoothController.java @@ -93,4 +93,9 @@ public class FakeBluetoothController extends BaseLeakChecker<Callback> implement public int getBondState(CachedBluetoothDevice device) { return 0; } + + @Override + public CachedBluetoothDevice getLastDevice() { + return null; + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeExtensionController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeExtensionController.java index 586a424cb816..ab16e3bd163e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeExtensionController.java +++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeExtensionController.java @@ -81,6 +81,11 @@ public class FakeExtensionController implements ExtensionController { } @Override + public ExtensionBuilder<T> withFeature(String feature, Supplier<T> def) { + return null; + } + + @Override public Extension build() { return new FakeExtension(mAllocation); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakePluginManager.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakePluginManager.java index d1b1c5b9a066..0a83a896dfaf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakePluginManager.java +++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakePluginManager.java @@ -14,6 +14,7 @@ package com.android.systemui.utils.leaks; +import android.content.Context; import android.testing.LeakCheck; import com.android.systemui.plugins.Plugin; diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/os/FakeHandler.java b/packages/SystemUI/tests/src/com/android/systemui/utils/os/FakeHandler.java new file mode 100644 index 000000000000..5a7d4b5e54b3 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/utils/os/FakeHandler.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.utils.os; + +import android.os.Handler; +import android.os.Looper; +import android.os.Message; + +import java.util.ArrayList; + +/** + * A handler that allows control over when to dispatch messages and callbacks. + * + * WARNING: Because most Handler methods are final, the only thing this handler can intercept + * are sending messages and posting runnables, but *NOT* removing messages nor runnables. + * It also *CANNOT* intercept messages posted to the front of queue. + */ +public class FakeHandler extends Handler { + + private Mode mMode = Mode.IMMEDIATE; + private ArrayList<Message> mQueuedMessages = new ArrayList<>(); + + public FakeHandler(Looper looper) { + super(looper); + } + + @Override + public boolean sendMessageAtTime(Message msg, long uptimeMillis) { + mQueuedMessages.add(msg); + if (mMode == Mode.IMMEDIATE) { + dispatchQueuedMessages(); + } + return true; + } + + public void setMode(Mode mode) { + mMode = mode; + } + + /** + * Dispatch any messages that have been queued on the calling thread. + */ + public void dispatchQueuedMessages() { + ArrayList<Message> messages = new ArrayList<>(mQueuedMessages); + mQueuedMessages.clear(); + for (Message msg : messages) { + dispatchMessage(msg); + } + } + + public enum Mode { + /** Messages are dispatched immediately on the calling thread. */ + IMMEDIATE, + /** Messages are queued until {@link #dispatchQueuedMessages()} is called. */ + QUEUEING, + } +} diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml index a3d27ce8a3da..8172e717850b 100644 --- a/packages/VpnDialogs/AndroidManifest.xml +++ b/packages/VpnDialogs/AndroidManifest.xml @@ -23,9 +23,10 @@ <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" /> <application android:label="VpnDialogs" - android:allowBackup="false" > + android:allowBackup="false"> + <activity android:name=".ConfirmDialog" - android:theme="@android:style/Theme.Material.Light.Dialog.Alert"> + android:theme="@android:style/Theme.Material.Light.Dialog.Alert"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.DEFAULT"/> @@ -33,12 +34,21 @@ </activity> <activity android:name=".ManageDialog" - android:theme="@android:style/Theme.Material.Light.Dialog.Alert" - android:noHistory="true"> - <intent-filter> - <action android:name="android.intent.action.MAIN"/> - <category android:name="android.intent.category.DEFAULT"/> - </intent-filter> + android:theme="@android:style/Theme.Material.Light.Dialog.Alert" + android:noHistory="true" + android:excludeFromRecents="true" + android:permission="android.permission.NETWORK_SETTINGS" + android:exported="true"> + </activity> + + <activity android:name=".AlwaysOnDisconnectedDialog" + android:label="@string/always_on_disconnected_title" + android:theme="@android:style/Theme.Material.Light.Dialog.Alert" + android:noHistory="true" + android:excludeFromRecents="true" + android:permission="android.permission.NETWORK_SETTINGS" + android:exported="true"> </activity> + </application> </manifest> diff --git a/packages/VpnDialogs/res/layout/always_on_disconnected.xml b/packages/VpnDialogs/res/layout/always_on_disconnected.xml new file mode 100644 index 000000000000..0f4a46d07a9a --- /dev/null +++ b/packages/VpnDialogs/res/layout/always_on_disconnected.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:padding="24dp"> + <TextView android:id="@+id/message" + android:layout_width="fill_parent" + android:layout_height="wrap_content"/> +</ScrollView> diff --git a/packages/VpnDialogs/res/values-af/strings.xml b/packages/VpnDialogs/res/values-af/strings.xml index 8c5739cdca88..ac82b0e0009a 100644 --- a/packages/VpnDialogs/res/values-af/strings.xml +++ b/packages/VpnDialogs/res/values-af/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Verbindingversoek"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wil \'n VPN-verbinding opstel wat dit sal toelaat om netwerkverkeer te monitor. Aanvaar dit net as jy die bron vertrou. <br /> <br /> <img src=vpn_icon /> verskyn boaan jou skerm as VPN aktief is."</string> <string name="legacy_title" msgid="192936250066580964">"VPN is gekoppel"</string> - <string name="configure" msgid="4905518375574791375">"Stel op"</string> - <string name="disconnect" msgid="971412338304200056">"Ontkoppel"</string> <string name="session" msgid="6470628549473641030">"Sessie:"</string> <string name="duration" msgid="3584782459928719435">"Tydsduur:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Gestuur:"</string> <string name="data_received" msgid="4062776929376067820">"Ontvang:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> grepe/<xliff:g id="NUMBER_1">%2$s</xliff:g> pakkies"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Kan nie aan altyd-aan-VPN koppel nie"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> is opgestel om ten alle tye gekoppel te bly, maar dit kan nie nou onmiddellik koppel nie. Jou foon sal \'n publieke netwerk gebruik totdat dit weer aan <xliff:g id="VPN_APP_1">%1$s</xliff:g> kan koppel."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> is opgestel om ten alle tye gekoppel te bly, maar dit kan nie nou onmiddellik koppel nie. Jy sal nie \'n verbinding hê totdat die VPN weer kan koppel nie."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Verander VPN-instellings"</string> + <string name="configure" msgid="4905518375574791375">"Stel op"</string> + <string name="disconnect" msgid="971412338304200056">"Ontkoppel"</string> + <string name="open_app" msgid="3717639178595958667">"Maak program oop"</string> + <string name="dismiss" msgid="6192859333764711227">"Maak toe"</string> </resources> diff --git a/packages/VpnDialogs/res/values-am/strings.xml b/packages/VpnDialogs/res/values-am/strings.xml index e6fc1129b0ac..103f101b8262 100644 --- a/packages/VpnDialogs/res/values-am/strings.xml +++ b/packages/VpnDialogs/res/values-am/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"የግንኙነት ጥያቄ"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> የአውታረ መረብ መከታተል የሚያስችል የVPN ግንኑነት ማዋቀር ይፈልጋል። ምንጩን የሚያምኑት ብቻ ከሆኑ ይቀበሉ። <br /> <br /> <img src=vpn_icon /> VPN ገቢር ሲሆን በማያ ገጽዎ ላይኛው ክፍል ላይ ይታያል።"</string> <string name="legacy_title" msgid="192936250066580964">"VPN ተያይዟል"</string> - <string name="configure" msgid="4905518375574791375">"አዋቅር"</string> - <string name="disconnect" msgid="971412338304200056">"አለያይ"</string> <string name="session" msgid="6470628549473641030">"ክፍለ ጊዜ፡"</string> <string name="duration" msgid="3584782459928719435">"ጊዜ"</string> <string name="data_transmitted" msgid="7988167672982199061">"ተልኳል ለ:"</string> <string name="data_received" msgid="4062776929376067820">"ተቀብሏል፡"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> ባይትስ / <xliff:g id="NUMBER_1">%2$s</xliff:g> ፓኬቶች"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"ሁልጊዜ ከበራ ቪፒኤን ጋር መገናኘት አልተቻለም"</string> + <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> ሁልጊዜ እንዲገናኝ የተዋቀረ ነው፣ ነገር ግን አሁን መገናኘት አይችልም። ቪፒኤኑ ዳግም መገናኘት እስኪችል ድረስ ግንኙነት አይኖረዎትም።"</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"የቪፒኤን ቅንብሮችን ይቀይሩ"</string> + <string name="configure" msgid="4905518375574791375">"አዋቅር"</string> + <string name="disconnect" msgid="971412338304200056">"አለያይ"</string> + <string name="open_app" msgid="3717639178595958667">"መተግበሪያን ክፈት"</string> + <string name="dismiss" msgid="6192859333764711227">"አሰናብት"</string> </resources> diff --git a/packages/VpnDialogs/res/values-ar/strings.xml b/packages/VpnDialogs/res/values-ar/strings.xml index e36eef4a0b83..808cde906d2f 100644 --- a/packages/VpnDialogs/res/values-ar/strings.xml +++ b/packages/VpnDialogs/res/values-ar/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"طلب الاتصال"</string> <string name="warning" msgid="809658604548412033">"يريد <xliff:g id="APP">%s</xliff:g> إعداد الاتصال بالشبكة الافتراضية الخاصة التي تتيح له مراقبة حركة المرور على الشبكة. فلا توافق إلا إذا كنت تثق في المصدر. <br /> <br /> <img src=vpn_icon /> يظهر في الجزء العلوي من الشاشة عندما تكون الشبكة الافتراضية الخاصة نشطة."</string> <string name="legacy_title" msgid="192936250066580964">"VPN متصلة"</string> - <string name="configure" msgid="4905518375574791375">"تهيئة"</string> - <string name="disconnect" msgid="971412338304200056">"قطع الاتصال"</string> <string name="session" msgid="6470628549473641030">"الجلسة"</string> <string name="duration" msgid="3584782459928719435">"المدة:"</string> <string name="data_transmitted" msgid="7988167672982199061">"مرسل:"</string> <string name="data_received" msgid="4062776929376067820">"تم الاستلام:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> بايت / <xliff:g id="NUMBER_1">%2$s</xliff:g> من الحزم"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"يتعذّر الاتصال بشبكة VPN التي يتم تشغيلها دائمًا"</string> + <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="configure" msgid="4905518375574791375">"تهيئة"</string> + <string name="disconnect" msgid="971412338304200056">"قطع الاتصال"</string> + <string name="open_app" msgid="3717639178595958667">"فتح التطبيق"</string> + <string name="dismiss" msgid="6192859333764711227">"تجاهل"</string> </resources> diff --git a/packages/VpnDialogs/res/values-az/strings.xml b/packages/VpnDialogs/res/values-az/strings.xml index c568e94e00f7..2bdf23ee2aa0 100644 --- a/packages/VpnDialogs/res/values-az/strings.xml +++ b/packages/VpnDialogs/res/values-az/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Bağlantı Sorğusu"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> VPN bağlantı yaratmaq istəyir ki, bu da şəbəkə trafikini izləyə bilər. Yalnız mənbəyə güvəndiyiniz halda qəbul edin. VPN aktiv olan zaman <br /> <br /> <img src=vpn_icon /> ekranın yuxarısında görünür."</string> <string name="legacy_title" msgid="192936250066580964">"VPN qoşuludur"</string> - <string name="configure" msgid="4905518375574791375">"Konfiqurasiya edin"</string> - <string name="disconnect" msgid="971412338304200056">"Əlaqəni kəs"</string> <string name="session" msgid="6470628549473641030">"Sessiya:"</string> <string name="duration" msgid="3584782459928719435">"Müddət:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Göndərilən:"</string> <string name="data_received" msgid="4062776929376067820">"Qəbul edilən:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bayt / <xliff:g id="NUMBER_1">%2$s</xliff:g> paket"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Həmişə aktiv VPN-ə qoşulmaq mümkün deyil"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> həmişə aktiv olacaq şəkildə ayarlanıb, lakin hazırda qoşulmaq mümkün deyil. Telefonunuz <xliff:g id="VPN_APP_1">%1$s</xliff:g> şəbəkəsinə qoşulana qədər ictimai şəbəkədən istifadə edəcək."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> həmişə aktiv olacaq şəkildə ayarlanıb, lakin hazırda qoşulmaq mümkün deyil. VPN təkrar qoşuluncaya qədər bağlantınız olmayacaq."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN ayarlarını dəyişin"</string> + <string name="configure" msgid="4905518375574791375">"Konfiqurasiya edin"</string> + <string name="disconnect" msgid="971412338304200056">"Əlaqəni kəs"</string> + <string name="open_app" msgid="3717639178595958667">"Tətbiqi açın"</string> + <string name="dismiss" msgid="6192859333764711227">"İmtina edin"</string> </resources> diff --git a/packages/VpnDialogs/res/values-b+sr+Latn/strings.xml b/packages/VpnDialogs/res/values-b+sr+Latn/strings.xml index 173cd03259ac..f40e40670bf3 100644 --- a/packages/VpnDialogs/res/values-b+sr+Latn/strings.xml +++ b/packages/VpnDialogs/res/values-b+sr+Latn/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Zahtev za povezivanje"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> želi da podesi VPN vezu koja omogućava praćenje saobraćaja na mreži. Prihvatite samo ako verujete izvoru. <br /> <br /> <img src=vpn_icon /> se prikazuje u vrhu ekrana kada je VPN aktivan."</string> <string name="legacy_title" msgid="192936250066580964">"VPN je povezan"</string> - <string name="configure" msgid="4905518375574791375">"Konfiguriši"</string> - <string name="disconnect" msgid="971412338304200056">"Prekini vezu"</string> <string name="session" msgid="6470628549473641030">"Sesija:"</string> <string name="duration" msgid="3584782459928719435">"Trajanje:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Poslato:"</string> <string name="data_received" msgid="4062776929376067820">"Primljeno:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bajt(ov)a / <xliff:g id="NUMBER_1">%2$s</xliff:g> paketa"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Povezivanje sa uvek uključenim VPN-om nije uspelo"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"Mreža <xliff:g id="VPN_APP_0">%1$s</xliff:g> je podešena da bude uvek povezana, ali trenutno ne može da uspostavi vezu. Telefon će koristiti javnu mrežu dok se ponovo ne poveže sa <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"Mreža <xliff:g id="VPN_APP">%1$s</xliff:g> je podešena da bude uvek povezana, ali trenutno ne može da uspostavi vezu. Nećete imati vezu dok se VPN ponovo ne poveže."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Promeni podešavanja VPN-a"</string> + <string name="configure" msgid="4905518375574791375">"Konfiguriši"</string> + <string name="disconnect" msgid="971412338304200056">"Prekini vezu"</string> + <string name="open_app" msgid="3717639178595958667">"Otvori aplikaciju"</string> + <string name="dismiss" msgid="6192859333764711227">"Odbaci"</string> </resources> diff --git a/packages/VpnDialogs/res/values-be/strings.xml b/packages/VpnDialogs/res/values-be/strings.xml index d96a1729f492..0903c8ece36b 100644 --- a/packages/VpnDialogs/res/values-be/strings.xml +++ b/packages/VpnDialogs/res/values-be/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Запыт на падлучэнне"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> спрабуе наладзіць падлучэнне VPN, якое дазваляе сачыць за сеткавым трафікам. Прымайце толькі тады, калі вы давяраеце гэтай крыніцы. Калі VPN актыўны, у верхняй частцы экрана адлюстроўваецца <br /> <br /> <img src=vpn_icon />."</string> <string name="legacy_title" msgid="192936250066580964">"VPN падключаны"</string> - <string name="configure" msgid="4905518375574791375">"Наладзіць"</string> - <string name="disconnect" msgid="971412338304200056">"Адключыцца"</string> <string name="session" msgid="6470628549473641030">"Сессія"</string> <string name="duration" msgid="3584782459928719435">"Працягласць:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Адпраўлена:"</string> <string name="data_received" msgid="4062776929376067820">"Атрымана:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> байт / <xliff:g id="NUMBER_1">%2$s</xliff:g> пакеты"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Не атрымалася падключыцца да заўсёды ўключанай VPN"</string> + <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="configure" msgid="4905518375574791375">"Наладзіць"</string> + <string name="disconnect" msgid="971412338304200056">"Адключыцца"</string> + <string name="open_app" msgid="3717639178595958667">"Адкрыць праграму"</string> + <string name="dismiss" msgid="6192859333764711227">"Адхіліць"</string> </resources> diff --git a/packages/VpnDialogs/res/values-bg/strings.xml b/packages/VpnDialogs/res/values-bg/strings.xml index d7b265fc5ea3..9ac853d2016f 100644 --- a/packages/VpnDialogs/res/values-bg/strings.xml +++ b/packages/VpnDialogs/res/values-bg/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Заявка за свързване"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> иска да настрои връзка с виртуална частна мрежа (VPN), за да може да наблюдава мрежовия трафик. Приемете само ако източникът е надежден. Иконата <br /> <br /> <img src=vpn_icon /> се показва в долната част на екрана при активирана VPN."</string> <string name="legacy_title" msgid="192936250066580964">"VPN е свързана"</string> - <string name="configure" msgid="4905518375574791375">"Конфигуриране"</string> - <string name="disconnect" msgid="971412338304200056">"Изключване"</string> <string name="session" msgid="6470628549473641030">"Сесия:"</string> <string name="duration" msgid="3584782459928719435">"Продължителност:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Изпратено:"</string> <string name="data_received" msgid="4062776929376067820">"Получено:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> байта/ <xliff:g id="NUMBER_1">%2$s</xliff:g> пакета"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Няма връзка с винаги включената VPN"</string> + <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="configure" msgid="4905518375574791375">"Конфигуриране"</string> + <string name="disconnect" msgid="971412338304200056">"Изключване"</string> + <string name="open_app" msgid="3717639178595958667">"Към приложението"</string> + <string name="dismiss" msgid="6192859333764711227">"Отхвърляне"</string> </resources> diff --git a/packages/VpnDialogs/res/values-bn/strings.xml b/packages/VpnDialogs/res/values-bn/strings.xml index 90ce36e75c76..2defd8184c5e 100644 --- a/packages/VpnDialogs/res/values-bn/strings.xml +++ b/packages/VpnDialogs/res/values-bn/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"সংযোগের অনুরোধ"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> এমন একটি VPN সংযোগ সেট আপ করতে চাচ্ছে যেটি দিয়ে এটি নেটওয়ার্ক ট্রাফিক নিরীক্ষণ করতে পারবে। আপনি যদি উৎসটিকে বিশ্বাস করেন, তাহলেই কেবল এতে সম্মতি দিন। VPN সক্রিয় থাকলে আপনার স্ক্রীনের উপরে <br /> <br /> <img src=vpn_icon /> দেখা যাবে।"</string> <string name="legacy_title" msgid="192936250066580964">"VPN সংযুক্ত হয়েছে"</string> - <string name="configure" msgid="4905518375574791375">"কনফিগার করুন"</string> - <string name="disconnect" msgid="971412338304200056">"সংযোগ বিচ্ছিন্ন করুন"</string> <string name="session" msgid="6470628549473641030">"অধিবেশন:"</string> <string name="duration" msgid="3584782459928719435">"সময়কাল:"</string> <string name="data_transmitted" msgid="7988167672982199061">"পাঠানো হয়েছে:"</string> <string name="data_received" msgid="4062776929376067820">"গৃহিত ডেটার পরিমান:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> বাইট / <xliff:g id="NUMBER_1">%2$s</xliff:g> প্যাকেট"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"সবসময়-চালু VPN এর সাথে সংযোগ করা যাচ্ছে না"</string> + <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="configure" msgid="4905518375574791375">"কনফিগার করুন"</string> + <string name="disconnect" msgid="971412338304200056">"সংযোগ বিচ্ছিন্ন করুন"</string> + <string name="open_app" msgid="3717639178595958667">"অ্যাপটি খুলুন"</string> + <string name="dismiss" msgid="6192859333764711227">"খারিজ করুন"</string> </resources> diff --git a/packages/VpnDialogs/res/values-bs/strings.xml b/packages/VpnDialogs/res/values-bs/strings.xml index 899908c290e8..1862bb7816bc 100644 --- a/packages/VpnDialogs/res/values-bs/strings.xml +++ b/packages/VpnDialogs/res/values-bs/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Zahtjev za povezivanje"</string> <string name="warning" msgid="809658604548412033">"Aplikacija <xliff:g id="APP">%s</xliff:g> želi podesiti VPN vezu koja joj omogućava praćenje mrežnog saobraćaja. Prihvatite samo ako je izvor pouzdan. <br /> <br /> <img src=vpn_icon /> se pojavi na vrhu ekrana kada je VPN aktivna."</string> <string name="legacy_title" msgid="192936250066580964">"VPN veza uspostavljena"</string> - <string name="configure" msgid="4905518375574791375">"Konfiguriraj"</string> - <string name="disconnect" msgid="971412338304200056">"Prekini vezu"</string> <string name="session" msgid="6470628549473641030">"Sesija:"</string> <string name="duration" msgid="3584782459928719435">"Trajanje:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Poslano:"</string> <string name="data_received" msgid="4062776929376067820">"Primljeno:"</string> <string name="data_value_format" msgid="2192466557826897580">"Broj bajtova: <xliff:g id="NUMBER_0">%1$s</xliff:g>/Broj paketa: <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Ne može se povezati na stalno uključen VPN"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"Aplikacija <xliff:g id="VPN_APP_0">%1$s</xliff:g> je postavljena da ostane povezana sve vrijeme, ali se trenutno ne može povezati. Telefon će koristiti javnu mrežu dok se ponovo ne mogne povezati s aplikacijom <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"Aplikacija <xliff:g id="VPN_APP">%1$s</xliff:g> je postavljena da ostane povezana sve vrijeme, ali se trenutno ne može povezati. Nećete biti imati vezu dok se VPN ne mogne ponovo povezati."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Promijenite postavke za VPN"</string> + <string name="configure" msgid="4905518375574791375">"Konfiguriraj"</string> + <string name="disconnect" msgid="971412338304200056">"Prekini vezu"</string> + <string name="open_app" msgid="3717639178595958667">"Otvori aplikaciju"</string> + <string name="dismiss" msgid="6192859333764711227">"Odbaci"</string> </resources> diff --git a/packages/VpnDialogs/res/values-ca/strings.xml b/packages/VpnDialogs/res/values-ca/strings.xml index ab6b50aeea71..97738c316f4b 100644 --- a/packages/VpnDialogs/res/values-ca/strings.xml +++ b/packages/VpnDialogs/res/values-ca/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Sol·licitud de connexió"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> vol configurar una connexió VPN que li permeti controlar el trànsit de xarxa. Accepta la sol·licitud només si prové d\'una font de confiança. <br /> <br /> <img src=vpn_icon /> es mostra a la part superior de la pantalla quan la VPN està activada."</string> <string name="legacy_title" msgid="192936250066580964">"La VPN està connectada"</string> - <string name="configure" msgid="4905518375574791375">"Configura"</string> - <string name="disconnect" msgid="971412338304200056">"Desconnecta"</string> <string name="session" msgid="6470628549473641030">"Sessió:"</string> <string name="duration" msgid="3584782459928719435">"Durada:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Enviat:"</string> <string name="data_received" msgid="4062776929376067820">"Rebut:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bytes/<xliff:g id="NUMBER_1">%2$s</xliff:g> paquets"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"No s\'ha pogut establir la connexió a la VPN sempre activada"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"S\'ha configurat <xliff:g id="VPN_APP_0">%1$s</xliff:g> perquè sempre tingui connexió, però ara mateix no es pot connectar. El telèfon utilitzarà una xarxa pública fins que no es pugui tornar a connectar a <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"S\'ha configurat <xliff:g id="VPN_APP">%1$s</xliff:g> perquè sempre tingui connexió, però ara mateix no es pot connectar. No tindràs connexió fins que no es pugui tornar a establir la connexió amb la VPN."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Canvia la configuració de la VPN"</string> + <string name="configure" msgid="4905518375574791375">"Configura"</string> + <string name="disconnect" msgid="971412338304200056">"Desconnecta"</string> + <string name="open_app" msgid="3717639178595958667">"Obre l\'aplicació"</string> + <string name="dismiss" msgid="6192859333764711227">"Ignora"</string> </resources> diff --git a/packages/VpnDialogs/res/values-cs/strings.xml b/packages/VpnDialogs/res/values-cs/strings.xml index 4f830fb00828..7a3d515877fa 100644 --- a/packages/VpnDialogs/res/values-cs/strings.xml +++ b/packages/VpnDialogs/res/values-cs/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Žádost o připojení"</string> <string name="warning" msgid="809658604548412033">"Aplikace <xliff:g id="APP">%s</xliff:g> žádá o nastavení připojení VPN, pomocí kterého bude moci sledovat síťový provoz. Povolte, jen pokud zdroji důvěřujete. <br /> <br /> <img src=vpn_icon /> – když je síť VPN aktivní, v horní části obrazovky se zobrazuje tato ikona."</string> <string name="legacy_title" msgid="192936250066580964">"Síť VPN je připojena"</string> - <string name="configure" msgid="4905518375574791375">"Konfigurovat"</string> - <string name="disconnect" msgid="971412338304200056">"Odpojit"</string> <string name="session" msgid="6470628549473641030">"Relace:"</string> <string name="duration" msgid="3584782459928719435">"Doba trvání:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Odesláno:"</string> <string name="data_received" msgid="4062776929376067820">"Přijato:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bajtů / <xliff:g id="NUMBER_1">%2$s</xliff:g> paketů"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Nelze se připojit k trvalé VPN"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"Aplikace <xliff:g id="VPN_APP_0">%1$s</xliff:g> je nastavena k trvalému připojení, ale nyní se nemůže připojit. Než se telefon bude moci připojit pomocí aplikace <xliff:g id="VPN_APP_1">%1$s</xliff:g>, použije veřejnou síť."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"Aplikace <xliff:g id="VPN_APP">%1$s</xliff:g> je nastavena k trvalému připojení, ale nyní se nemůže připojit. Než se budete moci připojit pomocí VPN, zůstanete offline."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Změnit nastavení VPN"</string> + <string name="configure" msgid="4905518375574791375">"Konfigurovat"</string> + <string name="disconnect" msgid="971412338304200056">"Odpojit"</string> + <string name="open_app" msgid="3717639178595958667">"Spustit aplikaci"</string> + <string name="dismiss" msgid="6192859333764711227">"Zavřít"</string> </resources> diff --git a/packages/VpnDialogs/res/values-da/strings.xml b/packages/VpnDialogs/res/values-da/strings.xml index 804982d9f9cd..7641158af3da 100644 --- a/packages/VpnDialogs/res/values-da/strings.xml +++ b/packages/VpnDialogs/res/values-da/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Forbindelsesanmodning"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> vil konfigurere en VPN-forbindelse, der giver appen mulighed for at registrere netværkstrafik. Du bør kun acceptere dette, hvis du har tillid til kilden. <br /> <br /> <img src=vpn_icon /> vises øverst på din skærm, når VPN-forbindelsen er aktiv."</string> <string name="legacy_title" msgid="192936250066580964">"VPN er tilsluttet"</string> - <string name="configure" msgid="4905518375574791375">"Konfigurer"</string> - <string name="disconnect" msgid="971412338304200056">"Fjern tilknytning"</string> <string name="session" msgid="6470628549473641030">"Session:"</string> <string name="duration" msgid="3584782459928719435">"Varighed:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Sendt:"</string> <string name="data_received" msgid="4062776929376067820">"Modtaget:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bytes / <xliff:g id="NUMBER_1">%2$s</xliff:g> pakker"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Der kan ikke oprettes forbindelse til konstant VPN"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> er konfigureret til altid at være forbundet, men kan ikke oprette forbindelse lige nu. Din telefon benytter et offentligt netværk, indtil den kan få forbindelse til <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> er konfigureret til altid at være forbundet, men kan ikke oprette forbindelse lige nu. Du har ingen forbindelse, før VPN kan oprette den igen."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Skift VPN-indstillinger"</string> + <string name="configure" msgid="4905518375574791375">"Konfigurer"</string> + <string name="disconnect" msgid="971412338304200056">"Fjern tilknytning"</string> + <string name="open_app" msgid="3717639178595958667">"Åbn app"</string> + <string name="dismiss" msgid="6192859333764711227">"Luk"</string> </resources> diff --git a/packages/VpnDialogs/res/values-de/strings.xml b/packages/VpnDialogs/res/values-de/strings.xml index 27b0196f882f..b1cebf84b77d 100644 --- a/packages/VpnDialogs/res/values-de/strings.xml +++ b/packages/VpnDialogs/res/values-de/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Verbindungsanfrage"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> möchte eine VPN-Verbindung herstellen, über die der Netzwerkverkehr überwacht werden kann. Lasse die Verbindung nur zu, wenn die App vertrauenswürdig ist. <br /> <br /> <img src=vpn_icon /> wird oben am Display angezeigt, wenn VPN aktiv ist."</string> <string name="legacy_title" msgid="192936250066580964">"VPN ist verbunden"</string> - <string name="configure" msgid="4905518375574791375">"Konfigurieren"</string> - <string name="disconnect" msgid="971412338304200056">"Verbindung trennen"</string> <string name="session" msgid="6470628549473641030">"Sitzung:"</string> <string name="duration" msgid="3584782459928719435">"Dauer:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Gesendet:"</string> <string name="data_received" msgid="4062776929376067820">"Empfangen:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> Byte/<xliff:g id="NUMBER_1">%2$s</xliff:g> Pakete"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Verbindung mit dauerhaft aktivem VPN nicht möglich"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> ist so eingerichtet, dass die Verbindung immer über das VPN geleitet wird, aber momentan kann keine Verbindung hergestellt werden. Bis die Verbindung über <xliff:g id="VPN_APP_1">%1$s</xliff:g> wiederhergestellt werden kann, verwendet dein Smartphone ein öffentliches Netzwerk."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> ist so eingerichtet, dass die Verbindung immer über das VPN geleitet wird, aber momentan kann keine Verbindung hergestellt werden. Solange die VPN-Verbindung nicht wiederhergestellt worden ist, bist du nicht verbunden."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN-Einstellungen ändern"</string> + <string name="configure" msgid="4905518375574791375">"Konfigurieren"</string> + <string name="disconnect" msgid="971412338304200056">"Verbindung trennen"</string> + <string name="open_app" msgid="3717639178595958667">"App öffnen"</string> + <string name="dismiss" msgid="6192859333764711227">"Schließen"</string> </resources> diff --git a/packages/VpnDialogs/res/values-el/strings.xml b/packages/VpnDialogs/res/values-el/strings.xml index 97b44070b4ed..78bcc43ff609 100644 --- a/packages/VpnDialogs/res/values-el/strings.xml +++ b/packages/VpnDialogs/res/values-el/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Αίτημα σύνδεσης"</string> <string name="warning" msgid="809658604548412033">"Η εφαρμογή <xliff:g id="APP">%s</xliff:g> επιθυμεί να ρυθμίσει μια σύνδεση VPN που της επιτρέπει να παρακολουθεί την επισκεψιμότητα του δικτύου. Αποδεχτείτε το αίτημα μόνο εάν εμπιστεύεστε την πηγή. Το εικονίδιο <br /> <br /> <img src=vpn_icon /> εμφανίζεται στο επάνω μέρος της οθόνης σας όταν είναι ενεργό το VPN."</string> <string name="legacy_title" msgid="192936250066580964">"Το VPN συνδέθηκε"</string> - <string name="configure" msgid="4905518375574791375">"Διαμόρφωση"</string> - <string name="disconnect" msgid="971412338304200056">"Αποσύνδεση"</string> <string name="session" msgid="6470628549473641030">"Περίοδος σύνδεσης"</string> <string name="duration" msgid="3584782459928719435">"Διάρκεια:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Στάλθηκε:"</string> <string name="data_received" msgid="4062776929376067820">"Λήφθηκε:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> byte / <xliff:g id="NUMBER_1">%2$s</xliff:g> πακέτα"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Δεν είναι δυνατή η σύνδεση σε πάντα ενεργό VPN"</string> + <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="configure" msgid="4905518375574791375">"Διαμόρφωση"</string> + <string name="disconnect" msgid="971412338304200056">"Αποσύνδεση"</string> + <string name="open_app" msgid="3717639178595958667">"Άνοιγμα εφαρμογής"</string> + <string name="dismiss" msgid="6192859333764711227">"Παράβλεψη"</string> </resources> diff --git a/packages/VpnDialogs/res/values-en-rAU/strings.xml b/packages/VpnDialogs/res/values-en-rAU/strings.xml index 2c93c781b1ca..6ed50a7668ae 100644 --- a/packages/VpnDialogs/res/values-en-rAU/strings.xml +++ b/packages/VpnDialogs/res/values-en-rAU/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Connection request"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears at the top of your screen when VPN is active."</string> <string name="legacy_title" msgid="192936250066580964">"VPN is connected"</string> - <string name="configure" msgid="4905518375574791375">"Configure"</string> - <string name="disconnect" msgid="971412338304200056">"Disconnect"</string> <string name="session" msgid="6470628549473641030">"Session:"</string> <string name="duration" msgid="3584782459928719435">"Duration:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Sent:"</string> <string name="data_received" msgid="4062776929376067820">"Received:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bytes / <xliff:g id="NUMBER_1">%2$s</xliff:g> packets"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Can\'t connect to always-on VPN"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> is set up to stay connected all the time, but it can\'t connect at the moment. Your phone will use a public network until it can reconnect to <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> is set up to stay connected all the time, but it can\'t connect at the moment. You won\'t have a connection until the VPN can reconnect."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Change VPN settings"</string> + <string name="configure" msgid="4905518375574791375">"Configure"</string> + <string name="disconnect" msgid="971412338304200056">"Disconnect"</string> + <string name="open_app" msgid="3717639178595958667">"Open app"</string> + <string name="dismiss" msgid="6192859333764711227">"Dismiss"</string> </resources> diff --git a/packages/VpnDialogs/res/values-en-rCA/strings.xml b/packages/VpnDialogs/res/values-en-rCA/strings.xml index 2c93c781b1ca..6ed50a7668ae 100644 --- a/packages/VpnDialogs/res/values-en-rCA/strings.xml +++ b/packages/VpnDialogs/res/values-en-rCA/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Connection request"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears at the top of your screen when VPN is active."</string> <string name="legacy_title" msgid="192936250066580964">"VPN is connected"</string> - <string name="configure" msgid="4905518375574791375">"Configure"</string> - <string name="disconnect" msgid="971412338304200056">"Disconnect"</string> <string name="session" msgid="6470628549473641030">"Session:"</string> <string name="duration" msgid="3584782459928719435">"Duration:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Sent:"</string> <string name="data_received" msgid="4062776929376067820">"Received:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bytes / <xliff:g id="NUMBER_1">%2$s</xliff:g> packets"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Can\'t connect to always-on VPN"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> is set up to stay connected all the time, but it can\'t connect at the moment. Your phone will use a public network until it can reconnect to <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> is set up to stay connected all the time, but it can\'t connect at the moment. You won\'t have a connection until the VPN can reconnect."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Change VPN settings"</string> + <string name="configure" msgid="4905518375574791375">"Configure"</string> + <string name="disconnect" msgid="971412338304200056">"Disconnect"</string> + <string name="open_app" msgid="3717639178595958667">"Open app"</string> + <string name="dismiss" msgid="6192859333764711227">"Dismiss"</string> </resources> diff --git a/packages/VpnDialogs/res/values-en-rGB/strings.xml b/packages/VpnDialogs/res/values-en-rGB/strings.xml index 2c93c781b1ca..6ed50a7668ae 100644 --- a/packages/VpnDialogs/res/values-en-rGB/strings.xml +++ b/packages/VpnDialogs/res/values-en-rGB/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Connection request"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears at the top of your screen when VPN is active."</string> <string name="legacy_title" msgid="192936250066580964">"VPN is connected"</string> - <string name="configure" msgid="4905518375574791375">"Configure"</string> - <string name="disconnect" msgid="971412338304200056">"Disconnect"</string> <string name="session" msgid="6470628549473641030">"Session:"</string> <string name="duration" msgid="3584782459928719435">"Duration:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Sent:"</string> <string name="data_received" msgid="4062776929376067820">"Received:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bytes / <xliff:g id="NUMBER_1">%2$s</xliff:g> packets"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Can\'t connect to always-on VPN"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> is set up to stay connected all the time, but it can\'t connect at the moment. Your phone will use a public network until it can reconnect to <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> is set up to stay connected all the time, but it can\'t connect at the moment. You won\'t have a connection until the VPN can reconnect."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Change VPN settings"</string> + <string name="configure" msgid="4905518375574791375">"Configure"</string> + <string name="disconnect" msgid="971412338304200056">"Disconnect"</string> + <string name="open_app" msgid="3717639178595958667">"Open app"</string> + <string name="dismiss" msgid="6192859333764711227">"Dismiss"</string> </resources> diff --git a/packages/VpnDialogs/res/values-en-rIN/strings.xml b/packages/VpnDialogs/res/values-en-rIN/strings.xml index 2c93c781b1ca..6ed50a7668ae 100644 --- a/packages/VpnDialogs/res/values-en-rIN/strings.xml +++ b/packages/VpnDialogs/res/values-en-rIN/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Connection request"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears at the top of your screen when VPN is active."</string> <string name="legacy_title" msgid="192936250066580964">"VPN is connected"</string> - <string name="configure" msgid="4905518375574791375">"Configure"</string> - <string name="disconnect" msgid="971412338304200056">"Disconnect"</string> <string name="session" msgid="6470628549473641030">"Session:"</string> <string name="duration" msgid="3584782459928719435">"Duration:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Sent:"</string> <string name="data_received" msgid="4062776929376067820">"Received:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bytes / <xliff:g id="NUMBER_1">%2$s</xliff:g> packets"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Can\'t connect to always-on VPN"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> is set up to stay connected all the time, but it can\'t connect at the moment. Your phone will use a public network until it can reconnect to <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> is set up to stay connected all the time, but it can\'t connect at the moment. You won\'t have a connection until the VPN can reconnect."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Change VPN settings"</string> + <string name="configure" msgid="4905518375574791375">"Configure"</string> + <string name="disconnect" msgid="971412338304200056">"Disconnect"</string> + <string name="open_app" msgid="3717639178595958667">"Open app"</string> + <string name="dismiss" msgid="6192859333764711227">"Dismiss"</string> </resources> diff --git a/packages/VpnDialogs/res/values-en-rXC/strings.xml b/packages/VpnDialogs/res/values-en-rXC/strings.xml index 640a41d4561c..089845af8243 100644 --- a/packages/VpnDialogs/res/values-en-rXC/strings.xml +++ b/packages/VpnDialogs/res/values-en-rXC/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Connection request"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears at the top of your screen when VPN is active."</string> <string name="legacy_title" msgid="192936250066580964">"VPN is connected"</string> - <string name="configure" msgid="4905518375574791375">"Configure"</string> - <string name="disconnect" msgid="971412338304200056">"Disconnect"</string> <string name="session" msgid="6470628549473641030">"Session:"</string> <string name="duration" msgid="3584782459928719435">"Duration:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Sent:"</string> <string name="data_received" msgid="4062776929376067820">"Received:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bytes / <xliff:g id="NUMBER_1">%2$s</xliff:g> packets"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Can\'t connect to always-on VPN"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> is set up to stay connected all the time, but it can\'t connect right now. Your phone will use a public network until it can reconnect to <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> is set up to stay connected all the time, but it can\'t connect right now. You won\'t have a connection until the VPN can reconnect."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Change VPN settings"</string> + <string name="configure" msgid="4905518375574791375">"Configure"</string> + <string name="disconnect" msgid="971412338304200056">"Disconnect"</string> + <string name="open_app" msgid="3717639178595958667">"Open app"</string> + <string name="dismiss" msgid="6192859333764711227">"Dismiss"</string> </resources> diff --git a/packages/VpnDialogs/res/values-es-rUS/strings.xml b/packages/VpnDialogs/res/values-es-rUS/strings.xml index 8f0a05003201..3732ebc6a333 100644 --- a/packages/VpnDialogs/res/values-es-rUS/strings.xml +++ b/packages/VpnDialogs/res/values-es-rUS/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Solicitud de conexión"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> quiere configurar una conexión VPN que permite controlar el tráfico de la red. Acéptala solo si confías en la fuente. <br /> <br /> <img src=vpn_icon /> aparece en la parte superior de la pantalla cuando la VPN está activa."</string> <string name="legacy_title" msgid="192936250066580964">"La VPN está conectada."</string> - <string name="configure" msgid="4905518375574791375">"Configurar"</string> - <string name="disconnect" msgid="971412338304200056">"Desconectar"</string> <string name="session" msgid="6470628549473641030">"Sesión:"</string> <string name="duration" msgid="3584782459928719435">"Duración:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Enviados:"</string> <string name="data_received" msgid="4062776929376067820">"Recibidos:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bytes / <xliff:g id="NUMBER_1">%2$s</xliff:g> paquetes"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"No se puede conectar a la VPN siempre activa"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"Se configuró <xliff:g id="VPN_APP_0">%1$s</xliff:g> para que permaneciera activa, pero no puede establecer conexión en este momento. Tu teléfono usará una red pública hasta que pueda volver a conectarse a <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"Se configuró <xliff:g id="VPN_APP">%1$s</xliff:g> para que permaneciera activa, pero no puede establecer conexión en este momento. No podrás conectarte hasta que la VPN vuelva a establecer la conexión."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Cambiar configuración de VPN"</string> + <string name="configure" msgid="4905518375574791375">"Configurar"</string> + <string name="disconnect" msgid="971412338304200056">"Desconectar"</string> + <string name="open_app" msgid="3717639178595958667">"Abrir app"</string> + <string name="dismiss" msgid="6192859333764711227">"Descartar"</string> </resources> diff --git a/packages/VpnDialogs/res/values-es/strings.xml b/packages/VpnDialogs/res/values-es/strings.xml index cc50abe567b8..1cb56021fb36 100644 --- a/packages/VpnDialogs/res/values-es/strings.xml +++ b/packages/VpnDialogs/res/values-es/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Solicitud de conexión"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> quiere configurar una conexión VPN para controlar el tráfico de red. Solo debes aceptarla si confías en la fuente. <br /> <br /> <img src=vpn_icon /> aparece en la parte superior de la pantalla cuando se active la conexión VPN."</string> <string name="legacy_title" msgid="192936250066580964">"VPN conectada"</string> - <string name="configure" msgid="4905518375574791375">"Configurar"</string> - <string name="disconnect" msgid="971412338304200056">"Desconectar"</string> <string name="session" msgid="6470628549473641030">"Sesión:"</string> <string name="duration" msgid="3584782459928719435">"Duración:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Enviado:"</string> <string name="data_received" msgid="4062776929376067820">"Recibido:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bytes / <xliff:g id="NUMBER_1">%2$s</xliff:g> paquetes"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"No se puede establecer conexión con VPN siempre activada"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> se ha configurado para tener conexión siempre, pero no se puede conectar en este momento. El teléfono utilizará una red pública hasta que se pueda volver a conectar a <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> se ha configurado para tener conexión siempre, pero no se puede conectar en este momento. No tendrás conexión hasta que te puedas volver a conectar a la red VPN."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Cambiar ajustes de VPN"</string> + <string name="configure" msgid="4905518375574791375">"Configurar"</string> + <string name="disconnect" msgid="971412338304200056">"Desconectar"</string> + <string name="open_app" msgid="3717639178595958667">"Abrir aplicación"</string> + <string name="dismiss" msgid="6192859333764711227">"Ignorar"</string> </resources> diff --git a/packages/VpnDialogs/res/values-et/strings.xml b/packages/VpnDialogs/res/values-et/strings.xml index ee8f7691b5f6..c328cd725396 100644 --- a/packages/VpnDialogs/res/values-et/strings.xml +++ b/packages/VpnDialogs/res/values-et/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Ühendamise taotlus"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> tahab seadistada VPN-i ühenduse, mis võimaldab jälgida võrguliiklust. Nõustuge ainult siis, kui usaldate seda allikat. <br /> <br /> <img src=vpn_icon /> kuvatakse ekraani ülaservas, kui VPN on aktiivne."</string> <string name="legacy_title" msgid="192936250066580964">"VPN on ühendatud"</string> - <string name="configure" msgid="4905518375574791375">"Seadistamine"</string> - <string name="disconnect" msgid="971412338304200056">"Katkesta ühendus"</string> <string name="session" msgid="6470628549473641030">"Seansid"</string> <string name="duration" msgid="3584782459928719435">"Kestus:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Saadetud:"</string> <string name="data_received" msgid="4062776929376067820">"Vastu on võetud:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> baiti / <xliff:g id="NUMBER_1">%2$s</xliff:g> paketti"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Alati sisselülitatud VPN-iga ei saa ühendada"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"Rakendus <xliff:g id="VPN_APP_0">%1$s</xliff:g> on seadistatud pidevaks ühenduseks, kuid praegu ei saa ühendada. Seni, kuni teie telefon rakendusega <xliff:g id="VPN_APP_1">%1$s</xliff:g> ühenduse loob, kasutab see avalikku võrku."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"Rakendus <xliff:g id="VPN_APP">%1$s</xliff:g> on seadistatud pidevaks ühenduseks, kuid praegu ei saa ühendada. Ühendus taastatakse siis, kui VPN-iga saab uuesti ühenduse luua."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN-i seadete muutmine"</string> + <string name="configure" msgid="4905518375574791375">"Seadistamine"</string> + <string name="disconnect" msgid="971412338304200056">"Katkesta ühendus"</string> + <string name="open_app" msgid="3717639178595958667">"Ava rakendus"</string> + <string name="dismiss" msgid="6192859333764711227">"Loobu"</string> </resources> diff --git a/packages/VpnDialogs/res/values-eu/strings.xml b/packages/VpnDialogs/res/values-eu/strings.xml index b71650974f99..a3b7716e91d3 100644 --- a/packages/VpnDialogs/res/values-eu/strings.xml +++ b/packages/VpnDialogs/res/values-eu/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Konektatzeko eskaera"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> aplikazioak VPN bidezko konexioa ezarri nahi du sareko trafikoa kontrolatzeko. Iturburua fidagarria bada bakarrik baimendu. <br /> <br /> VPN konexioa aktibo dagoenean, <img src=vpn_icon /> agertuko da pantailaren goialdean."</string> <string name="legacy_title" msgid="192936250066580964">"VPN sarera konektatuta dago"</string> - <string name="configure" msgid="4905518375574791375">"Konfiguratu"</string> - <string name="disconnect" msgid="971412338304200056">"Deskonektatu"</string> <string name="session" msgid="6470628549473641030">"Saioa:"</string> <string name="duration" msgid="3584782459928719435">"Iraupena:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Bidalita:"</string> <string name="data_received" msgid="4062776929376067820">"Jasota:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> byte / <xliff:g id="NUMBER_1">%2$s</xliff:g> pakete"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Ezin da konektatu beti aktibatuta dagoen VPN sarea"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"Beti aktibatuta egoteko dago konfiguratuta <xliff:g id="VPN_APP_0">%1$s</xliff:g>, baina une honetan ezin da konektatu. <xliff:g id="VPN_APP_1">%1$s</xliff:g> sarera berriro konektatu ahal izan arte, sare publiko bat erabiliko du telefonoak."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"Beti aktibatuta egoteko dago konfiguratuta <xliff:g id="VPN_APP">%1$s</xliff:g>, baina une honetan ezin da konektatu. VPN sarearen konexioa berreskuratu arte, ez duzu izango konexiorik."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Aldatu VPN ezarpenak"</string> + <string name="configure" msgid="4905518375574791375">"Konfiguratu"</string> + <string name="disconnect" msgid="971412338304200056">"Deskonektatu"</string> + <string name="open_app" msgid="3717639178595958667">"Ireki aplikazioa"</string> + <string name="dismiss" msgid="6192859333764711227">"Baztertu"</string> </resources> diff --git a/packages/VpnDialogs/res/values-fa/strings.xml b/packages/VpnDialogs/res/values-fa/strings.xml index 7b17f4266503..56f847c15827 100644 --- a/packages/VpnDialogs/res/values-fa/strings.xml +++ b/packages/VpnDialogs/res/values-fa/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"درخواست اتصال"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> میخواهد یک اتصال VPN راهاندازی کند که به آن امکان نظارت بر ترافیک شبکه را میدهد. فقط در صورتی بپذیرید که به منبع آن اطمینان دارید. هنگامی که VPN فعال شد، <br /> <br /> <img src=vpn_icon /> در بالای صفحه نمایش شما نشان داده میشود."</string> <string name="legacy_title" msgid="192936250066580964">"VPN متصل است"</string> - <string name="configure" msgid="4905518375574791375">"پیکربندی"</string> - <string name="disconnect" msgid="971412338304200056">"قطع اتصال"</string> <string name="session" msgid="6470628549473641030">"جلسه:"</string> <string name="duration" msgid="3584782459928719435">"مدت زمان:"</string> <string name="data_transmitted" msgid="7988167672982199061">"ارسال شده:"</string> <string name="data_received" msgid="4062776929376067820">"دریافتی:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> بایت / <xliff:g id="NUMBER_1">%2$s</xliff:g> بسته"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"اتصال به VPN همیشه روشن امکانپذیر نیست"</string> + <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="configure" msgid="4905518375574791375">"پیکربندی"</string> + <string name="disconnect" msgid="971412338304200056">"قطع اتصال"</string> + <string name="open_app" msgid="3717639178595958667">"باز کردن برنامه"</string> + <string name="dismiss" msgid="6192859333764711227">"رد کردن"</string> </resources> diff --git a/packages/VpnDialogs/res/values-fi/strings.xml b/packages/VpnDialogs/res/values-fi/strings.xml index 23fae48b158f..91c918af09c3 100644 --- a/packages/VpnDialogs/res/values-fi/strings.xml +++ b/packages/VpnDialogs/res/values-fi/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Yhteyspyyntö"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> haluaa tehdä asetukset VPN-yhteydellä, jonka kautta sovellus voi valvoa verkkoliikennettä. Hyväksy vain, jos lähde on luotettava. <br /> <br /> <img src=vpn_icon /> näkyy ruudun yläreunassa, kun VPN on käytössä."</string> <string name="legacy_title" msgid="192936250066580964">"VPN on yhdistetty"</string> - <string name="configure" msgid="4905518375574791375">"Asetukset"</string> - <string name="disconnect" msgid="971412338304200056">"Katkaise yhteys"</string> <string name="session" msgid="6470628549473641030">"Käyttökerta"</string> <string name="duration" msgid="3584782459928719435">"Kesto:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Lähetetty:"</string> <string name="data_received" msgid="4062776929376067820">"Vastaanotettu:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> tavua / <xliff:g id="NUMBER_1">%2$s</xliff:g> pakettia"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Ei yhteyttä aina päällä olevaan VPN:ään"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> on määritetty pitämään yhteys aina päällä, mutta se ei voi muodostaa yhteyttä tällä hetkellä. Puhelin käyttää julkista verkkoa, kunnes <xliff:g id="VPN_APP_1">%1$s</xliff:g> on taas käytettävissä."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> on määritetty pitämään yhteys aina päällä, mutta se ei voi muodostaa yhteyttä tällä hetkellä. Puhelimella ei ole internetyhteyttä, ennen kuin VPN-yhteys voidaan muodostaa."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Muuta VPN-asetuksia"</string> + <string name="configure" msgid="4905518375574791375">"Asetukset"</string> + <string name="disconnect" msgid="971412338304200056">"Katkaise yhteys"</string> + <string name="open_app" msgid="3717639178595958667">"Avaa sovellus"</string> + <string name="dismiss" msgid="6192859333764711227">"Hylkää"</string> </resources> diff --git a/packages/VpnDialogs/res/values-fr-rCA/strings.xml b/packages/VpnDialogs/res/values-fr-rCA/strings.xml index 0c434a05e02b..aa86c7ca8a7f 100644 --- a/packages/VpnDialogs/res/values-fr-rCA/strings.xml +++ b/packages/VpnDialogs/res/values-fr-rCA/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Demande de connexion"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> veut configurer une connexion RPV qui permet de surveiller le trafic réseau. N\'acceptez que si vous faites confiance à la source. <br /><br /><img src=vpn_icon/> s\'affiche dans le haut de votre écran lorsqu\'une connexion RPV est active."</string> <string name="legacy_title" msgid="192936250066580964">"RPV connecté"</string> - <string name="configure" msgid="4905518375574791375">"Configurer"</string> - <string name="disconnect" msgid="971412338304200056">"Déconnecter"</string> <string name="session" msgid="6470628549473641030">"Session :"</string> <string name="duration" msgid="3584782459928719435">"Durée :"</string> <string name="data_transmitted" msgid="7988167672982199061">"Date d\'envoi :"</string> <string name="data_received" msgid="4062776929376067820">"Reçu le :"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> octets / <xliff:g id="NUMBER_1">%2$s</xliff:g> paquets"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Impossible de se connecter au RPV permanent"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> est configuré pour rester connecté en permanence, mais n\'arrive pas à se connecter en ce moment. Votre téléphone utilisera un réseau public jusqu\'à ce qu\'il puisse se reconnecter à <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> est configuré pour rester connecté en permanence, mais n\'arrive pas à se connecter en ce moment. Vous n\'aurez pas de connexion jusqu\'à ce que le RPV arrive à se reconnecter."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Modifier les paramètres RPV"</string> + <string name="configure" msgid="4905518375574791375">"Configurer"</string> + <string name="disconnect" msgid="971412338304200056">"Déconnecter"</string> + <string name="open_app" msgid="3717639178595958667">"Ouvrir l\'application"</string> + <string name="dismiss" msgid="6192859333764711227">"Ignorer"</string> </resources> diff --git a/packages/VpnDialogs/res/values-fr/strings.xml b/packages/VpnDialogs/res/values-fr/strings.xml index dadb8643ddce..2b3eacea6430 100644 --- a/packages/VpnDialogs/res/values-fr/strings.xml +++ b/packages/VpnDialogs/res/values-fr/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Demande de connexion"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> souhaite configurer une connexion VPN qui permet de surveiller le trafic réseau. N\'acceptez que si vous faites confiance à la source. <br /> <br /> <img src=vpn_icon /> s\'affiche en haut de votre écran lorsqu\'une connexion VPN est active."</string> <string name="legacy_title" msgid="192936250066580964">"VPN connecté"</string> - <string name="configure" msgid="4905518375574791375">"Configurer"</string> - <string name="disconnect" msgid="971412338304200056">"Déconnecter"</string> <string name="session" msgid="6470628549473641030">"Session :"</string> <string name="duration" msgid="3584782459928719435">"Durée :"</string> <string name="data_transmitted" msgid="7988167672982199061">"Envoyé :"</string> <string name="data_received" msgid="4062776929376067820">"Reçu :"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> octets / <xliff:g id="NUMBER_1">%2$s</xliff:g> paquets"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Impossible de se connecter au VPN permanent"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"Le VPN <xliff:g id="VPN_APP_0">%1$s</xliff:g> est configuré pour rester connecté en permanence, mais il ne peut pas se connecter actuellement. Votre téléphone utilisera un réseau public jusqu\'à ce qu\'il puisse se reconnecter à <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"Le VPN <xliff:g id="VPN_APP">%1$s</xliff:g> est configuré pour rester connecté en permanence, mais il ne peut pas se connecter actuellement. Vous ne disposerez d\'aucune connexion jusqu\'à ce que le VPN puisse se reconnecter."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Modifier les paramètres VPN"</string> + <string name="configure" msgid="4905518375574791375">"Configurer"</string> + <string name="disconnect" msgid="971412338304200056">"Déconnecter"</string> + <string name="open_app" msgid="3717639178595958667">"Ouvrir l\'application"</string> + <string name="dismiss" msgid="6192859333764711227">"Ignorer"</string> </resources> diff --git a/packages/VpnDialogs/res/values-gl/strings.xml b/packages/VpnDialogs/res/values-gl/strings.xml index 40f54fcfaad6..8a66d081a71b 100644 --- a/packages/VpnDialogs/res/values-gl/strings.xml +++ b/packages/VpnDialogs/res/values-gl/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Solicitude de conexión"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> quere configurar unha conexión VPN que lle permite controlar o tráfico da rede. Acepta soamente se confías na fonte. <br /> <br /> <img src=vpn_icon /> aparece na parte superior da pantalla cando se activa a VPN."</string> <string name="legacy_title" msgid="192936250066580964">"A VPN está conectada"</string> - <string name="configure" msgid="4905518375574791375">"Configurar"</string> - <string name="disconnect" msgid="971412338304200056">"Desconectar"</string> <string name="session" msgid="6470628549473641030">"Sesión:"</string> <string name="duration" msgid="3584782459928719435">"Duración:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Datos enviados:"</string> <string name="data_received" msgid="4062776929376067820">"Recibido:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bytes / <xliff:g id="NUMBER_1">%2$s</xliff:g> paquetes"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Non se pode establecer conexión coa VPN sempre activada"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"A <xliff:g id="VPN_APP_0">%1$s</xliff:g> está configurada para permanecer conectada sempre, pero non se pode conectar neste momento. O teu teléfono utilizará unha rede pública ata que se poida conectar de novo á <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"A <xliff:g id="VPN_APP">%1$s</xliff:g> está configurada para permanecer conectada sempre, pero non se pode conectar neste momento. Non se establecerá conexión ata que a VPN se poida conectar de novo."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Cambiar a configuración da VPN"</string> + <string name="configure" msgid="4905518375574791375">"Configurar"</string> + <string name="disconnect" msgid="971412338304200056">"Desconectar"</string> + <string name="open_app" msgid="3717639178595958667">"Abrir aplicación"</string> + <string name="dismiss" msgid="6192859333764711227">"Ignorar"</string> </resources> diff --git a/packages/VpnDialogs/res/values-gu/strings.xml b/packages/VpnDialogs/res/values-gu/strings.xml index a0fb98ab61af..961711c57c3d 100644 --- a/packages/VpnDialogs/res/values-gu/strings.xml +++ b/packages/VpnDialogs/res/values-gu/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"કનેક્શન વિનંતી"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> VPN કનેક્શન સેટ કરવા માગે છે જે તેને નેટવર્ક ટ્રાફિક મૉનિટર કરવાની મંજૂરી આપે છે. જો તમને સ્રોત પર વિશ્વાસ હોય તો જ સ્વીકારો. <br /> <br /> <img src=vpn_icon /> તમારી સ્ક્રીનની ટોચ પર ત્યારે દેખાય છે જ્યારે VPN સક્રિય હોય છે."</string> <string name="legacy_title" msgid="192936250066580964">"VPN કનેક્ટ કરેલું છે"</string> - <string name="configure" msgid="4905518375574791375">"ગોઠવો"</string> - <string name="disconnect" msgid="971412338304200056">"ડિસ્કનેક્ટ કરો"</string> <string name="session" msgid="6470628549473641030">"સત્ર:"</string> <string name="duration" msgid="3584782459928719435">"અવધિ:"</string> <string name="data_transmitted" msgid="7988167672982199061">"મોકલ્યું:"</string> <string name="data_received" msgid="4062776929376067820">"પ્રાપ્ત કર્યુ:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> બાઇટ્સ / <xliff:g id="NUMBER_1">%2$s</xliff:g> પેકેટ્સ"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"હંમેશાં-ચાલુ VPN કનેક્ટ કરી શકાતું નથી"</string> + <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="configure" msgid="4905518375574791375">"ગોઠવો"</string> + <string name="disconnect" msgid="971412338304200056">"ડિસ્કનેક્ટ કરો"</string> + <string name="open_app" msgid="3717639178595958667">"ઍપ ખોલો"</string> + <string name="dismiss" msgid="6192859333764711227">"છોડી દો"</string> </resources> diff --git a/packages/VpnDialogs/res/values-hi/strings.xml b/packages/VpnDialogs/res/values-hi/strings.xml index 15f69c6c3560..ebfcf9bd7b52 100644 --- a/packages/VpnDialogs/res/values-hi/strings.xml +++ b/packages/VpnDialogs/res/values-hi/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"कनेक्शन अनुरोध"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> VPN कनेक्शन सेट करना चाहता है जो उसे नेटवर्क ट्रैफ़िक मॉनीटर करने देता है. केवल तभी स्वीकार करें, जबकि आप स्रोत पर विश्वास करते हों. VPN सक्रिय होने पर आपकी स्क्रीन पर ऊपर <br /> <br /> <img src=vpn_icon /> दिखाई देता है."</string> <string name="legacy_title" msgid="192936250066580964">"VPN कनेक्ट है"</string> - <string name="configure" msgid="4905518375574791375">"कॉन्फ़िगर करें"</string> - <string name="disconnect" msgid="971412338304200056">"डिस्कनेक्ट करें"</string> <string name="session" msgid="6470628549473641030">"सत्र:"</string> <string name="duration" msgid="3584782459928719435">"अवधि:"</string> <string name="data_transmitted" msgid="7988167672982199061">"भेजे गए:"</string> <string name="data_received" msgid="4062776929376067820">"प्राप्त:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> बाइट / <xliff:g id="NUMBER_1">%2$s</xliff:g> पैकेट"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"हमेशा चालू रहने वाले VPN से नहीं जुड़ पा रहा है"</string> + <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="configure" msgid="4905518375574791375">"कॉन्फ़िगर करें"</string> + <string name="disconnect" msgid="971412338304200056">"डिस्कनेक्ट करें"</string> + <string name="open_app" msgid="3717639178595958667">"ऐप खोलें"</string> + <string name="dismiss" msgid="6192859333764711227">"खारिज करें"</string> </resources> diff --git a/packages/VpnDialogs/res/values-hr/strings.xml b/packages/VpnDialogs/res/values-hr/strings.xml index d58319d91fa0..aa9e436f56e7 100644 --- a/packages/VpnDialogs/res/values-hr/strings.xml +++ b/packages/VpnDialogs/res/values-hr/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Zahtjev za povezivanje"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> želi postaviti VPN vezu pomoću koje će moći nadzirati mrežni promet. Prihvatite samo ako smatrate izvor pouzdanim. Kada je VPN aktivan, pri vrhu zaslona prikazuje se <br /> <br /> <img src=vpn_icon />."</string> <string name="legacy_title" msgid="192936250066580964">"VPN je spojen"</string> - <string name="configure" msgid="4905518375574791375">"Konfiguriraj"</string> - <string name="disconnect" msgid="971412338304200056">"Prekini vezu"</string> <string name="session" msgid="6470628549473641030">"Sesija"</string> <string name="duration" msgid="3584782459928719435">"Trajanje:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Poslano:"</string> <string name="data_received" msgid="4062776929376067820">"Primljeno:"</string> <string name="data_value_format" msgid="2192466557826897580">"Bajtova: <xliff:g id="NUMBER_0">%1$s</xliff:g>/paketa: <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Povezivanje s uvijek uključenim VPN-om nije moguće"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"Mreža <xliff:g id="VPN_APP_0">%1$s</xliff:g> postavljena je da bude stalno povezana, ali se trenutačno ne može povezati. Telefon će koristiti javnu mrežu dok povezivanje s mrežom <xliff:g id="VPN_APP_1">%1$s</xliff:g> ne bude ponovo moguće."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"Mreža <xliff:g id="VPN_APP">%1$s</xliff:g> postavljena je da bude stalno povezana, ali se trenutačno ne može povezati. Telefon će koristiti javnu mrežu dok povezivanje s VPN-om ne bude ponovo moguće."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Promjena postavki VPN-a"</string> + <string name="configure" msgid="4905518375574791375">"Konfiguriraj"</string> + <string name="disconnect" msgid="971412338304200056">"Prekini vezu"</string> + <string name="open_app" msgid="3717639178595958667">"Otvori aplikaciju"</string> + <string name="dismiss" msgid="6192859333764711227">"Odbaci"</string> </resources> diff --git a/packages/VpnDialogs/res/values-hu/strings.xml b/packages/VpnDialogs/res/values-hu/strings.xml index 2ffdff83f3f6..703aa792f3c3 100644 --- a/packages/VpnDialogs/res/values-hu/strings.xml +++ b/packages/VpnDialogs/res/values-hu/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Kapcsolódási kérés"</string> <string name="warning" msgid="809658604548412033">"A(z) <xliff:g id="APP">%s</xliff:g> VPN kapcsolatot akar beállítani, amelynek segítségével figyelheti a hálózati forgalmat. Csak akkor fogadja el, ha megbízik a forrásban. <br /> <br /> Amikor a VPN aktív, <img src=vpn_icon /> ikon jelenik meg a képernyő tetején."</string> <string name="legacy_title" msgid="192936250066580964">"A VPN csatlakoztatva van"</string> - <string name="configure" msgid="4905518375574791375">"Konfigurálás"</string> - <string name="disconnect" msgid="971412338304200056">"Kapcsolat bontása"</string> <string name="session" msgid="6470628549473641030">"Munkamenet:"</string> <string name="duration" msgid="3584782459928719435">"Időtartam:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Elküldve:"</string> <string name="data_received" msgid="4062776929376067820">"Érkezett:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bájt/<xliff:g id="NUMBER_1">%2$s</xliff:g> adatcsomag"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Nem lehet csatlakozni a mindig bekapcsolt állapotú VPN-hez"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"A(z) <xliff:g id="VPN_APP_0">%1$s</xliff:g> úgy van beállítva, hogy mindig fenntartsa a kapcsolatot, de jelenleg nem képes csatlakozni. Telefonja nyilvános hálózatot használ addig, amíg nem sikerül újra csatlakozni a következőhöz: <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"A(z) <xliff:g id="VPN_APP">%1$s</xliff:g> úgy van beállítva, hogy mindig fenntartsa a kapcsolatot, de jelenleg nem képes csatlakozni. Amíg a VPN újra nem csatlakozik, Önnek nem lesz internetkapcsolata."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN-beállítások módosítása"</string> + <string name="configure" msgid="4905518375574791375">"Konfigurálás"</string> + <string name="disconnect" msgid="971412338304200056">"Kapcsolat bontása"</string> + <string name="open_app" msgid="3717639178595958667">"Alkalmazás indítása"</string> + <string name="dismiss" msgid="6192859333764711227">"Bezárás"</string> </resources> diff --git a/packages/VpnDialogs/res/values-hy/strings.xml b/packages/VpnDialogs/res/values-hy/strings.xml index 2a27a9366df0..c296c8547283 100644 --- a/packages/VpnDialogs/res/values-hy/strings.xml +++ b/packages/VpnDialogs/res/values-hy/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Միացման հայց"</string> <string name="warning" msgid="809658604548412033">"«<xliff:g id="APP">%s</xliff:g>» հավելվածը ցանկանում է VPN կապ հաստատել՝ ցանցային երթևեկը հսկելու համար: Թույլատրեք, միայն եթե վստահում եք աղբյուրին: Երբ VPN-ն ակտիվ լինի, ձեր էկրանի վերին հատվածում կհայտնվի <br /> <br /> <img src=vpn_icon /> պատկերը:"</string> <string name="legacy_title" msgid="192936250066580964">"VPN-ը կապակցված է"</string> - <string name="configure" msgid="4905518375574791375">"Կարգավորել"</string> - <string name="disconnect" msgid="971412338304200056">"Անջատել"</string> <string name="session" msgid="6470628549473641030">"Աշխատաշրջան`"</string> <string name="duration" msgid="3584782459928719435">"Տևողությունը՝"</string> <string name="data_transmitted" msgid="7988167672982199061">"Ուղարկվել է՝"</string> <string name="data_received" msgid="4062776929376067820">"Ստացվել է՝"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> բայթ / <xliff:g id="NUMBER_1">%2$s</xliff:g> փաթեթ"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Չի հաջողվում միանալ միշտ միացված VPN-ին"</string> + <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="configure" msgid="4905518375574791375">"Կարգավորել"</string> + <string name="disconnect" msgid="971412338304200056">"Անջատել"</string> + <string name="open_app" msgid="3717639178595958667">"Բացել հավելվածը"</string> + <string name="dismiss" msgid="6192859333764711227">"Փակել"</string> </resources> diff --git a/packages/VpnDialogs/res/values-in/strings.xml b/packages/VpnDialogs/res/values-in/strings.xml index 5553d70e9f4f..386c24a73a36 100644 --- a/packages/VpnDialogs/res/values-in/strings.xml +++ b/packages/VpnDialogs/res/values-in/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Permintaan sambungan"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ingin menyiapkan sambungan VPN yang memungkinkannya memantau lalu-lintas jaringan. Terima hanya jika Anda memercayai sumber. <br /> <br /> <img src=vpn_icon /> muncul di bagian atas layar Anda saat VPN aktif."</string> <string name="legacy_title" msgid="192936250066580964">"VPN tersambung"</string> - <string name="configure" msgid="4905518375574791375">"Konfigurasikan"</string> - <string name="disconnect" msgid="971412338304200056">"Putuskan sambungan"</string> <string name="session" msgid="6470628549473641030">"Sesi:"</string> <string name="duration" msgid="3584782459928719435">"Durasi:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Terkirim:"</string> <string name="data_received" msgid="4062776929376067820">"Diterima:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bita / <xliff:g id="NUMBER_1">%2$s</xliff:g> paket"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Tidak dapat tersambung ke VPN yang selalu aktif"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> disiapkan untuk selalu tersambung, tetapi saat ini tidak dapat tersambung. Ponsel akan menggunakan jaringan publik sampai dapat tersambung ulang ke <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> disiapkan untuk selalu tersambung, tetapi saat ini tidak dapat tersambung. Anda akan tersambung jika VPN dapat tersambung ulang."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Ubah setelan VPN"</string> + <string name="configure" msgid="4905518375574791375">"Konfigurasikan"</string> + <string name="disconnect" msgid="971412338304200056">"Putuskan sambungan"</string> + <string name="open_app" msgid="3717639178595958667">"Buka aplikasi"</string> + <string name="dismiss" msgid="6192859333764711227">"Tutup"</string> </resources> diff --git a/packages/VpnDialogs/res/values-is/strings.xml b/packages/VpnDialogs/res/values-is/strings.xml index 059c6a9f724e..70fb40fc467c 100644 --- a/packages/VpnDialogs/res/values-is/strings.xml +++ b/packages/VpnDialogs/res/values-is/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Beiðni um tengingu"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> vill setja upp VPN-tengingu til þess að geta fylgst með netumferð. Samþykktu þetta aðeins ef þú treystir upprunanum. <br /> <br /> <img src=vpn_icon /> birtist efst á skjánum þegar VPN er virkt."</string> <string name="legacy_title" msgid="192936250066580964">"VPN er tengt"</string> - <string name="configure" msgid="4905518375574791375">"Stilla"</string> - <string name="disconnect" msgid="971412338304200056">"Aftengja"</string> <string name="session" msgid="6470628549473641030">"Lota:"</string> <string name="duration" msgid="3584782459928719435">"Tímalengd:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Sent:"</string> <string name="data_received" msgid="4062776929376067820">"Móttekið:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bæti / <xliff:g id="NUMBER_1">%2$s</xliff:g> pakkar"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Ekki er hægt að tengjast sívirku VPN"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> er sett upp til að halda tengingu öllum stundum, en það getur ekki tengst að svo stöddu. Síminn notast við opið netkerfi þar til hann getur endurtengst við <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> er sett upp til að halda tengingu öllum stundum, en það getur ekki tengst að svo stöddu. Þú verður án tengingar þar til VPN getur endurtengst."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Breyta stillingum VPN"</string> + <string name="configure" msgid="4905518375574791375">"Stilla"</string> + <string name="disconnect" msgid="971412338304200056">"Aftengja"</string> + <string name="open_app" msgid="3717639178595958667">"Opna forrit"</string> + <string name="dismiss" msgid="6192859333764711227">"Hunsa"</string> </resources> diff --git a/packages/VpnDialogs/res/values-it/strings.xml b/packages/VpnDialogs/res/values-it/strings.xml index e601a5f56bdf..2602493faf00 100644 --- a/packages/VpnDialogs/res/values-it/strings.xml +++ b/packages/VpnDialogs/res/values-it/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Richiesta di connessione"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> vuole impostare una connessione VPN che le consenta di monitorare il traffico di rete. Accetta soltanto se ritieni la fonte attendibile. Quando la connessione VPN è attiva, nella parte superiore dello schermo viene visualizzata l\'icona <br /> <br /> <img src=vpn_icon />."</string> <string name="legacy_title" msgid="192936250066580964">"VPN connessa"</string> - <string name="configure" msgid="4905518375574791375">"Configura"</string> - <string name="disconnect" msgid="971412338304200056">"Disconnetti"</string> <string name="session" msgid="6470628549473641030">"Sessione:"</string> <string name="duration" msgid="3584782459928719435">"Durata:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Inviati:"</string> <string name="data_received" msgid="4062776929376067820">"Ricevuti:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> byte/<xliff:g id="NUMBER_1">%2$s</xliff:g> pacchetti"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Impossibile connettersi alla VPN sempre attiva"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> è impostata per rimanere sempre connessa, ma al momento non è possibile stabilire la connessione. Il telefono userà una rete pubblica finché potrà riconnettersi a <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> è impostata per rimanere sempre connessa, ma al momento non è possibile stabilire la connessione. Non avrai connessione finché non sarà possibile riconnettersi alla VPN."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Cambia le impostazioni VPN"</string> + <string name="configure" msgid="4905518375574791375">"Configura"</string> + <string name="disconnect" msgid="971412338304200056">"Disconnetti"</string> + <string name="open_app" msgid="3717639178595958667">"Apri app"</string> + <string name="dismiss" msgid="6192859333764711227">"Ignora"</string> </resources> diff --git a/packages/VpnDialogs/res/values-iw/strings.xml b/packages/VpnDialogs/res/values-iw/strings.xml index e5d2f8952c42..55ac85f2c76a 100644 --- a/packages/VpnDialogs/res/values-iw/strings.xml +++ b/packages/VpnDialogs/res/values-iw/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"בקשת חיבור"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> רוצה להגדיר חיבור VPN שיאפשר לו לפקח על תעבורת הרשת. אשר את הבקשה רק אם אתה נותן אמון במקור. <br /> <br /> <img src=vpn_icon /> מופיע בחלק העליון של המסך כאשר VPN פעיל."</string> <string name="legacy_title" msgid="192936250066580964">"VPN מחובר"</string> - <string name="configure" msgid="4905518375574791375">"הגדר"</string> - <string name="disconnect" msgid="971412338304200056">"נתק"</string> <string name="session" msgid="6470628549473641030">"הפעלה"</string> <string name="duration" msgid="3584782459928719435">"משך:"</string> <string name="data_transmitted" msgid="7988167672982199061">"נשלח:"</string> <string name="data_received" msgid="4062776929376067820">"התקבל:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> בתים / <xliff:g id="NUMBER_1">%2$s</xliff:g> מנות"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"לא ניתן להתחבר ל-VPN שפועל כל הזמן"</string> + <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="configure" msgid="4905518375574791375">"הגדר"</string> + <string name="disconnect" msgid="971412338304200056">"נתק"</string> + <string name="open_app" msgid="3717639178595958667">"לאפליקציה"</string> + <string name="dismiss" msgid="6192859333764711227">"סגירה"</string> </resources> diff --git a/packages/VpnDialogs/res/values-ja/strings.xml b/packages/VpnDialogs/res/values-ja/strings.xml index 0e65866bf244..9dbf38bf6e7d 100644 --- a/packages/VpnDialogs/res/values-ja/strings.xml +++ b/packages/VpnDialogs/res/values-ja/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"接続リクエスト"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g>がネットワークトラフィックを監視するためVPN接続をセットアップしようとしています。ソースを信頼できる場合にのみ許可してください。<br /> <br /> VPNがアクティブになると画面の上部に<img src=vpn_icon />が表示されます。"</string> <string name="legacy_title" msgid="192936250066580964">"VPN接続済み"</string> - <string name="configure" msgid="4905518375574791375">"設定"</string> - <string name="disconnect" msgid="971412338304200056">"切断"</string> <string name="session" msgid="6470628549473641030">"セッション:"</string> <string name="duration" msgid="3584782459928719435">"期間:"</string> <string name="data_transmitted" msgid="7988167672982199061">"送信:"</string> <string name="data_received" msgid="4062776929376067820">"受信:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g>バイト/<xliff:g id="NUMBER_1">%2$s</xliff:g>パケット"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"常時接続 VPN に接続できません"</string> + <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="configure" msgid="4905518375574791375">"設定"</string> + <string name="disconnect" msgid="971412338304200056">"切断"</string> + <string name="open_app" msgid="3717639178595958667">"アプリを開く"</string> + <string name="dismiss" msgid="6192859333764711227">"閉じる"</string> </resources> diff --git a/packages/VpnDialogs/res/values-ka/strings.xml b/packages/VpnDialogs/res/values-ka/strings.xml index 61f3b0f23558..e5a07532c32e 100644 --- a/packages/VpnDialogs/res/values-ka/strings.xml +++ b/packages/VpnDialogs/res/values-ka/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"კავშირის მოთხოვნა"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> სურს დააყენოს VPN კავშირი, რაც ქსელის ტრაფიკის მონიტორინგის საშუალებას იძლევა. მიიღოთ მხოლოდ ისეთ შემთხვევაში, თუ წყაროს ენდობით. <br /> <br /> <img src=vpn_icon /> თქვენი ეკრანის სიის თავში გამოჩნდება, როდესაც VPN აქტიურია."</string> <string name="legacy_title" msgid="192936250066580964">"VPN დაკავშირებულია"</string> - <string name="configure" msgid="4905518375574791375">"კონფიგურაცია"</string> - <string name="disconnect" msgid="971412338304200056">"კავშირის გაწყვეტა"</string> <string name="session" msgid="6470628549473641030">"სესია:"</string> <string name="duration" msgid="3584782459928719435">"ხანგრძლივობა:"</string> <string name="data_transmitted" msgid="7988167672982199061">"გაგზავნილი:"</string> <string name="data_received" msgid="4062776929376067820">"მიღებული:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> ბაიტი / <xliff:g id="NUMBER_1">%2$s</xliff:g> პაკეტი"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"მუდმივად ჩართულ VPN-თან დაკავშირება ვერ ხერხდება"</string> + <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="configure" msgid="4905518375574791375">"კონფიგურაცია"</string> + <string name="disconnect" msgid="971412338304200056">"კავშირის გაწყვეტა"</string> + <string name="open_app" msgid="3717639178595958667">"გახსენით აპი"</string> + <string name="dismiss" msgid="6192859333764711227">"დახურვა"</string> </resources> diff --git a/packages/VpnDialogs/res/values-kk/strings.xml b/packages/VpnDialogs/res/values-kk/strings.xml index 8514d3c6b377..79f79c34e1b4 100644 --- a/packages/VpnDialogs/res/values-kk/strings.xml +++ b/packages/VpnDialogs/res/values-kk/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Байланысты сұрау"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> VPN байланысын орнатқысы келеді, бұл оған желілік трафикті бақылауға мүмкіндік береді. Көзге сенсеңіз ғана қабылдаңыз. VPN белсенді болғанда экранның жоғарғы жағында <br /> <br /> <img src=vpn_icon /> көрсетіледі."</string> <string name="legacy_title" msgid="192936250066580964">"ВЖЖ қосылған"</string> - <string name="configure" msgid="4905518375574791375">"Конфигурациялау"</string> - <string name="disconnect" msgid="971412338304200056">"Ажырату"</string> <string name="session" msgid="6470628549473641030">"Сессия:"</string> <string name="duration" msgid="3584782459928719435">"Ұзақтығы:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Жіберілді:"</string> <string name="data_received" msgid="4062776929376067820">"Қабылданды:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> байт / <xliff:g id="NUMBER_1">%2$s</xliff:g> жинақ"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Әрқашан қосулы VPN желісіне қосылу мүмкін емес"</string> + <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="configure" msgid="4905518375574791375">"Конфигурациялау"</string> + <string name="disconnect" msgid="971412338304200056">"Ажырату"</string> + <string name="open_app" msgid="3717639178595958667">"Қолданбаны ашу"</string> + <string name="dismiss" msgid="6192859333764711227">"Жабу"</string> </resources> diff --git a/packages/VpnDialogs/res/values-km/strings.xml b/packages/VpnDialogs/res/values-km/strings.xml index 027f1045889e..06f34dbf2733 100644 --- a/packages/VpnDialogs/res/values-km/strings.xml +++ b/packages/VpnDialogs/res/values-km/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"សំណើសុំការតភ្ជាប់"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ចង់បង្កើតការតភ្ជាប់ VPN ដែលអនុញ្ញាតឲ្យវាត្រួតពិនិត្យចរាចរបណ្ដាញ។ ព្រមទទួល ប្រសិនបើអ្នកទុកចិត្តលើប្រភពតែប៉ុណ្ណោះ។ <br /> <br /> <img src=vpn_icon /> នឹងលេចឡើងនៅផ្នែកខាងលើនៃអេក្រង់របស់អ្នក ពេល VPN សកម្ម។"</string> <string name="legacy_title" msgid="192936250066580964">"បានភ្ជាប់ VPN"</string> - <string name="configure" msgid="4905518375574791375">"កំណត់រចនាសម្ព័ន្ធ"</string> - <string name="disconnect" msgid="971412338304200056">"ផ្ដាច់"</string> <string name="session" msgid="6470628549473641030">"សម័យ៖"</string> <string name="duration" msgid="3584782459928719435">"ថិរវេលា៖"</string> <string name="data_transmitted" msgid="7988167672982199061">"បានផ្ញើ៖"</string> <string name="data_received" msgid="4062776929376067820">"បានទទួល៖"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> បៃ / <xliff:g id="NUMBER_1">%2$s</xliff:g> កញ្ចប់ព័ត៌មាន"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"មិនអាចភ្ជាប់ជាមួយ VPN បើកជានិច្ច"</string> + <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="configure" msgid="4905518375574791375">"កំណត់រចនាសម្ព័ន្ធ"</string> + <string name="disconnect" msgid="971412338304200056">"ផ្ដាច់"</string> + <string name="open_app" msgid="3717639178595958667">"បើកកម្មវិធី"</string> + <string name="dismiss" msgid="6192859333764711227">"បដិសេធ"</string> </resources> diff --git a/packages/VpnDialogs/res/values-kn/strings.xml b/packages/VpnDialogs/res/values-kn/strings.xml index b3f5a10d1e26..040cd6c5aeda 100644 --- a/packages/VpnDialogs/res/values-kn/strings.xml +++ b/packages/VpnDialogs/res/values-kn/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"ಸಂಪರ್ಕ ವಿನಂತಿ"</string> <string name="warning" msgid="809658604548412033">"ನೆಟ್ವರ್ಕ್ ಟ್ರಾಫಿಕ್ ಅನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಲು ಅನುಮತಿಸುವಂತಹ VPN ಸಂಪರ್ಕವನ್ನು ಹೊಂದಿಸಲು <xliff:g id="APP">%s</xliff:g> ಬಯಸುತ್ತದೆ. ನೀವು ಮೂಲವನ್ನು ನಂಬಿದರೆ ಮಾತ್ರ ಸಮ್ಮತಿಸಿ. VPN ಸಕ್ರಿಯವಾಗಿರುವಾಗ ನಿಮ್ಮ ಪರದೆಯ ಮೇಲ್ಭಾಗದಲ್ಲಿ <br /> <br /> <img src=vpn_icon /> ಗೋರಿಸುತ್ತದೆ."</string> <string name="legacy_title" msgid="192936250066580964">"VPN ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string> - <string name="configure" msgid="4905518375574791375">"ಕಾನ್ಫಿಗರ್ ಮಾಡು"</string> - <string name="disconnect" msgid="971412338304200056">"ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸು"</string> <string name="session" msgid="6470628549473641030">"ಸೆಷನ್:"</string> <string name="duration" msgid="3584782459928719435">"ಅವಧಿ:"</string> <string name="data_transmitted" msgid="7988167672982199061">"ಕಳುಹಿಸಲಾಗಿದೆ:"</string> <string name="data_received" msgid="4062776929376067820">"ಸ್ವೀಕರಿಸಲಾಗಿದೆ:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> ಬೈಟ್ಗಳು / <xliff:g id="NUMBER_1">%2$s</xliff:g> ಪ್ಯಾಕೆಟ್ಗಳು"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"ಯಾವಾಗಲೂ ಆನ್ ಆಗಿರುವ VPN ಗೆ ಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string> + <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="configure" msgid="4905518375574791375">"ಕಾನ್ಫಿಗರ್ ಮಾಡು"</string> + <string name="disconnect" msgid="971412338304200056">"ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸು"</string> + <string name="open_app" msgid="3717639178595958667">"ಅಪ್ಲಿಕೇಶನ್ ತೆರೆಯಿರಿ"</string> + <string name="dismiss" msgid="6192859333764711227">"ವಜಾಗೊಳಿಸಿ"</string> </resources> diff --git a/packages/VpnDialogs/res/values-ko/strings.xml b/packages/VpnDialogs/res/values-ko/strings.xml index b9c7ba1e0b6f..6ad497680ae7 100644 --- a/packages/VpnDialogs/res/values-ko/strings.xml +++ b/packages/VpnDialogs/res/values-ko/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"연결 요청"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g>에서 네트워크 트래픽을 모니터링하도록 허용하는 VPN 연결을 설정하려고 합니다. 출처를 신뢰할 수 있는 경우에만 수락하세요. VPN이 활성화되면 <br /> <br /> <img src=vpn_icon />이 화면 위에 표시됩니다."</string> <string name="legacy_title" msgid="192936250066580964">"VPN이 연결되었습니다."</string> - <string name="configure" msgid="4905518375574791375">"설정"</string> - <string name="disconnect" msgid="971412338304200056">"연결 끊기"</string> <string name="session" msgid="6470628549473641030">"세션:"</string> <string name="duration" msgid="3584782459928719435">"기간:"</string> <string name="data_transmitted" msgid="7988167672982199061">"보냄:"</string> <string name="data_received" msgid="4062776929376067820">"수신됨:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g>바이트/<xliff:g id="NUMBER_1">%2$s</xliff:g>패킷"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"연결 유지 VPN에 연결할 수 없음"</string> + <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="configure" msgid="4905518375574791375">"설정"</string> + <string name="disconnect" msgid="971412338304200056">"연결 끊기"</string> + <string name="open_app" msgid="3717639178595958667">"앱 열기"</string> + <string name="dismiss" msgid="6192859333764711227">"닫기"</string> </resources> diff --git a/packages/VpnDialogs/res/values-ky/strings.xml b/packages/VpnDialogs/res/values-ky/strings.xml index 44fbabddc25e..4e2f698bb1e5 100644 --- a/packages/VpnDialogs/res/values-ky/strings.xml +++ b/packages/VpnDialogs/res/values-ky/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Туташуу сурамы"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> тармактык трафикти көзөмөлдөөгө уруксат берген VPN туташуусун орноткусу келет. Аны булакка ишенсеңиз гана кабыл алыңыз. <br /> <br /> <img src=vpn_icon /> VPN иштеп турганда экраныңыздын жогору жагынан көрүнөт."</string> <string name="legacy_title" msgid="192936250066580964">"VPN байланышта"</string> - <string name="configure" msgid="4905518375574791375">"Конфигурациялоо"</string> - <string name="disconnect" msgid="971412338304200056">"Ажыратуу"</string> <string name="session" msgid="6470628549473641030">"Сессия:"</string> <string name="duration" msgid="3584782459928719435">"Узактыгы:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Жөнөтүлдү:"</string> <string name="data_received" msgid="4062776929376067820">"Келди:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> байт / <xliff:g id="NUMBER_1">%2$s</xliff:g> пакет"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Ар дайым күйүк VPN\'ге туташа албай жатат"</string> + <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="configure" msgid="4905518375574791375">"Конфигурациялоо"</string> + <string name="disconnect" msgid="971412338304200056">"Ажыратуу"</string> + <string name="open_app" msgid="3717639178595958667">"Колдонмону ачуу"</string> + <string name="dismiss" msgid="6192859333764711227">"Четке кагуу"</string> </resources> diff --git a/packages/VpnDialogs/res/values-lo/strings.xml b/packages/VpnDialogs/res/values-lo/strings.xml index 6248f8d9d441..c591308480c1 100644 --- a/packages/VpnDialogs/res/values-lo/strings.xml +++ b/packages/VpnDialogs/res/values-lo/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"ການຮ້ອງຂໍການເຊື່ອມຕໍ່"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ຕ້ອງການຕັ້ງຄ່າການເຊື່ອມຕໍ່ VPN ທີ່ອະນຸຍາດໃຫ້ຕິດຕາມທຣາບຟິກເຄືອຂ່າຍໄດ້. ທ່ານຄວນຍິນຍອມສະເພາະໃນກໍລະນີທີ່ທ່ານເຊື່ອຖືແຫລ່ງຂໍ້ມູນເທົ່ານັ້ນ. <br /> <br /> <img src=vpn_icon /> ຈະປາກົດຢູ່ດ້ານເທິງຂອງໜ້າຈໍເມື່ອມີການເປີດໃຊ້ VPN."</string> <string name="legacy_title" msgid="192936250066580964">"ເຊື່ອມຕໍ່ VPN ແລ້ວ"</string> - <string name="configure" msgid="4905518375574791375">"ປັບຄ່າ"</string> - <string name="disconnect" msgid="971412338304200056">"ຕັດການເຊື່ອມຕໍ່"</string> <string name="session" msgid="6470628549473641030">"ເຊສຊັນ:"</string> <string name="duration" msgid="3584782459928719435">"ໄລຍະເວລາ:"</string> <string name="data_transmitted" msgid="7988167672982199061">"ສົ່ງ:"</string> <string name="data_received" msgid="4062776929376067820">"ຮັບ:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> ໄບ / <xliff:g id="NUMBER_1">%2$s</xliff:g> ແພັກເກັດ"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"ບໍ່ສາມາດເຊື່ອມຕໍ່ຫາ VPN ແບບເປີດຕະຫຼອດໄດ້"</string> + <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="configure" msgid="4905518375574791375">"ປັບຄ່າ"</string> + <string name="disconnect" msgid="971412338304200056">"ຕັດການເຊື່ອມຕໍ່"</string> + <string name="open_app" msgid="3717639178595958667">"ເປີດແອັບ"</string> + <string name="dismiss" msgid="6192859333764711227">"ປິດໄວ້"</string> </resources> diff --git a/packages/VpnDialogs/res/values-lt/strings.xml b/packages/VpnDialogs/res/values-lt/strings.xml index f70d55d7ae3f..8846310730ce 100644 --- a/packages/VpnDialogs/res/values-lt/strings.xml +++ b/packages/VpnDialogs/res/values-lt/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Ryšio užklausa"</string> <string name="warning" msgid="809658604548412033">"„<xliff:g id="APP">%s</xliff:g>“ nori nustatyti VPN ryšį, kad galėtų stebėti tinklo srautą. Sutikite, tik jei pasitikite šaltiniu. <br /> <br /> <img src=vpn_icon /> rodoma ekrano viršuje, kai VPN aktyvus."</string> <string name="legacy_title" msgid="192936250066580964">"VPN prijungtas"</string> - <string name="configure" msgid="4905518375574791375">"Konfigūruoti"</string> - <string name="disconnect" msgid="971412338304200056">"Atsijungti"</string> <string name="session" msgid="6470628549473641030">"Sesija"</string> <string name="duration" msgid="3584782459928719435">"Trukmė:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Išsiųsta"</string> <string name="data_received" msgid="4062776929376067820">"Gauta"</string> <string name="data_value_format" msgid="2192466557826897580">"Baitų: <xliff:g id="NUMBER_0">%1$s</xliff:g> baitų / paketų: <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Prisijungti prie visada įjungto VPN nepavyko"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"„<xliff:g id="VPN_APP_0">%1$s</xliff:g>“ nustatyta taip, kad prie jos visada būtų galima prisijungti, bet šiuo metu prisijungti nepavyksta. Kol vėl galės prisijungti prie „<xliff:g id="VPN_APP_1">%1$s</xliff:g>“, telefonas naudos viešąjį tinklą."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"„<xliff:g id="VPN_APP">%1$s</xliff:g>“ nustatyta taip, kad prie jos visada būtų galima prisijungti, bet šiuo metu prisijungti nepavyksta. Kol prie VPN bus galima prisijungti iš naujo, ryšio neturėsite."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Keisti VPN nustatymus"</string> + <string name="configure" msgid="4905518375574791375">"Konfigūruoti"</string> + <string name="disconnect" msgid="971412338304200056">"Atsijungti"</string> + <string name="open_app" msgid="3717639178595958667">"Atidaryti programą"</string> + <string name="dismiss" msgid="6192859333764711227">"Atsisakyti"</string> </resources> diff --git a/packages/VpnDialogs/res/values-lv/strings.xml b/packages/VpnDialogs/res/values-lv/strings.xml index ff59d1841cf5..07625b6173c6 100644 --- a/packages/VpnDialogs/res/values-lv/strings.xml +++ b/packages/VpnDialogs/res/values-lv/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Savienojuma pieprasījums"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> vēlas izveidot VPN savienojumu, kas ļaus pārraudzīt tīkla datplūsmu. Piekrītiet tikai tad, ja uzticaties avotam. <br /> <br /> <img src=vpn_icon /> tiek rādīta ekrāna augšdaļā, kad darbojas VPN."</string> <string name="legacy_title" msgid="192936250066580964">"Ir izveidots savienojums ar VPN"</string> - <string name="configure" msgid="4905518375574791375">"Konfigurēt"</string> - <string name="disconnect" msgid="971412338304200056">"Pārtraukt savienojumu"</string> <string name="session" msgid="6470628549473641030">"Sesija:"</string> <string name="duration" msgid="3584782459928719435">"Ilgums:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Nosūtīts:"</string> <string name="data_received" msgid="4062776929376067820">"Saņemts:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> baiti/<xliff:g id="NUMBER_1">%2$s</xliff:g> paketes"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Nevar izveidot savienojumu ar vienmēr ieslēgtu VPN"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"Lietotnei <xliff:g id="VPN_APP_0">%1$s</xliff:g> ir iestatīts vienmēr ieslēgts savienojums, taču pašlaik nevar izveidot savienojumu. Jūsu tālrunī tiks izmantots publisks tīkls, līdz varēs izveidot savienojumu ar lietotni <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"Lietotnei <xliff:g id="VPN_APP">%1$s</xliff:g> ir iestatīts vienmēr ieslēgts savienojums, taču pašlaik nevar izveidot savienojumu. Savienojums būs pieejams, kad atkal varēs izveidot savienojumu ar VPN."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Mainīt VPN iestatījumus"</string> + <string name="configure" msgid="4905518375574791375">"Konfigurēt"</string> + <string name="disconnect" msgid="971412338304200056">"Pārtraukt savienojumu"</string> + <string name="open_app" msgid="3717639178595958667">"Atvērt lietotni"</string> + <string name="dismiss" msgid="6192859333764711227">"Nerādīt"</string> </resources> diff --git a/packages/VpnDialogs/res/values-mk/strings.xml b/packages/VpnDialogs/res/values-mk/strings.xml index d835cfca6494..b5a64f213066 100644 --- a/packages/VpnDialogs/res/values-mk/strings.xml +++ b/packages/VpnDialogs/res/values-mk/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Барање за поврзување"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> сака да постави поврзување со ВПН коешто му дозволува да го набљудува сообраќајот на мрежата. Прифатете само доколку му верувате на изворот. <br /> <br /> <img src=vpn_icon /> се појавува на врвот на екранот кога ВПН е активна."</string> <string name="legacy_title" msgid="192936250066580964">"VPN е поврзана"</string> - <string name="configure" msgid="4905518375574791375">"Конфигурирај"</string> - <string name="disconnect" msgid="971412338304200056">"Исклучи"</string> <string name="session" msgid="6470628549473641030">"Сесија:"</string> <string name="duration" msgid="3584782459928719435">"Времетраење:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Испратено:"</string> <string name="data_received" msgid="4062776929376067820">"Примени:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> бајти / <xliff:g id="NUMBER_1">%2$s</xliff:g> пакети"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Не може да се поврзе на секогаш вклучената VPN"</string> + <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="configure" msgid="4905518375574791375">"Конфигурирај"</string> + <string name="disconnect" msgid="971412338304200056">"Исклучи"</string> + <string name="open_app" msgid="3717639178595958667">"Отвори ја апликацијата"</string> + <string name="dismiss" msgid="6192859333764711227">"Отфрли"</string> </resources> diff --git a/packages/VpnDialogs/res/values-ml/strings.xml b/packages/VpnDialogs/res/values-ml/strings.xml index 3dd76d88328d..680d0ef539b7 100644 --- a/packages/VpnDialogs/res/values-ml/strings.xml +++ b/packages/VpnDialogs/res/values-ml/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"കണക്ഷൻ അഭ്യർത്ഥന"</string> <string name="warning" msgid="809658604548412033">"നെറ്റ്വർക്ക് ട്രാഫിക്ക് നിരീക്ഷിക്കാൻ അനുവദിക്കുന്ന ഒരു VPN കണക്ഷൻ <xliff:g id="APP">%s</xliff:g> സജ്ജീകരിക്കേണ്ടതുണ്ട്. ഉറവിടം പരിചിതമാണെങ്കിൽ മാത്രം അംഗീകരിക്കുക. VPN സജീവമാകുമ്പോൾ <br /> <br /> <img src=vpn_icon /> നിങ്ങളുടെ സ്ക്രീനിന്റെ മുകളിൽ ദൃശ്യമാകുന്നു."</string> <string name="legacy_title" msgid="192936250066580964">"VPN കണക്റ്റുചെയ്തു"</string> - <string name="configure" msgid="4905518375574791375">"കോൺഫിഗർ ചെയ്യുക"</string> - <string name="disconnect" msgid="971412338304200056">"വിച്ഛേദിക്കുക"</string> <string name="session" msgid="6470628549473641030">"സെഷൻ:"</string> <string name="duration" msgid="3584782459928719435">"സമയദൈര്ഘ്യം:"</string> <string name="data_transmitted" msgid="7988167672982199061">"അയച്ചത്:"</string> <string name="data_received" msgid="4062776929376067820">"ലഭിച്ചത്:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> ബൈറ്റുകൾ / <xliff:g id="NUMBER_1">%2$s</xliff:g> പാക്കറ്റുകൾ"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"എപ്പോഴും ഓണായിരിക്കുന്ന VPN-ലേക്ക് കണക്റ്റുചെയ്യാനായില്ല"</string> + <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="configure" msgid="4905518375574791375">"കോൺഫിഗർ ചെയ്യുക"</string> + <string name="disconnect" msgid="971412338304200056">"വിച്ഛേദിക്കുക"</string> + <string name="open_app" msgid="3717639178595958667">"ആപ്പ് തുറക്കുക"</string> + <string name="dismiss" msgid="6192859333764711227">"നിരസിക്കുക"</string> </resources> diff --git a/packages/VpnDialogs/res/values-mn/strings.xml b/packages/VpnDialogs/res/values-mn/strings.xml index 1b6cb6c1e1f5..9aa104aff5ab 100644 --- a/packages/VpnDialogs/res/values-mn/strings.xml +++ b/packages/VpnDialogs/res/values-mn/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Холболтын хүсэлт"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> нь сүлжээний трафикыг хянах боломж бүхий VPN холболт үүсгэхийг хүсэж байна. Та зөвхөн эх үүсвэрт итгэж байгаа бол зөвшөөрнө үү. <br /> <br /> <img src=vpn_icon /> таны дэлгэц дээр VPN идэвхтэй үед гарч ирнэ."</string> <string name="legacy_title" msgid="192936250066580964">"VPN холбогдов"</string> - <string name="configure" msgid="4905518375574791375">"Тохируулах"</string> - <string name="disconnect" msgid="971412338304200056">"Салгах"</string> <string name="session" msgid="6470628549473641030">"Сешн:"</string> <string name="duration" msgid="3584782459928719435">"Үргэлжлэх хугацаа:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Илгээсэн:"</string> <string name="data_received" msgid="4062776929376067820">"Хүлээн авсан:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> байт/ <xliff:g id="NUMBER_1">%2$s</xliff:g> пакет"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Тогтмол асаалттай VPN-д холбогдох боломжгүй"</string> + <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="configure" msgid="4905518375574791375">"Тохируулах"</string> + <string name="disconnect" msgid="971412338304200056">"Салгах"</string> + <string name="open_app" msgid="3717639178595958667">"Апп нээх"</string> + <string name="dismiss" msgid="6192859333764711227">"Хаах"</string> </resources> diff --git a/packages/VpnDialogs/res/values-mr/strings.xml b/packages/VpnDialogs/res/values-mr/strings.xml index a325b90fafd9..129b7b15c2c8 100644 --- a/packages/VpnDialogs/res/values-mr/strings.xml +++ b/packages/VpnDialogs/res/values-mr/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"कनेक्शन विनंती"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> नेटवर्क रहदारीचे परीक्षण करण्यासाठी त्यास अनुमती देणारे VPN कनेक्शन सेट करू इच्छितो. आपल्याला स्त्रोत विश्वसनीय वाटत असेल तरच स्वीकार करा. <br /> <br /> <img src=vpn_icon /> VPN सक्रिय असताना आपल्या स्क्रीनच्या शीर्षावर दिसते."</string> <string name="legacy_title" msgid="192936250066580964">"VPN कनेक्ट केले"</string> - <string name="configure" msgid="4905518375574791375">"कॉन्फिगर करा"</string> - <string name="disconnect" msgid="971412338304200056">"डिस्कनेक्ट करा"</string> <string name="session" msgid="6470628549473641030">"सत्र:"</string> <string name="duration" msgid="3584782459928719435">"कालावधी:"</string> <string name="data_transmitted" msgid="7988167672982199061">"प्रेषित:"</string> <string name="data_received" msgid="4062776929376067820">"प्राप्त झाले:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> बाइट / <xliff:g id="NUMBER_1">%2$s</xliff:g> पॅकेट"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"कायम चालू असलेल्या VPN शी कनेक्ट करू शकत नाही"</string> + <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="configure" msgid="4905518375574791375">"कॉन्फिगर करा"</string> + <string name="disconnect" msgid="971412338304200056">"डिस्कनेक्ट करा"</string> + <string name="open_app" msgid="3717639178595958667">"अॅप उघडा"</string> + <string name="dismiss" msgid="6192859333764711227">"डिसमिस करा"</string> </resources> diff --git a/packages/VpnDialogs/res/values-ms/strings.xml b/packages/VpnDialogs/res/values-ms/strings.xml index 8ea682f4408b..b489f2edabc0 100644 --- a/packages/VpnDialogs/res/values-ms/strings.xml +++ b/packages/VpnDialogs/res/values-ms/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Permintaan sambungan"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ingin menyediakan sambungan VPN yang membenarkan apl memantau trafik rangkaian. Terima hanya jika anda mempercayai sumber. <br /> <br /> <img src=vpn_icon /> terpapar pada bahagian atas skrin anda apabila VPN aktif."</string> <string name="legacy_title" msgid="192936250066580964">"VPN telah disambungkan"</string> - <string name="configure" msgid="4905518375574791375">"Konfigurasikan"</string> - <string name="disconnect" msgid="971412338304200056">"Putuskan sambungan"</string> <string name="session" msgid="6470628549473641030">"Sesi:"</string> <string name="duration" msgid="3584782459928719435">"Tempoh:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Dihantar:"</string> <string name="data_received" msgid="4062776929376067820">"Diterima:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bait / <xliff:g id="NUMBER_1">%2$s</xliff:g> bingkisan"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Tidak dapat menyambung ke VPN sentiasa hidup"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> disediakan untuk kekal bersambung pada sepanjang masa tetapi sambungan tidak dapat dibuat sekarang. Telefon anda akan menggunakan rangkaian awam sehingga dapat disambung semula ke <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> disediakan untuk kekal bersambung pada sepanjang masa tetapi sambungan tidak dapat dibuat sekarang. Sambungan tidak akan tersedia sehingga VPN dapat bersambung semula."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Tukar tetapan VPN"</string> + <string name="configure" msgid="4905518375574791375">"Konfigurasikan"</string> + <string name="disconnect" msgid="971412338304200056">"Putuskan sambungan"</string> + <string name="open_app" msgid="3717639178595958667">"Buka apl"</string> + <string name="dismiss" msgid="6192859333764711227">"Ketepikan"</string> </resources> diff --git a/packages/VpnDialogs/res/values-my/strings.xml b/packages/VpnDialogs/res/values-my/strings.xml index 6456c5efb452..9d60ff42a7cd 100644 --- a/packages/VpnDialogs/res/values-my/strings.xml +++ b/packages/VpnDialogs/res/values-my/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"ချိတ်ဆက်ရန် တောင်းဆိုချက်"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> က ကွန်ရက် လုပ်ငန်းကို စောင့်ကြည့်ခွင့် ပြုမည့် VPN ချိတ်ဆက်မှုကို ထူထောင်လိုသည်။ ရင်းမြစ်ကို သင်က ယုံကြည်မှသာ လက်ခံပါ။ <br /> <br /> <img src=vpn_icon /> မှာ VPN အလုပ်လုပ်နေလျှင် သင်၏ မျက်နှာပြင် ထိပ်မှာ ပေါ်လာမည်။"</string> <string name="legacy_title" msgid="192936250066580964">"VPNနှင့်ချိတ်ဆက်ထားသည်"</string> - <string name="configure" msgid="4905518375574791375">"ပုံပေါ်စေသည်"</string> - <string name="disconnect" msgid="971412338304200056">"ချိတ်ဆက်ခြင်းရပ်ရန်"</string> <string name="session" msgid="6470628549473641030">"သတ်မှတ်ပေးထားသည့်အချိန်:"</string> <string name="duration" msgid="3584782459928719435">"အချိန်ကာလ-"</string> <string name="data_transmitted" msgid="7988167672982199061">"ပို့သည်-"</string> <string name="data_received" msgid="4062776929376067820">"လက်ခံရရှိသည်"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bytes / <xliff:g id="NUMBER_1">%2$s</xliff:g> packets"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"အမြဲပွင့်နေသော VPN ကို ချိတ်ဆက်၍မရပါ"</string> + <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="configure" msgid="4905518375574791375">"ပုံပေါ်စေသည်"</string> + <string name="disconnect" msgid="971412338304200056">"ချိတ်ဆက်ခြင်းရပ်ရန်"</string> + <string name="open_app" msgid="3717639178595958667">"အက်ပ်ကို ဖွင့်ရန်"</string> + <string name="dismiss" msgid="6192859333764711227">"ပယ်ရန်"</string> </resources> diff --git a/packages/VpnDialogs/res/values-nb/strings.xml b/packages/VpnDialogs/res/values-nb/strings.xml index f99c2e7833a1..b45d3b90f9d5 100644 --- a/packages/VpnDialogs/res/values-nb/strings.xml +++ b/packages/VpnDialogs/res/values-nb/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Tilkoblingsforespørsel"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ønsker å bruke en VPN-tilkobling som tillater at appen overvåker nettverkstrafikken. Du bør bare godta dette hvis du stoler på kilden. <br /> <br /> <img src=vpn_icon /> vises øverst på skjermen din når VPN er aktivert."</string> <string name="legacy_title" msgid="192936250066580964">"VPN er tilkoblet"</string> - <string name="configure" msgid="4905518375574791375">"Konfigurer"</string> - <string name="disconnect" msgid="971412338304200056">"Koble fra"</string> <string name="session" msgid="6470628549473641030">"Økt:"</string> <string name="duration" msgid="3584782459928719435">"Varighet:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Sendt:"</string> <string name="data_received" msgid="4062776929376067820">"Mottatt:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> byte / <xliff:g id="NUMBER_1">%2$s</xliff:g> pakker"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Kan ikke koble til alltid på-VPN"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> er konfigurert til å være tilkoblet hele tiden, men kan ikke kobles til for øyeblikket. Telefonen din kommer til å bruke et offentlig nettverk til den kan koble til <xliff:g id="VPN_APP_1">%1$s</xliff:g> igjen."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> er konfigurert til å være tilkoblet hele tiden, men kan ikke kobles til for øyeblikket. Du har ingen tilkobling før VPN-et kan kobles til igjen."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Endre VPN-innstillingene"</string> + <string name="configure" msgid="4905518375574791375">"Konfigurer"</string> + <string name="disconnect" msgid="971412338304200056">"Koble fra"</string> + <string name="open_app" msgid="3717639178595958667">"Åpne appen"</string> + <string name="dismiss" msgid="6192859333764711227">"Avvis"</string> </resources> diff --git a/packages/VpnDialogs/res/values-ne/strings.xml b/packages/VpnDialogs/res/values-ne/strings.xml index d3cf435590c8..c19ae5254855 100644 --- a/packages/VpnDialogs/res/values-ne/strings.xml +++ b/packages/VpnDialogs/res/values-ne/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"जडान अनुरोध"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ले नेटवर्क यातायात अनुगमन गर्न अनुमति दिने VPN जडान स्थापना गर्न चाहन्छ। तपाईँले स्रोत भरोसा छ भने मात्र स्वीकार गर्नुहोस्। <br /> <br /> <img src=vpn_icon /> जब VPN सक्रिय हुन्छ आफ्नो स्क्रिनको माथि देखा पर्छन्।"</string> <string name="legacy_title" msgid="192936250066580964">"VPN जोडिएको छ"</string> - <string name="configure" msgid="4905518375574791375">"कन्फिगर गर्नुहोस्"</string> - <string name="disconnect" msgid="971412338304200056">"विच्छेदन गर्नुहोस्"</string> <string name="session" msgid="6470628549473641030">"सत्र:"</string> <string name="duration" msgid="3584782459928719435">"अवधि:"</string> <string name="data_transmitted" msgid="7988167672982199061">"पठाइयो:"</string> <string name="data_received" msgid="4062776929376067820">"प्राप्त भयो:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> बाइटहरू / <xliff:g id="NUMBER_1">%2$s</xliff:g> प्याकेटहरू"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"सधैँ-सक्रिय रहने VPN सेवामा जडान गर्न सकिँदैन"</string> + <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="configure" msgid="4905518375574791375">"कन्फिगर गर्नुहोस्"</string> + <string name="disconnect" msgid="971412338304200056">"विच्छेदन गर्नुहोस्"</string> + <string name="open_app" msgid="3717639178595958667">"अनुप्रयोग खोल्नुहोस्"</string> + <string name="dismiss" msgid="6192859333764711227">"खारेज गर्नुहोस्"</string> </resources> diff --git a/packages/VpnDialogs/res/values-nl/strings.xml b/packages/VpnDialogs/res/values-nl/strings.xml index ae789b2a05e4..8073b09e203c 100644 --- a/packages/VpnDialogs/res/values-nl/strings.xml +++ b/packages/VpnDialogs/res/values-nl/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Verbindingsverzoek"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wil een VPN-verbinding opzetten om netwerkverkeer te controleren. Accepteer het verzoek alleen als je de bron vertrouwt. <br /> <br /> <img src=vpn_icon /> wordt boven aan je scherm weergegeven wanneer VPN actief is."</string> <string name="legacy_title" msgid="192936250066580964">"Verbinding met VPN"</string> - <string name="configure" msgid="4905518375574791375">"Configureren"</string> - <string name="disconnect" msgid="971412338304200056">"Verbinding verbreken"</string> <string name="session" msgid="6470628549473641030">"Sessie:"</string> <string name="duration" msgid="3584782459928719435">"Duur:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Verzonden:"</string> <string name="data_received" msgid="4062776929376067820">"Ontvangen:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bytes/<xliff:g id="NUMBER_1">%2$s</xliff:g> pakketten"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Kan geen verbinding maken met Always-on VPN"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> is ingesteld om doorlopend verbinding te houden, maar kan nu geen verbinding maken. Je telefoon gebruikt een openbaar netwerk totdat deze opnieuw verbinding kan maken met <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> is ingesteld om doorlopend verbinding te houden, maar kan nu geen verbinding maken. Je hebt geen verbinding totdat het VPN opnieuw verbinding kan maken."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN-instellingen wijzigen"</string> + <string name="configure" msgid="4905518375574791375">"Configureren"</string> + <string name="disconnect" msgid="971412338304200056">"Verbinding verbreken"</string> + <string name="open_app" msgid="3717639178595958667">"App openen"</string> + <string name="dismiss" msgid="6192859333764711227">"Sluiten"</string> </resources> diff --git a/packages/VpnDialogs/res/values-pa/strings.xml b/packages/VpnDialogs/res/values-pa/strings.xml index 8e7c73deb2b5..c7159d256d5a 100644 --- a/packages/VpnDialogs/res/values-pa/strings.xml +++ b/packages/VpnDialogs/res/values-pa/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"ਕਨੈਕਸ਼ਨ ਬੇਨਤੀ"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ਇੱਕ VPN ਕਨੈਕਸ਼ਨ ਸੈਟ ਅਪ ਕਰਨਾ ਚਾਹੁੰਦਾ ਹੈ ਜੋ ਇਸਨੂੰ ਨੈੱਟਵਰਕ ਟ੍ਰੈਫਿਕ ਦਾ ਨਿਰੀਖਣ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਕੇਵਲ ਤਾਂ ਹੀ ਸਵੀਕਾਰ ਕਰੋ ਜੇਕਰ ਤੁਸੀਂ ਸਰੋਤ ਤੇ ਭਰੋਸਾ ਕਰਦੇ ਹੋ। <br /> <br /> <img src=vpn_icon /> ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ ਦੇ ਟੌਪ ਤੇ ਪ੍ਰਗਟ ਹੁੰਦਾ ਹੈ ਜਦੋਂ VPN ਸਕਿਰਿਆ ਹੁੰਦਾ ਹੈ।"</string> <string name="legacy_title" msgid="192936250066580964">"VPN ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ ਹੈ"</string> - <string name="configure" msgid="4905518375574791375">"ਕੌਂਫਿਗਰ ਕਰੋ"</string> - <string name="disconnect" msgid="971412338304200056">"ਡਿਸਕਨੈਕਟ ਕਰੋ"</string> <string name="session" msgid="6470628549473641030">"ਸੈਸ਼ਨ:"</string> <string name="duration" msgid="3584782459928719435">"ਮਿਆਦ:"</string> <string name="data_transmitted" msgid="7988167672982199061">"ਭੇਜਿਆ:"</string> <string name="data_received" msgid="4062776929376067820">"ਪ੍ਰਾਪਤ ਕੀਤਾ:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> ਬਾਈਟਸ / <xliff:g id="NUMBER_1">%2$s</xliff:g> ਪੈਕੇਟਸ"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"ਹਮੇਸ਼ਾ-ਚਾਲੂ VPN ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string> + <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="configure" msgid="4905518375574791375">"ਕੌਂਫਿਗਰ ਕਰੋ"</string> + <string name="disconnect" msgid="971412338304200056">"ਡਿਸਕਨੈਕਟ ਕਰੋ"</string> + <string name="open_app" msgid="3717639178595958667">"ਐਪ ਖੋਲ੍ਹੋ"</string> + <string name="dismiss" msgid="6192859333764711227">"ਖਾਰਜ ਕਰੋ"</string> </resources> diff --git a/packages/VpnDialogs/res/values-pl/strings.xml b/packages/VpnDialogs/res/values-pl/strings.xml index a8c08d51edcf..be6a4c262640 100644 --- a/packages/VpnDialogs/res/values-pl/strings.xml +++ b/packages/VpnDialogs/res/values-pl/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Żądanie połączenia"</string> <string name="warning" msgid="809658604548412033">"Aplikacja <xliff:g id="APP">%s</xliff:g> chce utworzyć połączenie VPN, które pozwoli jej na monitorowanie ruchu sieciowego. Zaakceptuj, tylko jeśli masz zaufanie do źródła. Gdy sieć VPN jest aktywna, u góry ekranu pojawia się <br /> <br /> <img src=vpn_icon />."</string> <string name="legacy_title" msgid="192936250066580964">"Połączono z VPN"</string> - <string name="configure" msgid="4905518375574791375">"Konfiguruj"</string> - <string name="disconnect" msgid="971412338304200056">"Rozłącz"</string> <string name="session" msgid="6470628549473641030">"Sesja:"</string> <string name="duration" msgid="3584782459928719435">"Czas trwania:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Wysłano:"</string> <string name="data_received" msgid="4062776929376067820">"Odebrano:"</string> <string name="data_value_format" msgid="2192466557826897580">"Bajty: <xliff:g id="NUMBER_0">%1$s</xliff:g> / pakiety: <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Nie można połączyć się ze stałą siecią VPN"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"Aplikacja <xliff:g id="VPN_APP_0">%1$s</xliff:g> jest skonfigurowana tak, by była cały czas połączona, ale teraz nie może się połączyć. Telefon będzie korzystał z sieci publicznej, aż zdoła się ponownie połączyć z aplikacją <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"Aplikacja <xliff:g id="VPN_APP">%1$s</xliff:g> jest skonfigurowana tak, by była cały czas połączona, ale teraz nie może się połączyć. Połączenie nie będzie dostępne, aż urządzenie zdoła ponownie połączyć się z siecią VPN."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Zmień ustawienia sieci VPN"</string> + <string name="configure" msgid="4905518375574791375">"Konfiguruj"</string> + <string name="disconnect" msgid="971412338304200056">"Rozłącz"</string> + <string name="open_app" msgid="3717639178595958667">"Otwórz aplikację"</string> + <string name="dismiss" msgid="6192859333764711227">"Zamknij"</string> </resources> diff --git a/packages/VpnDialogs/res/values-pt-rBR/strings.xml b/packages/VpnDialogs/res/values-pt-rBR/strings.xml index e4154bc802a4..9fdca9bd54bf 100644 --- a/packages/VpnDialogs/res/values-pt-rBR/strings.xml +++ b/packages/VpnDialogs/res/values-pt-rBR/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Solicitação de conexão"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> quer configurar uma conexão VPN que permite monitorar o tráfego da rede. Aceite se confiar na origem. <br /> <br /> <img src=vpn_icon /> é exibido na parte superior da tela quando a VPN estiver ativa."</string> <string name="legacy_title" msgid="192936250066580964">"O VPN está conectado"</string> - <string name="configure" msgid="4905518375574791375">"Configurar"</string> - <string name="disconnect" msgid="971412338304200056">"Desconectar"</string> <string name="session" msgid="6470628549473641030">"Sessão:"</string> <string name="duration" msgid="3584782459928719435">"Duração:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Enviado:"</string> <string name="data_received" msgid="4062776929376067820">"Recebido:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bytes/<xliff:g id="NUMBER_1">%2$s</xliff:g> pacotes"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Não é possível se conectar à VPN sempre ativa"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> está configurada para permanecer conectada o tempo todo, mas não é possível conectá-la no momento. Seu smartphone usará uma rede pública até que possa se reconectar a <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> está definida para permanecer conectada o tempo todo, mas não é possível conectá-la no momento. Você não terá uma conexão até que a VPN possa se reconectar."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Alterar configurações de VPN"</string> + <string name="configure" msgid="4905518375574791375">"Configurar"</string> + <string name="disconnect" msgid="971412338304200056">"Desconectar"</string> + <string name="open_app" msgid="3717639178595958667">"Abrir app"</string> + <string name="dismiss" msgid="6192859333764711227">"Dispensar"</string> </resources> diff --git a/packages/VpnDialogs/res/values-pt-rPT/strings.xml b/packages/VpnDialogs/res/values-pt-rPT/strings.xml index e3727c06440e..01beddbab4e4 100644 --- a/packages/VpnDialogs/res/values-pt-rPT/strings.xml +++ b/packages/VpnDialogs/res/values-pt-rPT/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Pedido de ligação"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> pretende configurar uma ligação VPN que lhe permita monitorizar o tráfego de rede. Aceite apenas se confiar na fonte. <br /> <br /> <img src=vpn_icon /> aparece na parte superior do seu ecrã quando a VPN está ativa."</string> <string name="legacy_title" msgid="192936250066580964">"A VPN está ligada"</string> - <string name="configure" msgid="4905518375574791375">"Configurar"</string> - <string name="disconnect" msgid="971412338304200056">"Desligar"</string> <string name="session" msgid="6470628549473641030">"Sessão"</string> <string name="duration" msgid="3584782459928719435">"Duração:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Enviados:"</string> <string name="data_received" msgid="4062776929376067820">"Recebidos:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bytes / <xliff:g id="NUMBER_1">%2$s</xliff:g> pacotes"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Não é possível estabelecer ligação à VPN sempre ativada"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"A aplicação <xliff:g id="VPN_APP_0">%1$s</xliff:g> está configurada para se manter sempre ligada, mas, neste momento, não é possível estabelecer ligação. O seu telemóvel irá utilizar uma rede pública até conseguir restabelecer ligação à aplicação <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"A aplicação <xliff:g id="VPN_APP">%1$s</xliff:g> está configurada para se manter sempre ligada, mas, neste momento, não é possível estabelecer ligação. Não terá ligação até que a VPN a consiga restabelecer."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Alterar as definições da VPN"</string> + <string name="configure" msgid="4905518375574791375">"Configurar"</string> + <string name="disconnect" msgid="971412338304200056">"Desligar"</string> + <string name="open_app" msgid="3717639178595958667">"Abrir aplicação"</string> + <string name="dismiss" msgid="6192859333764711227">"Ignorar"</string> </resources> diff --git a/packages/VpnDialogs/res/values-pt/strings.xml b/packages/VpnDialogs/res/values-pt/strings.xml index e4154bc802a4..9fdca9bd54bf 100644 --- a/packages/VpnDialogs/res/values-pt/strings.xml +++ b/packages/VpnDialogs/res/values-pt/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Solicitação de conexão"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> quer configurar uma conexão VPN que permite monitorar o tráfego da rede. Aceite se confiar na origem. <br /> <br /> <img src=vpn_icon /> é exibido na parte superior da tela quando a VPN estiver ativa."</string> <string name="legacy_title" msgid="192936250066580964">"O VPN está conectado"</string> - <string name="configure" msgid="4905518375574791375">"Configurar"</string> - <string name="disconnect" msgid="971412338304200056">"Desconectar"</string> <string name="session" msgid="6470628549473641030">"Sessão:"</string> <string name="duration" msgid="3584782459928719435">"Duração:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Enviado:"</string> <string name="data_received" msgid="4062776929376067820">"Recebido:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bytes/<xliff:g id="NUMBER_1">%2$s</xliff:g> pacotes"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Não é possível se conectar à VPN sempre ativa"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> está configurada para permanecer conectada o tempo todo, mas não é possível conectá-la no momento. Seu smartphone usará uma rede pública até que possa se reconectar a <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> está definida para permanecer conectada o tempo todo, mas não é possível conectá-la no momento. Você não terá uma conexão até que a VPN possa se reconectar."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Alterar configurações de VPN"</string> + <string name="configure" msgid="4905518375574791375">"Configurar"</string> + <string name="disconnect" msgid="971412338304200056">"Desconectar"</string> + <string name="open_app" msgid="3717639178595958667">"Abrir app"</string> + <string name="dismiss" msgid="6192859333764711227">"Dispensar"</string> </resources> diff --git a/packages/VpnDialogs/res/values-ro/strings.xml b/packages/VpnDialogs/res/values-ro/strings.xml index e2e1e44021b0..4e60df2eca8e 100644 --- a/packages/VpnDialogs/res/values-ro/strings.xml +++ b/packages/VpnDialogs/res/values-ro/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Solicitare de conexiune"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> dorește să configureze o conexiune VPN care să îi permită să monitorizeze traficul în rețea. Acceptați numai dacă aveți încredere în sursă. Atunci când conexiunea VPN este activă, <br /> <br /> <img src=vpn_icon /> se afișează în partea de sus a ecranului."</string> <string name="legacy_title" msgid="192936250066580964">"VPN este conectat"</string> - <string name="configure" msgid="4905518375574791375">"Configurați"</string> - <string name="disconnect" msgid="971412338304200056">"Deconectați"</string> <string name="session" msgid="6470628549473641030">"Sesiune:"</string> <string name="duration" msgid="3584782459928719435">"Durată:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Trimise:"</string> <string name="data_received" msgid="4062776929376067820">"Primite:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> octeți/<xliff:g id="NUMBER_1">%2$s</xliff:g> pachete"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Nu se poate conecta la rețeaua VPN activată permanent"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> este setată să rămână conectată permanent, dar momentan nu se poate conecta. Telefonul dvs. va folosi o rețea publică până când se va putea reconecta la <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> este setată să rămână conectată permanent, dar momentan nu se poate conecta. Nu veți avea conexiune până când se va putea reconecta rețeaua VPN."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Modificați setările VPN"</string> + <string name="configure" msgid="4905518375574791375">"Configurați"</string> + <string name="disconnect" msgid="971412338304200056">"Deconectați"</string> + <string name="open_app" msgid="3717639178595958667">"Deschideți aplicația"</string> + <string name="dismiss" msgid="6192859333764711227">"Închideți"</string> </resources> diff --git a/packages/VpnDialogs/res/values-ru/strings.xml b/packages/VpnDialogs/res/values-ru/strings.xml index 0e89d8e55d24..b9207a07e10c 100644 --- a/packages/VpnDialogs/res/values-ru/strings.xml +++ b/packages/VpnDialogs/res/values-ru/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Запрос на подключение"</string> <string name="warning" msgid="809658604548412033">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" пытается подключиться к сети VPN, чтобы отслеживать трафик. Этот запрос следует принимать, только если вы доверяете источнику.<br/><br/>Когда подключение VPN активно, в верхней части экрана появляется значок <img src=vpn_icon />."</string> <string name="legacy_title" msgid="192936250066580964">"VPN-подключение установлено"</string> - <string name="configure" msgid="4905518375574791375">"Настроить"</string> - <string name="disconnect" msgid="971412338304200056">"Разъединить"</string> <string name="session" msgid="6470628549473641030">"Сеанс:"</string> <string name="duration" msgid="3584782459928719435">"Продолжительность:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Отправлено:"</string> <string name="data_received" msgid="4062776929376067820">"Получено:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> Б; пакетов: <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Нет подключения к постоянной VPN"</string> + <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>\" настроено постоянное подключение, но сейчас установить его не удается. Соединение будет отсутствовать до тех пор, пока сеть не станет доступна снова."</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="configure" msgid="4905518375574791375">"Настроить"</string> + <string name="disconnect" msgid="971412338304200056">"Разъединить"</string> + <string name="open_app" msgid="3717639178595958667">"Открыть приложение"</string> + <string name="dismiss" msgid="6192859333764711227">"Закрыть"</string> </resources> diff --git a/packages/VpnDialogs/res/values-si/strings.xml b/packages/VpnDialogs/res/values-si/strings.xml index 5f54821fdceb..bb97a5d86c5f 100644 --- a/packages/VpnDialogs/res/values-si/strings.xml +++ b/packages/VpnDialogs/res/values-si/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"සම්බන්ධතා ඉල්ලීම"</string> <string name="warning" msgid="809658604548412033">"ජාල තදබදය නිරීක්ෂණය කිරීමට ඉඩ දෙන VPN සම්බන්ධතාවක් සැකසීමට <xliff:g id="APP">%s</xliff:g> අවශ්යය වේ. ප්රභවය ඔබ විශ්වාස කරන්නේ නම් පමණක් පිළිගන්න. VPN සක්රිය විට <br /> <br /> <img src=vpn_icon />."</string> <string name="legacy_title" msgid="192936250066580964">"VPN සම්බන්ධිතයි"</string> - <string name="configure" msgid="4905518375574791375">"වින්යාස කිරීම"</string> - <string name="disconnect" msgid="971412338304200056">"විසන්ධි කරන්න"</string> <string name="session" msgid="6470628549473641030">"සැසිය:"</string> <string name="duration" msgid="3584782459928719435">"කාල සීමාව:"</string> <string name="data_transmitted" msgid="7988167672982199061">"යවන ලද:"</string> <string name="data_received" msgid="4062776929376067820">"ලැබිණි:"</string> <string name="data_value_format" msgid="2192466557826897580">"බයිට <xliff:g id="NUMBER_0">%1$s</xliff:g> / පැකැට්ටු <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"සැම විට ක්රියාත්මක VPN වෙත සම්බන්ධ විය නොහැක"</string> + <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="configure" msgid="4905518375574791375">"වින්යාස කිරීම"</string> + <string name="disconnect" msgid="971412338304200056">"විසන්ධි කරන්න"</string> + <string name="open_app" msgid="3717639178595958667">"යෙදුම විවෘත කරන්න"</string> + <string name="dismiss" msgid="6192859333764711227">"ඉවතලන්න"</string> </resources> diff --git a/packages/VpnDialogs/res/values-sk/strings.xml b/packages/VpnDialogs/res/values-sk/strings.xml index b7ce96642719..00029641e57b 100644 --- a/packages/VpnDialogs/res/values-sk/strings.xml +++ b/packages/VpnDialogs/res/values-sk/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Žiadosť o pripojenie"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> žiada o nastavenie pripojenia VPN, pomocou ktorého bude môcť sledovať sieťové prenosy. Povoľte iba v prípade, že zdroju dôverujete. <br /> <br /> <img src=vpn_icon /> sa zobrazuje v hornej časti obrazovky, keď je pripojenie VPN aktívne."</string> <string name="legacy_title" msgid="192936250066580964">"Sieť VPN je pripojená"</string> - <string name="configure" msgid="4905518375574791375">"Konfigurovať"</string> - <string name="disconnect" msgid="971412338304200056">"Odpojiť"</string> <string name="session" msgid="6470628549473641030">"Relácia"</string> <string name="duration" msgid="3584782459928719435">"Trvanie:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Odoslané:"</string> <string name="data_received" msgid="4062776929376067820">"Prijaté:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> B/<xliff:g id="NUMBER_1">%2$s</xliff:g> paketov"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Nedá sa pripojiť k vždy zapnutej sieti VPN"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"Sieť <xliff:g id="VPN_APP_0">%1$s</xliff:g> je nastavená, aby bola neustále pripojená, ale momentálne sa nedokáže pripojiť. Než sa telefón bude môcť znova pripojiť k sieti <xliff:g id="VPN_APP_1">%1$s</xliff:g>, bude používať verejnú sieť."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"Sieť <xliff:g id="VPN_APP">%1$s</xliff:g> je nastavená, aby bola neustále pripojená, ale momentálne sa nedokáže pripojiť. Než sa sieť VPN znova pripojí, nebudete mať pripojenie."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Zmeniť nastavenia VPN"</string> + <string name="configure" msgid="4905518375574791375">"Konfigurovať"</string> + <string name="disconnect" msgid="971412338304200056">"Odpojiť"</string> + <string name="open_app" msgid="3717639178595958667">"Otvoriť aplikáciu"</string> + <string name="dismiss" msgid="6192859333764711227">"Zrušiť"</string> </resources> diff --git a/packages/VpnDialogs/res/values-sl/strings.xml b/packages/VpnDialogs/res/values-sl/strings.xml index 9955c8960338..d5014fa34394 100644 --- a/packages/VpnDialogs/res/values-sl/strings.xml +++ b/packages/VpnDialogs/res/values-sl/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Zahteva za povezavo"</string> <string name="warning" msgid="809658604548412033">"Aplikacija <xliff:g id="APP">%s</xliff:g> želi nastaviti povezavo VPN, ki omogoča nadzor omrežnega prometa. To sprejmite samo, če zaupate viru. Ko je povezava VPN aktivna, se na vrhu zaslona prikaže ikona <br /> <br /> <img src=vpn_icon />."</string> <string name="legacy_title" msgid="192936250066580964">"Povezava z navideznim zasebnim omrežjem je vzpostavljena"</string> - <string name="configure" msgid="4905518375574791375">"Konfiguriranje"</string> - <string name="disconnect" msgid="971412338304200056">"Prekini povezavo"</string> <string name="session" msgid="6470628549473641030">"Seja:"</string> <string name="duration" msgid="3584782459928719435">"Trajanje:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Poslano:"</string> <string name="data_received" msgid="4062776929376067820">"Prejeto:"</string> <string name="data_value_format" msgid="2192466557826897580">"Št. bajtov: <xliff:g id="NUMBER_0">%1$s</xliff:g>/št. paketov: <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Povezave s stalno vklopljenim VPN-jem ni mogoče vzpostaviti"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"Omrežje <xliff:g id="VPN_APP_0">%1$s</xliff:g> je nastavljeno na stalno povezanost, vendar povezave trenutno ni mogoče vzpostaviti. Telefon bo uporabljal javno omrežje, dokler znova ne vzpostavi povezave z omrežjem <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"Omrežje <xliff:g id="VPN_APP">%1$s</xliff:g> je nastavljeno na stalno povezanost, vendar povezave trenutno ni mogoče vzpostaviti. Brez povezave boste, dokler se znova ne vzpostavi povezava z omrežjem VPN."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Spremenite nastavitve omrežja VPN"</string> + <string name="configure" msgid="4905518375574791375">"Konfiguriranje"</string> + <string name="disconnect" msgid="971412338304200056">"Prekini povezavo"</string> + <string name="open_app" msgid="3717639178595958667">"Odpri aplikacijo"</string> + <string name="dismiss" msgid="6192859333764711227">"Opusti"</string> </resources> diff --git a/packages/VpnDialogs/res/values-sq/strings.xml b/packages/VpnDialogs/res/values-sq/strings.xml index 8dc8bfb7087a..4a96e7b92212 100644 --- a/packages/VpnDialogs/res/values-sq/strings.xml +++ b/packages/VpnDialogs/res/values-sq/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Kërkesë për lidhje"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> kërkon të vendosë një lidhje VPN-je që e lejon të monitorojë trafikun e rrjetit. Prano vetëm nëse i beson burimit. <br /> <br /> <img src=vpn_icon /> shfaqet në krye të ekranit kur VPN-ja është aktive."</string> <string name="legacy_title" msgid="192936250066580964">"VPN-ja është e lidhur"</string> - <string name="configure" msgid="4905518375574791375">"Konfiguro"</string> - <string name="disconnect" msgid="971412338304200056">"Shkëputu"</string> <string name="session" msgid="6470628549473641030">"Sesioni:"</string> <string name="duration" msgid="3584782459928719435">"Kohëzgjatja:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Dërguar:"</string> <string name="data_received" msgid="4062776929376067820">"Marrë:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bajte / <xliff:g id="NUMBER_1">%2$s</xliff:g> paketa"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Nuk mund të lidhet me VPN-në gjithmonë të aktivizuar"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> është konfiguruar për të qëndruar i lidhur gjatë të gjithë kohës, por nuk mund të lidhet në këtë moment. Telefoni yt do të përdorë një rrjet publik derisa të arrijë të rilidhet me <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> është konfiguruar për të qëndruar i lidhur gjatë të gjithë kohës, por nuk mund të lidhet në këtë moment. Nuk do të kesh një lidhje derisa VPN të arrijë të rilidhet."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Ndrysho cilësimet e VPN-së"</string> + <string name="configure" msgid="4905518375574791375">"Konfiguro"</string> + <string name="disconnect" msgid="971412338304200056">"Shkëputu"</string> + <string name="open_app" msgid="3717639178595958667">"Hap aplikacionin"</string> + <string name="dismiss" msgid="6192859333764711227">"Largoje"</string> </resources> diff --git a/packages/VpnDialogs/res/values-sr/strings.xml b/packages/VpnDialogs/res/values-sr/strings.xml index 97d9d9a6ca5c..8ce8060e333d 100644 --- a/packages/VpnDialogs/res/values-sr/strings.xml +++ b/packages/VpnDialogs/res/values-sr/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Захтев за повезивање"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> жели да подеси VPN везу која омогућава праћење саобраћаја на мрежи. Прихватите само ако верујете извору. <br /> <br /> <img src=vpn_icon /> се приказује у врху екрана када је VPN активан."</string> <string name="legacy_title" msgid="192936250066580964">"VPN је повезан"</string> - <string name="configure" msgid="4905518375574791375">"Конфигуриши"</string> - <string name="disconnect" msgid="971412338304200056">"Прекини везу"</string> <string name="session" msgid="6470628549473641030">"Сесија:"</string> <string name="duration" msgid="3584782459928719435">"Трајање:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Послато:"</string> <string name="data_received" msgid="4062776929376067820">"Примљенo:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> бајт(ов)а / <xliff:g id="NUMBER_1">%2$s</xliff:g> пакета"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Повезивање са увек укљученим VPN-ом није успело"</string> + <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="configure" msgid="4905518375574791375">"Конфигуриши"</string> + <string name="disconnect" msgid="971412338304200056">"Прекини везу"</string> + <string name="open_app" msgid="3717639178595958667">"Отвори апликацију"</string> + <string name="dismiss" msgid="6192859333764711227">"Одбаци"</string> </resources> diff --git a/packages/VpnDialogs/res/values-sv/strings.xml b/packages/VpnDialogs/res/values-sv/strings.xml index 7204ff047906..16b6a31d7d1a 100644 --- a/packages/VpnDialogs/res/values-sv/strings.xml +++ b/packages/VpnDialogs/res/values-sv/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Anslutningsförfrågan"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> vill starta en VPN-anslutning som tillåter att appen övervakar nätverkstrafiken. Godkänn endast detta om du litar på källan. <br /> <br /> <img src=vpn_icon /> visas längst upp på skärmen när VPN-anslutningen är aktiv."</string> <string name="legacy_title" msgid="192936250066580964">"VPN är anslutet"</string> - <string name="configure" msgid="4905518375574791375">"Konfigurera"</string> - <string name="disconnect" msgid="971412338304200056">"Koppla från"</string> <string name="session" msgid="6470628549473641030">"Session:"</string> <string name="duration" msgid="3584782459928719435">"Längd:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Skickat:"</string> <string name="data_received" msgid="4062776929376067820">"Mottaget:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> byte/<xliff:g id="NUMBER_1">%2$s</xliff:g> paket"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Det gick inte att ansluta till Always-on VPN"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> är konfigurerad att vara ansluten hela tiden, men det går inte att ansluta just nu. Mobilen använder ett offentligt nätverk tills den kan ansluta till <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> är konfigurerad att vara ansluten hela tiden, men det går inte att ansluta just nu. Du har ingen anslutning tills VPN-nätverket kan ansluta igen."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Ändra inställningarna för VPN"</string> + <string name="configure" msgid="4905518375574791375">"Konfigurera"</string> + <string name="disconnect" msgid="971412338304200056">"Koppla från"</string> + <string name="open_app" msgid="3717639178595958667">"Öppna appen"</string> + <string name="dismiss" msgid="6192859333764711227">"Ignorera"</string> </resources> diff --git a/packages/VpnDialogs/res/values-sw/strings.xml b/packages/VpnDialogs/res/values-sw/strings.xml index e48210cba3be..ea2688438b7a 100644 --- a/packages/VpnDialogs/res/values-sw/strings.xml +++ b/packages/VpnDialogs/res/values-sw/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Ombi la muunganisho"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> inataka kusanidi muunganisho wa VPN utakaoiruhusu kufuatilia shughuli kwenye mtandao. Kubali ikiwa tu unakiamini chanzo. <br /> <br /> <img src=vpn_icon /> huonekana sehemu ya juu ya skrini yako VPN inapofanya kazi."</string> <string name="legacy_title" msgid="192936250066580964">"VPN imeunganishwa"</string> - <string name="configure" msgid="4905518375574791375">"Sanidi"</string> - <string name="disconnect" msgid="971412338304200056">"Tenganisha"</string> <string name="session" msgid="6470628549473641030">"Kipindi:"</string> <string name="duration" msgid="3584782459928719435">"Muda:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Zilizotumwa:"</string> <string name="data_received" msgid="4062776929376067820">"Imepokelewa:"</string> <string name="data_value_format" msgid="2192466557826897580">"baiti <xliff:g id="NUMBER_0">%1$s</xliff:g> / pakiti <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Imeshindwa kuunganisha kwenye VPN iliyowashwa kila wakati"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"Mipangilio ya <xliff:g id="VPN_APP_0">%1$s</xliff:g> imewekwa ili ibaki kuwa imeunganishwa kila wakati, lakini haiwezi kuunganisha sasa hivi. Simu yako itatumia mtandao wa umma hadi itakapounganishwa tena kwenye <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"Mipangilio ya <xliff:g id="VPN_APP">%1$s</xliff:g> imewekwa ili ibaki kuwa imeunganishwa kila wakati, lakini haiwezi kuunganisha sasa hivi. Hutapata muunganisho hadi VPN iunganishwe tena."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Badilisha mipangilio ya VPN"</string> + <string name="configure" msgid="4905518375574791375">"Sanidi"</string> + <string name="disconnect" msgid="971412338304200056">"Tenganisha"</string> + <string name="open_app" msgid="3717639178595958667">"Fungua programu"</string> + <string name="dismiss" msgid="6192859333764711227">"Ondoa"</string> </resources> diff --git a/packages/VpnDialogs/res/values-ta/strings.xml b/packages/VpnDialogs/res/values-ta/strings.xml index f03d3e4145d3..81a198440c44 100644 --- a/packages/VpnDialogs/res/values-ta/strings.xml +++ b/packages/VpnDialogs/res/values-ta/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"இணைப்புக் கோரிக்கை"</string> <string name="warning" msgid="809658604548412033">"VPN இணைப்பை அமைக்க <xliff:g id="APP">%s</xliff:g> விழைகிறது அதன்மூலம் இது நெட்வொர்க் ட்ராஃபிக்கைக் கண்காணிக்கும் அனுமதியைப் பெறும். நம்பகமான மூலத்தை மட்டுமே ஏற்கவும். VPN இயக்கத்தில் உள்ளபோது திரையில் மேல் பகுதியில் <br /> <br /> <img src=vpn_icon /> தோன்றும்."</string> <string name="legacy_title" msgid="192936250066580964">"VPN இணைக்கப்பட்டது"</string> - <string name="configure" msgid="4905518375574791375">"உள்ளமை"</string> - <string name="disconnect" msgid="971412338304200056">"தொடர்பைத் துண்டி"</string> <string name="session" msgid="6470628549473641030">"அமர்வு:"</string> <string name="duration" msgid="3584782459928719435">"காலஅளவு:"</string> <string name="data_transmitted" msgid="7988167672982199061">"அனுப்பியது:"</string> <string name="data_received" msgid="4062776929376067820">"பெறப்பட்டது:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> பைட்கள் / <xliff:g id="NUMBER_1">%2$s</xliff:g> தொகுப்பு"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"எப்போதும் இயக்கத்தில் இருக்கும்படி அமைத்த VPN உடன் இணைக்க முடியவில்லை"</string> + <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="configure" msgid="4905518375574791375">"உள்ளமை"</string> + <string name="disconnect" msgid="971412338304200056">"தொடர்பைத் துண்டி"</string> + <string name="open_app" msgid="3717639178595958667">"பயன்பாட்டைத் திற"</string> + <string name="dismiss" msgid="6192859333764711227">"நிராகரி"</string> </resources> diff --git a/packages/VpnDialogs/res/values-te/strings.xml b/packages/VpnDialogs/res/values-te/strings.xml index 609b74d74bb9..864c926bc615 100644 --- a/packages/VpnDialogs/res/values-te/strings.xml +++ b/packages/VpnDialogs/res/values-te/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"కనెక్షన్ అభ్యర్థన"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> నెట్వర్క్ ట్రాఫిక్ని పర్యవేక్షించగలగడానికి VPN కనెక్షన్ను సెటప్ చేయాలనుకుంటోంది. మీరు మూలాన్ని విశ్వసిస్తే మాత్రమే ఆమోదించండి. VPN సక్రియంగా ఉన్నప్పుడు మీ స్క్రీన్ ఎగువన <br /> <br /> <img src=vpn_icon /> కనిపిస్తుంది."</string> <string name="legacy_title" msgid="192936250066580964">"VPN కనెక్ట్ చేయబడింది"</string> - <string name="configure" msgid="4905518375574791375">"కాన్ఫిగర్ చేయి"</string> - <string name="disconnect" msgid="971412338304200056">"డిస్కనెక్ట్ చేయి"</string> <string name="session" msgid="6470628549473641030">"సెషన్:"</string> <string name="duration" msgid="3584782459928719435">"వ్యవధి:"</string> <string name="data_transmitted" msgid="7988167672982199061">"పంపినది:"</string> <string name="data_received" msgid="4062776929376067820">"స్వీకరించినది:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> బైట్లు / <xliff:g id="NUMBER_1">%2$s</xliff:g> ప్యాకెట్లు"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"ఎల్లప్పుడూ ఆన్లో ఉండే VPNకి కనెక్ట్ చేయడం సాధ్యపడదు"</string> + <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="configure" msgid="4905518375574791375">"కాన్ఫిగర్ చేయి"</string> + <string name="disconnect" msgid="971412338304200056">"డిస్కనెక్ట్ చేయి"</string> + <string name="open_app" msgid="3717639178595958667">"యాప్ని తెరవండి"</string> + <string name="dismiss" msgid="6192859333764711227">"తీసివేయండి"</string> </resources> diff --git a/packages/VpnDialogs/res/values-th/strings.xml b/packages/VpnDialogs/res/values-th/strings.xml index 1b5f0a8619e2..f6dfca5a8434 100644 --- a/packages/VpnDialogs/res/values-th/strings.xml +++ b/packages/VpnDialogs/res/values-th/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"ขอการเชื่อมต่อ"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ต้องการติดตั้งการเชื่อมต่อ VPN เพื่อให้แอปสามารถตรวจสอบการเข้าใช้งานเครือข่าย โปรดยอมรับหากคุณเชื่อถือแหล่งที่มานี้เท่านั้น <br /> <br /> <img src=vpn_icon /> จะปรากฏที่ด้านบนหน้าจอเมื่อมีการใช้งาน VPN อยู่"</string> <string name="legacy_title" msgid="192936250066580964">"เชื่อมต่อ VPN แล้ว"</string> - <string name="configure" msgid="4905518375574791375">"กำหนดค่า"</string> - <string name="disconnect" msgid="971412338304200056">"ยกเลิกการเชื่อมต่อ"</string> <string name="session" msgid="6470628549473641030">"เซสชัน"</string> <string name="duration" msgid="3584782459928719435">"ระยะเวลา:"</string> <string name="data_transmitted" msgid="7988167672982199061">"ส่งแล้ว:"</string> <string name="data_received" msgid="4062776929376067820">"รับแล้ว:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> ไบต์/<xliff:g id="NUMBER_1">%2$s</xliff:g> แพ็คเก็ต"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"ไม่สามารถเชื่อมต่อ VPN แบบเปิดตลอดเวลา"</string> + <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="configure" msgid="4905518375574791375">"กำหนดค่า"</string> + <string name="disconnect" msgid="971412338304200056">"ยกเลิกการเชื่อมต่อ"</string> + <string name="open_app" msgid="3717639178595958667">"เปิดแอป"</string> + <string name="dismiss" msgid="6192859333764711227">"ปิด"</string> </resources> diff --git a/packages/VpnDialogs/res/values-tl/strings.xml b/packages/VpnDialogs/res/values-tl/strings.xml index a115ae547052..9c01c32d0d0d 100644 --- a/packages/VpnDialogs/res/values-tl/strings.xml +++ b/packages/VpnDialogs/res/values-tl/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Kahilingan sa koneksyon"</string> <string name="warning" msgid="809658604548412033">"Gusto ng <xliff:g id="APP">%s</xliff:g> na mag-set up ng koneksyon sa VPN na nagbibigay-daan ditong masubaybayan ang trapiko ng network. Tanggapin lang kung pinagkakatiwalaan mo ang pinagmulan. Lalabas ang <br /> <br /> <img src=vpn_icon /> sa itaas ng iyong screen kapag aktibo ang VPN."</string> <string name="legacy_title" msgid="192936250066580964">"Nakakonekta ang VPN"</string> - <string name="configure" msgid="4905518375574791375">"I-configure"</string> - <string name="disconnect" msgid="971412338304200056">"Idiskonekta"</string> <string name="session" msgid="6470628549473641030">"Session:"</string> <string name="duration" msgid="3584782459928719435">"Tagal:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Ipinadala:"</string> <string name="data_received" msgid="4062776929376067820">"Natanggap:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> (na) byte / <xliff:g id="NUMBER_1">%2$s</xliff:g> (na) packet"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Hindi makakonekta sa VPN na palaging naka-on"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"Naka-set up ang <xliff:g id="VPN_APP_0">%1$s</xliff:g> na manatiling nakakonekta sa lahat ng oras, ngunit hindi ito makakonekta sa ngayon. Gagamit ng pampublikong network ang iyong telepono hanggang sa muli itong makakonekta sa <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"Naka-set up ang <xliff:g id="VPN_APP">%1$s</xliff:g> na manatiling nakakonekta sa lahat ng oras, ngunit hindi ito makakonekta sa ngayon. Hindi ka magkakaroon ng koneksyon hanggang sa muling makakonekta ang VPN."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Baguhin ang mga setting ng VPN"</string> + <string name="configure" msgid="4905518375574791375">"I-configure"</string> + <string name="disconnect" msgid="971412338304200056">"Idiskonekta"</string> + <string name="open_app" msgid="3717639178595958667">"Buksan ang app"</string> + <string name="dismiss" msgid="6192859333764711227">"I-dismiss"</string> </resources> diff --git a/packages/VpnDialogs/res/values-tr/strings.xml b/packages/VpnDialogs/res/values-tr/strings.xml index abebeca3fbaf..8665a47e6633 100644 --- a/packages/VpnDialogs/res/values-tr/strings.xml +++ b/packages/VpnDialogs/res/values-tr/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Bağlantı isteği"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ağ trafiğini izlemesine olanak veren bir VPN bağlantısı oluşturmak istiyor. Sadece, ilgili kaynağa güveniyorsanız kabul edin. <br /> <br /> VPN aktif olduğunda ekranınızın üst tarafında <img src=vpn_icon /> simgesi görünür."</string> <string name="legacy_title" msgid="192936250066580964">"VPN bağlı"</string> - <string name="configure" msgid="4905518375574791375">"Yapılandır"</string> - <string name="disconnect" msgid="971412338304200056">"Bağlantıyı kes"</string> <string name="session" msgid="6470628549473641030">"Oturum:"</string> <string name="duration" msgid="3584782459928719435">"Süre:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Gönderilen:"</string> <string name="data_received" msgid="4062776929376067820">"Alınan:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bayt / <xliff:g id="NUMBER_1">%2$s</xliff:g> paket"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Her zaman açık VPN\'ye bağlanılamıyor"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> sürekli bağlantıda kalacak şekilde ayarlandı, ancak şu anda bağlanamıyor. <xliff:g id="VPN_APP_1">%1$s</xliff:g> uygulamasına bağlanana kadar telefonunuz genel bir ağı kullanacak."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> sürekli bağlantıda kalacak şekilde ayarlandı, ancak şu anda bağlanamıyor. VPN bağlanana kadar bağlantınız olmayacak."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN ayarlarını değiştir"</string> + <string name="configure" msgid="4905518375574791375">"Yapılandır"</string> + <string name="disconnect" msgid="971412338304200056">"Bağlantıyı kes"</string> + <string name="open_app" msgid="3717639178595958667">"Uygulamayı aç"</string> + <string name="dismiss" msgid="6192859333764711227">"Kapat"</string> </resources> diff --git a/packages/VpnDialogs/res/values-uk/strings.xml b/packages/VpnDialogs/res/values-uk/strings.xml index eed37eed7830..8f91abf990b3 100644 --- a/packages/VpnDialogs/res/values-uk/strings.xml +++ b/packages/VpnDialogs/res/values-uk/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Запит на під’єднання"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> хоче під’єднатися до мережі VPN, щоб контролювати мережевий трафік. Дозволяйте, якщо довіряєте джерелу. Коли мережа VPN активна, угорі екрана відображається значок <br /> <br /> <img src=vpn_icon />."</string> <string name="legacy_title" msgid="192936250066580964">"Мережу VPN під’єднано"</string> - <string name="configure" msgid="4905518375574791375">"Налаштувати"</string> - <string name="disconnect" msgid="971412338304200056">"Від’єднати"</string> <string name="session" msgid="6470628549473641030">"Сеанс:"</string> <string name="duration" msgid="3584782459928719435">"Тривалість:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Надіслано:"</string> <string name="data_received" msgid="4062776929376067820">"Отримано:"</string> <string name="data_value_format" msgid="2192466557826897580">"Байтів: <xliff:g id="NUMBER_0">%1$s</xliff:g> / пакетів: <xliff:g id="NUMBER_1">%2$s</xliff:g>"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Не вдається під’єднатися до постійної мережі VPN"</string> + <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="configure" msgid="4905518375574791375">"Налаштувати"</string> + <string name="disconnect" msgid="971412338304200056">"Від’єднати"</string> + <string name="open_app" msgid="3717639178595958667">"Відкрити додаток"</string> + <string name="dismiss" msgid="6192859333764711227">"Закрити"</string> </resources> diff --git a/packages/VpnDialogs/res/values-ur/strings.xml b/packages/VpnDialogs/res/values-ur/strings.xml index 34f72c80150f..db0c2971a64c 100644 --- a/packages/VpnDialogs/res/values-ur/strings.xml +++ b/packages/VpnDialogs/res/values-ur/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"کنکشن کی درخواست"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ایک ایسا VPN کنکشن ترتیب دینا چاہتی ہے جو اسے نیٹ ورک ٹریفک کو مانیٹر کرنے کی اجازت دیتا ہے۔ اگر آپ کو ماخذ پر بھروسہ ہے تبھی قبول کریں۔ <br /> <br /> <img src=vpn_icon /> آپ کی اسکرین کے اوپر اس وقت ظاہر ہوتا ہے جب VPN فعال ہوتا ہے۔"</string> <string name="legacy_title" msgid="192936250066580964">"VPN مربوط ہے"</string> - <string name="configure" msgid="4905518375574791375">"ترتیب دیں"</string> - <string name="disconnect" msgid="971412338304200056">"منقطع کریں"</string> <string name="session" msgid="6470628549473641030">"سیشن:"</string> <string name="duration" msgid="3584782459928719435">"دورانیہ:"</string> <string name="data_transmitted" msgid="7988167672982199061">"ارسال کردہ:"</string> <string name="data_received" msgid="4062776929376067820">"موصولہ:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> بائٹس / <xliff:g id="NUMBER_1">%2$s</xliff:g> پیکٹس"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"ہمیشہ آن VPN سے منسلک نہیں کر سکتے"</string> + <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="configure" msgid="4905518375574791375">"ترتیب دیں"</string> + <string name="disconnect" msgid="971412338304200056">"منقطع کریں"</string> + <string name="open_app" msgid="3717639178595958667">"ایپ کھولیں"</string> + <string name="dismiss" msgid="6192859333764711227">"برخاست کریں"</string> </resources> diff --git a/packages/VpnDialogs/res/values-uz/strings.xml b/packages/VpnDialogs/res/values-uz/strings.xml index 69e3e2962bca..5a348a0610d3 100644 --- a/packages/VpnDialogs/res/values-uz/strings.xml +++ b/packages/VpnDialogs/res/values-uz/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Ulanish uchun so‘rov"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ilovasi trafikni kuzatish uchun VPN tarmog‘iga ulanmoqchi. Agar ilovaga ishonsangiz, so‘rovga rozi bo‘ling.<br /> <br />VPN faol bo‘lsa, ekranning yuqori qismida <img src=vpn_icon /> belgisi paydo bo‘ladi."</string> <string name="legacy_title" msgid="192936250066580964">"VPN ulangan"</string> - <string name="configure" msgid="4905518375574791375">"Moslash"</string> - <string name="disconnect" msgid="971412338304200056">"Aloqani uzish"</string> <string name="session" msgid="6470628549473641030">"Seans:"</string> <string name="duration" msgid="3584782459928719435">"Davomiyligi:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Jo‘natildi:"</string> <string name="data_received" msgid="4062776929376067820">"Qabul qilingan:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bayt / <xliff:g id="NUMBER_1">%2$s</xliff:g> ta paket"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Doimiy VPN tarmoqqa ulanilmadi"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> ilovasi doim ulanib turiladigan qilib sozlangan, lekin hozirda ulana olmayapti. To <xliff:g id="VPN_APP_1">%1$s</xliff:g> ilovasiga qayta ulanmaguncha, telefoningiz ochiq tarmoqdan foydalanib turadi."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> ilovasi doim ulanib turiladigan qilib sozlangan, lekin hozirda ulana olmayapti. To VPN tarmoqqa qayta ulanmaguncha, hech qanday tarmoqqa ulanmay turiladi."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN sozlamalarini o‘zgartirish"</string> + <string name="configure" msgid="4905518375574791375">"Moslash"</string> + <string name="disconnect" msgid="971412338304200056">"Aloqani uzish"</string> + <string name="open_app" msgid="3717639178595958667">"Ilovani ochish"</string> + <string name="dismiss" msgid="6192859333764711227">"Yopish"</string> </resources> diff --git a/packages/VpnDialogs/res/values-vi/strings.xml b/packages/VpnDialogs/res/values-vi/strings.xml index c7df53fadfd0..7201683851c3 100644 --- a/packages/VpnDialogs/res/values-vi/strings.xml +++ b/packages/VpnDialogs/res/values-vi/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Yêu cầu kết nối"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> muốn thiết lập kết nối VPN cho phép ứng dụng giám sát lưu lượng truy cập mạng. Chỉ chấp nhận nếu bạn tin tưởng nguồn. <br /> <br /> <img src=vpn_icon /> xuất hiện ở đầu màn hình của bạn khi VPN đang hoạt động."</string> <string name="legacy_title" msgid="192936250066580964">"VPN được kết nối"</string> - <string name="configure" msgid="4905518375574791375">"Định cấu hình"</string> - <string name="disconnect" msgid="971412338304200056">"Ngắt kết nối"</string> <string name="session" msgid="6470628549473641030">"Phiên"</string> <string name="duration" msgid="3584782459928719435">"Thời lượng:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Đã gửi:"</string> <string name="data_received" msgid="4062776929376067820">"Đã nhận:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> byte / <xliff:g id="NUMBER_1">%2$s</xliff:g> gói"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Không thể kết nối với VPN luôn bật"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> được thiết lập để luôn duy trì kết nối nhưng hiện không thể kết nối. Điện thoại của bạn sẽ sử dụng mạng công cộng cho tới khi có thể kết nối lại với <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> được thiết lập để luôn duy trì kết nối nhưng hiện không thể kết nối. Bạn sẽ không có kết nối cho tới khi VPN này có thể kết nối lại."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Thay đổi cài đặt VPN"</string> + <string name="configure" msgid="4905518375574791375">"Định cấu hình"</string> + <string name="disconnect" msgid="971412338304200056">"Ngắt kết nối"</string> + <string name="open_app" msgid="3717639178595958667">"Mở ứng dụng"</string> + <string name="dismiss" msgid="6192859333764711227">"Loại bỏ"</string> </resources> diff --git a/packages/VpnDialogs/res/values-zh-rCN/strings.xml b/packages/VpnDialogs/res/values-zh-rCN/strings.xml index cdea95d6e17a..28153122b1f6 100644 --- a/packages/VpnDialogs/res/values-zh-rCN/strings.xml +++ b/packages/VpnDialogs/res/values-zh-rCN/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"网络连接请求"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g>想要设置一个VPN连接(可被用于监控网络流量)。请只在您信任该来源的情况下才接受此请求。在VPN处于活动状态时,您的屏幕顶部会显示 <img src=vpn_icon /> 图标。"</string> <string name="legacy_title" msgid="192936250066580964">"已连接VPN"</string> - <string name="configure" msgid="4905518375574791375">"配置"</string> - <string name="disconnect" msgid="971412338304200056">"断开连接"</string> <string name="session" msgid="6470628549473641030">"会话:"</string> <string name="duration" msgid="3584782459928719435">"时长:"</string> <string name="data_transmitted" msgid="7988167672982199061">"已发送:"</string> <string name="data_received" msgid="4062776929376067820">"已接收:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> 字节/<xliff:g id="NUMBER_1">%2$s</xliff:g> 个数据包"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"无法连接到始终开启的 VPN"</string> + <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="configure" msgid="4905518375574791375">"配置"</string> + <string name="disconnect" msgid="971412338304200056">"断开连接"</string> + <string name="open_app" msgid="3717639178595958667">"打开应用"</string> + <string name="dismiss" msgid="6192859333764711227">"关闭"</string> </resources> diff --git a/packages/VpnDialogs/res/values-zh-rHK/strings.xml b/packages/VpnDialogs/res/values-zh-rHK/strings.xml index fa77c6c695bd..f70cd5115e72 100644 --- a/packages/VpnDialogs/res/values-zh-rHK/strings.xml +++ b/packages/VpnDialogs/res/values-zh-rHK/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"連線要求"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> 要求設定 VPN 連線以監控網絡流量。除非您信任要求來源,否則請勿隨意接受要求。<br /> <br />VPN 啟用時,畫面頂端會顯示 <img src=vpn_icon />。"</string> <string name="legacy_title" msgid="192936250066580964">"VPN 已連線"</string> - <string name="configure" msgid="4905518375574791375">"設定"</string> - <string name="disconnect" msgid="971412338304200056">"中斷連線"</string> <string name="session" msgid="6470628549473641030">"時段:"</string> <string name="duration" msgid="3584782459928719435">"持續時間︰"</string> <string name="data_transmitted" msgid="7988167672982199061">"已傳送:"</string> <string name="data_received" msgid="4062776929376067820">"已接收:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> 位元組 / <xliff:g id="NUMBER_1">%2$s</xliff:g> 封包"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"無法連線至永遠開啟的 VPN"</string> + <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="configure" msgid="4905518375574791375">"設定"</string> + <string name="disconnect" msgid="971412338304200056">"中斷連線"</string> + <string name="open_app" msgid="3717639178595958667">"開啟應用程式"</string> + <string name="dismiss" msgid="6192859333764711227">"關閉"</string> </resources> diff --git a/packages/VpnDialogs/res/values-zh-rTW/strings.xml b/packages/VpnDialogs/res/values-zh-rTW/strings.xml index 6b3599332085..edd8e61d5555 100644 --- a/packages/VpnDialogs/res/values-zh-rTW/strings.xml +++ b/packages/VpnDialogs/res/values-zh-rTW/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"連線要求"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> 要求設定 VPN 連線,允許此要求即開放該來源監控網路流量。除非你信任該來源,否則請勿任意接受要求。<br /> <br />VPN 啟用時,畫面頂端會顯示 <img src=vpn_icon />。"</string> <string name="legacy_title" msgid="192936250066580964">"VPN 已連線"</string> - <string name="configure" msgid="4905518375574791375">"設定"</string> - <string name="disconnect" msgid="971412338304200056">"中斷連線"</string> <string name="session" msgid="6470628549473641030">"工作階段:"</string> <string name="duration" msgid="3584782459928719435">"持續時間:"</string> <string name="data_transmitted" msgid="7988167672982199061">"已傳送:"</string> <string name="data_received" msgid="4062776929376067820">"已接收:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> 位元組 / <xliff:g id="NUMBER_1">%2$s</xliff:g> 個封包"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"無法連上永久連線的 VPN"</string> + <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="configure" msgid="4905518375574791375">"設定"</string> + <string name="disconnect" msgid="971412338304200056">"中斷連線"</string> + <string name="open_app" msgid="3717639178595958667">"開啟應用程式"</string> + <string name="dismiss" msgid="6192859333764711227">"關閉"</string> </resources> diff --git a/packages/VpnDialogs/res/values-zu/strings.xml b/packages/VpnDialogs/res/values-zu/strings.xml index abe54a93613a..4ab1225e6fc6 100644 --- a/packages/VpnDialogs/res/values-zu/strings.xml +++ b/packages/VpnDialogs/res/values-zu/strings.xml @@ -19,11 +19,18 @@ <string name="prompt" msgid="3183836924226407828">"Isicelo soxhumo"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ifuna ukusetha uxhumo lwe-VPN eyivumela ukwengamela ithrafikhi yenethiwekhi. Yamukela kuphela uma wethemba umthombo. <br /> <br /> <img src=vpn_icon /> ibonakala phezu kwesikrini sakho uma i-VPN isebenza."</string> <string name="legacy_title" msgid="192936250066580964">"I-VPN ixhunyiwe"</string> - <string name="configure" msgid="4905518375574791375">"Misa"</string> - <string name="disconnect" msgid="971412338304200056">"Ayixhumekile kwi-inthanethi"</string> <string name="session" msgid="6470628549473641030">"Iseshini:"</string> <string name="duration" msgid="3584782459928719435">"Ubude besikhathi:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Thunyelwe:"</string> <string name="data_received" msgid="4062776929376067820">"Okwamukelwe:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> amaphakethe/ <xliff:g id="NUMBER_1">%2$s</xliff:g> amabhayithi"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Ayikwazi ukuxhuma ku-VPN njalo"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> isethelwe ukuhlala ixhumekile ngazo zonke izikhathi, kodwa ayikwazi ukuxhuma manje. Ifoni yakho izosebenzisa inethiwekhi ize ikwazi ukuxhuma ku-<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> isethelwe ukuhlala ixhumekile ngazo zonke izikhathi, kodwa ayikwazi ukuxhuma manje. Ngeke ube noxhumo i-VPN ize ikwazi ukuxhuma."</string> + <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Shintsha izilungiseleo ze-VPN"</string> + <string name="configure" msgid="4905518375574791375">"Misa"</string> + <string name="disconnect" msgid="971412338304200056">"Ayixhumekile kwi-inthanethi"</string> + <string name="open_app" msgid="3717639178595958667">"Vula uhlelo lokusebenza"</string> + <string name="dismiss" msgid="6192859333764711227">"Cashisa"</string> </resources> diff --git a/packages/VpnDialogs/res/values/strings.xml b/packages/VpnDialogs/res/values/strings.xml index 406bcc34a101..443a9bc33b90 100644 --- a/packages/VpnDialogs/res/values/strings.xml +++ b/packages/VpnDialogs/res/values/strings.xml @@ -18,7 +18,6 @@ <!-- Dialog title to identify the request from a VPN application. [CHAR LIMIT=60] --> <string name="prompt">Connection request</string> - <!-- Dialog message to warn about the risk of using a VPN application. [CHAR LIMIT=NONE] --> <string name="warning"><xliff:g id="app">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. @@ -31,11 +30,6 @@ <!-- Dialog title for built-in VPN. [CHAR LIMIT=40] --> <string name="legacy_title">VPN is connected</string> - <!-- Button label to configure the current VPN session. [CHAR LIMIT=20] --> - <string name="configure">Configure</string> - <!-- Button label to disconnect the current VPN session. [CHAR LIMIT=20] --> - <string name="disconnect">Disconnect</string> - <!-- Label for the name of the current VPN session. [CHAR LIMIT=20] --> <string name="session">Session:</string> <!-- Label for the duration of the current VPN session. [CHAR LIMIT=20] --> @@ -44,10 +38,55 @@ <string name="data_transmitted">Sent:</string> <!-- Label for the network usage of data received over VPN. [CHAR LIMIT=20] --> <string name="data_received">Received:</string> - <!-- Formatted string for the network usage over VPN. [CHAR LIMIT=40] --> <string name="data_value_format"> <xliff:g id="number">%1$s</xliff:g> bytes / <xliff:g id="number">%2$s</xliff:g> packets </string> + + <!-- This string is the title of a dialog. The dialog shows up for Android users when always-on + VPN, a VPN that's set to always stay connected, loses its connection. [CHAR LIMIT=60] --> + <string name="always_on_disconnected_title">Can\'t connect to always-on VPN</string> + <!-- This message is part of a dialog. The dialog shows up for users when always-on VPN, a VPN + that's set to always stay connected, loses its connection. Until the phone can reconnect to + the VPN, it'll automatically connect to a public network if possible. This text is followed + by a clickable link that leads to VPN settings. [CHAR LIMIT=NONE] --> + <string name="always_on_disconnected_message"> + <xliff:g id="vpn_app" example="Foo VPN App">%1$s</xliff:g> is set up to stay connected all + the time, but it can\'t connect right now. Your phone will use a public network until it can + reconnect to <xliff:g id="vpn_app" example="Foo VPN App">%1$s</xliff:g>. + </string> + <!-- This message is part of a dialog. The dialog shows up for users when always-on VPN, a VPN + that's set to always stay connected, loses its connection while in the lockdown mode. + Until the phone can reconnect to the VPN, it won't be able to connect to the Internet. This + text is followed by a clickable link that leads to VPN settings. [CHAR LIMIT=NONE] --> + <string name="always_on_disconnected_message_lockdown"> + <xliff:g id="vpn_app" example="Foo VPN App">%1$s</xliff:g> is set up to stay connected all + the time, but it can\'t connect right now. You won\'t have a connection until the VPN can + reconnect. + </string> + <!-- This is a space separating the body text and the "Change VPN settings" link that follows + it. [CHAR LIMIT=5] --> + <string name="always_on_disconnected_message_separator">" "</string> + <!-- This is a clickable link appended at the end of the body text of a dialog. The dialog shows + up for users when always-on VPN, a VPN that's set to always stay connected, loses its + connection. This link takes the user to the VPN page in Settings. --> + <string name="always_on_disconnected_message_settings_link">Change VPN settings</string> + + <!-- This is the label of a button in a dialog. The button takes the user to the VPN settings + screen. [CHAR LIMIT=20] --> + <string name="configure">Configure</string> + <!-- This is the label of a button in a dialog. The button lets the user disconnect from the + current VPN connection. [CHAR LIMIT=20] --> + <string name="disconnect">Disconnect</string> + <!-- This button is part of a dialog, and it opens the user's VPN app. The dialog shows up for + users when always-on VPN, a VPN that's set to always stay connected, loses its connection. + Until the phone can reconnect to the VPN, it may automatically connect to a public network. + If it doesn't, the user won't have a connection until the VPN reconnects. [CHAR LIMIT=20] + --> + <string name="open_app">Open app</string> + <!-- This is the label of a button in a dialog. The button lets the user dismiss the dialog + without any consequences. [CHAR LIMIT=20] --> + <string name="dismiss">Dismiss</string> + </resources> diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/AlwaysOnDisconnectedDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/AlwaysOnDisconnectedDialog.java new file mode 100644 index 000000000000..846fcf867e32 --- /dev/null +++ b/packages/VpnDialogs/src/com/android/vpndialogs/AlwaysOnDisconnectedDialog.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.vpndialogs; + +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.IConnectivityManager; +import android.os.Bundle; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.UserHandle; +import android.provider.Settings; +import android.text.SpannableStringBuilder; +import android.text.method.LinkMovementMethod; +import android.text.style.ClickableSpan; +import android.util.Log; +import android.view.View; +import android.view.WindowManager; +import android.widget.TextView; + +import com.android.internal.app.AlertActivity; +import com.android.internal.net.VpnConfig; + +public class AlwaysOnDisconnectedDialog extends AlertActivity + implements DialogInterface.OnClickListener{ + + private static final String TAG = "VpnDisconnected"; + + private IConnectivityManager mService; + private int mUserId; + private String mVpnPackage; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mService = IConnectivityManager.Stub.asInterface( + ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); + mUserId = UserHandle.myUserId(); + mVpnPackage = getAlwaysOnVpnPackage(); + if (mVpnPackage == null) { + finish(); + return; + } + + View view = View.inflate(this, R.layout.always_on_disconnected, null); + TextView messageView = view.findViewById(R.id.message); + messageView.setText(getMessage(getIntent().getBooleanExtra("lockdown", false))); + messageView.setMovementMethod(LinkMovementMethod.getInstance()); + + mAlertParams.mTitle = getString(R.string.always_on_disconnected_title); + mAlertParams.mPositiveButtonText = getString(R.string.open_app); + mAlertParams.mPositiveButtonListener = this; + mAlertParams.mNegativeButtonText = getString(R.string.dismiss); + mAlertParams.mNegativeButtonListener = this; + mAlertParams.mCancelable = false; + mAlertParams.mView = view; + setupAlert(); + + getWindow().setCloseOnTouchOutside(false); + getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); + } + + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which) { + case BUTTON_POSITIVE: + PackageManager pm = getPackageManager(); + final Intent intent = pm.getLaunchIntentForPackage(mVpnPackage); + if (intent != null) { + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); + } + finish(); + break; + case BUTTON_NEGATIVE: + finish(); + break; + default: + break; + } + } + + private String getAlwaysOnVpnPackage() { + try { + return mService.getAlwaysOnVpnPackage(mUserId); + } catch (RemoteException e) { + Log.e(TAG, "Can't getAlwaysOnVpnPackage()", e); + return null; + } + } + + private CharSequence getVpnLabel() { + try { + return VpnConfig.getVpnLabel(this, mVpnPackage); + } catch (PackageManager.NameNotFoundException e) { + Log.w(TAG, "Can't getVpnLabel() for " + mVpnPackage, e); + return mVpnPackage; + } + } + + private CharSequence getMessage(boolean isLockdown) { + final SpannableStringBuilder message = new SpannableStringBuilder(); + final int baseMessageResId = isLockdown + ? R.string.always_on_disconnected_message_lockdown + : R.string.always_on_disconnected_message; + message.append(getString(baseMessageResId, getVpnLabel())); + message.append(getString(R.string.always_on_disconnected_message_separator)); + message.append(getString(R.string.always_on_disconnected_message_settings_link), + new VpnSpan(), 0 /*flags*/); + return message; + } + + private class VpnSpan extends ClickableSpan { + @Override + public void onClick(View unused) { + final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); + } + } +} diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java index 2fe6648d82da..01dca7e30e64 100644 --- a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java +++ b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java @@ -54,12 +54,6 @@ public class ManageDialog extends AlertActivity implements protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if (getCallingPackage() != null) { - Log.e(TAG, getCallingPackage() + " cannot start this activity"); - finish(); - return; - } - try { mService = IConnectivityManager.Stub.asInterface( diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index ae259321062b..7690f6d2853c 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -62,6 +62,14 @@ message MetricsEvent { // The action failed TYPE_FAILURE = 11; + + // Type for APP_TRANSITION_REPORTED_DRAWN event: The activity was started without restoring from + // a bundle. + TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE = 12; + + // Type for APP_TRANSITION_REPORTED_DRAWN event: The activity was started with restoring from + // a bundle. + TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE = 13; } // Types of alerts, as bit field values @@ -4043,6 +4051,7 @@ message MetricsEvent { ASSIST_GESTURE_PRIMED = 998; // ACTION: Assist gesture triggered + // SUBTYPE: 1 is for SCREEN_ON, 2 is for SCREEN_OFF // CATEGORY: GLOBAL_SYSTEM_UI // OS: O DR ASSIST_GESTURE_TRIGGERED = 999; @@ -4265,6 +4274,19 @@ message MetricsEvent { // FIELD: The numeric preference value (of type int) when it is changed in Settings FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE = 1089; + // ACTION: Logged when the app has notified that it has fully drawn. See + // Activity.reportFullyDrawn(). + APP_TRANSITION_REPORTED_DRAWN = 1090; + + // FIELD: The delay of the activity reporting to be fully drawn measured from the beginning of + // the app transition. + APP_TRANSITION_REPORTED_DRAWN_MS = 1091; + + // OPEN: Settings > Storage > Photos & Videos + // CATEGORY: SETTINGS + // OS: O MR + APPLICATIONS_STORAGE_PHOTOS = 1092; + // ---- End O-MR1 Constants, all O-MR1 constants go above this line ---- // OPEN: Settings > Network & Internet > Mobile network @@ -4334,6 +4356,10 @@ message MetricsEvent { // CATEGORY: SETTINGS ACTION_MOBILE_NETWORK_SET_UP_DATA_SERVICE = 1155; + // OPEN: Settings > Developer Options > Experiment dashboard + // CATEGORY: SETTINGS + SETTINGS_FEATURE_FLAGS_DASHBOARD = 1156; + // Add new aosp constants above this line. // END OF AOSP CONSTANTS } diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityClientConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityClientConnection.java new file mode 100644 index 000000000000..df4c8ed5e400 --- /dev/null +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityClientConnection.java @@ -0,0 +1,1325 @@ +/* + ** Copyright 2017, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +package com.android.server.accessibility; + +import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT; +import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; + +import android.accessibilityservice.AccessibilityService; +import android.accessibilityservice.AccessibilityServiceInfo; +import android.accessibilityservice.GestureDescription; +import android.accessibilityservice.IAccessibilityServiceClient; +import android.accessibilityservice.IAccessibilityServiceConnection; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.PendingIntent; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.pm.ParceledListSlice; +import android.graphics.Region; +import android.os.Binder; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.RemoteException; +import android.util.Slog; +import android.util.SparseArray; +import android.view.KeyEvent; +import android.view.MagnificationSpec; +import android.view.View; +import android.view.WindowManagerInternal; +import android.view.accessibility.AccessibilityCache; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityInteractionClient; +import android.view.accessibility.AccessibilityNodeInfo; +import android.view.accessibility.AccessibilityWindowInfo; +import android.view.accessibility.IAccessibilityInteractionConnection; +import android.view.accessibility.IAccessibilityInteractionConnectionCallback; + + +import com.android.internal.os.SomeArgs; +import com.android.internal.util.DumpUtils; +import com.android.server.accessibility.AccessibilityManagerService.SecurityPolicy; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * This class represents an accessibility client - either an AccessibilityService or a UiAutomation. + * It is responsible for behavior common to both types of clients. + */ +abstract class AccessibilityClientConnection extends IAccessibilityServiceConnection.Stub + implements ServiceConnection, IBinder.DeathRecipient, KeyEventDispatcher.KeyEventFilter, + FingerprintGestureDispatcher.FingerprintGestureClient { + private static final boolean DEBUG = false; + private static final String LOG_TAG = "AccessibilityClientConnection"; + + protected final Context mContext; + protected final SystemSupport mSystemSupport; + private final WindowManagerInternal mWindowManagerService; + private final GlobalActionPerformer mGlobalActionPerformer; + + // Handler for scheduling method invocations on the main thread. + public final InvocationHandler mInvocationHandler; + + final int mId; + + final AccessibilityServiceInfo mAccessibilityServiceInfo; + + // Lock must match the one used by AccessibilityManagerService + protected final Object mLock; + + protected final SecurityPolicy mSecurityPolicy; + + // The service that's bound to this instance. Whenever this value is non-null, this + // object is registered as a death recipient + IBinder mService; + + IAccessibilityServiceClient mServiceInterface; + + int mEventTypes; + + int mFeedbackType; + + Set<String> mPackageNames = new HashSet<>(); + + boolean mIsDefault; + + boolean mRequestTouchExplorationMode; + + boolean mRequestFilterKeyEvents; + + boolean mRetrieveInteractiveWindows; + + boolean mCaptureFingerprintGestures; + + boolean mRequestAccessibilityButton; + + boolean mReceivedAccessibilityButtonCallbackSinceBind; + + boolean mLastAccessibilityButtonCallbackState; + + int mFetchFlags; + + long mNotificationTimeout; + + final ComponentName mComponentName; + + // the events pending events to be dispatched to this service + final SparseArray<AccessibilityEvent> mPendingEvents = new SparseArray<>(); + + /** Whether this service relies on its {@link AccessibilityCache} being up to date */ + boolean mUsesAccessibilityCache = false; + + // Handler only for dispatching accessibility events since we use event + // types as message types allowing us to remove messages per event type. + public Handler mEventDispatchHandler; + + final IBinder mOverlayWindowToken = new Binder(); + + + public interface SystemSupport { + /** + * @return The current dispatcher for key events + */ + @NonNull KeyEventDispatcher getKeyEventDispatcher(); + + /** + * @param windowId The id of the window of interest + * @return The magnification spec for the window, or {@code null} if none is available + */ + @Nullable MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId); + + /** + * @return The current injector of motion events, if one exists + */ + @Nullable MotionEventInjector getMotionEventInjectorLocked(); + + /** + * @return The current dispatcher for fingerprint gestures, if one exists + */ + @Nullable FingerprintGestureDispatcher getFingerprintGestureDispatcher(); + + /** + * @return The magnification controller + */ + @NonNull MagnificationController getMagnificationController(); + + /** + * Resolve a connection for a window id + * + * @param windowId The id of the window of interest + * + * @return a connection to the window + */ + IAccessibilityInteractionConnection getConnectionLocked(int windowId); + + /** + * Perform the specified accessibility action + * + * @param resolvedWindowId The window ID + * [Other parameters match the method on IAccessibilityServiceConnection] + * + * @return Whether or not the action could be sent to the app process + */ + boolean performAccessibilityAction(int resolvedWindowId, + long accessibilityNodeId, int action, Bundle arguments, int interactionId, + IAccessibilityInteractionConnectionCallback callback, int fetchFlags, + long interrogatingTid); + + /** + * Replace the interaction callback if needed, for example if the window is in picture- + * in-picture mode and needs its nodes replaced. + * + * @param originalCallback The callback we were planning to use + * @param resolvedWindowId The ID of the window we're calling + * @param interactionId The id for the original callback + * @param interrogatingPid Process ID of requester + * @param interrogatingTid Thread ID of requester + * + * @return The callback to use, which may be the original one. + */ + @NonNull IAccessibilityInteractionConnectionCallback replaceCallbackIfNeeded( + IAccessibilityInteractionConnectionCallback originalCallback, + int resolvedWindowId, int interactionId, int interrogatingPid, + long interrogatingTid); + + /** + * Request that the system make sure windows are available to interrogate + */ + void ensureWindowsAvailableTimed(); + + /** + * Called back to notify system that the client has changed + * @param serviceInfoChanged True if the service's AccessibilityServiceInfo changed. + */ + void onClientChange(boolean serviceInfoChanged); + + int getCurrentUserIdLocked(); + + boolean isAccessibilityButtonShown(); + + /** + * Persists the component names in the specified setting in a + * colon separated fashion. + * + * @param settingName The setting name. + * @param componentNames The component names. + * @param userId The user id to persist the setting for. + */ + void persistComponentNamesToSettingLocked(String settingName, + Set<ComponentName> componentNames, int userId); + + /* This is exactly PendingIntent.getActivity, separated out for testability */ + PendingIntent getPendingIntentActivity(Context context, int requestCode, Intent intent, + int flags); + } + + public AccessibilityClientConnection(Context context, ComponentName componentName, + AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler, + Object lock, SecurityPolicy securityPolicy, SystemSupport systemSupport, + WindowManagerInternal windowManagerInternal, + GlobalActionPerformer globalActionPerfomer) { + mContext = context; + mWindowManagerService = windowManagerInternal; + mId = id; + mComponentName = componentName; + mAccessibilityServiceInfo = accessibilityServiceInfo; + mLock = lock; + mSecurityPolicy = securityPolicy; + mGlobalActionPerformer = globalActionPerfomer; + mSystemSupport = systemSupport; + mInvocationHandler = new InvocationHandler(mainHandler.getLooper()); + mEventDispatchHandler = new Handler(mainHandler.getLooper()) { + @Override + public void handleMessage(Message message) { + final int eventType = message.what; + AccessibilityEvent event = (AccessibilityEvent) message.obj; + boolean serviceWantsEvent = message.arg1 != 0; + notifyAccessibilityEventInternal(eventType, event, serviceWantsEvent); + } + }; + setDynamicallyConfigurableProperties(accessibilityServiceInfo); + } + + @Override + public boolean onKeyEvent(KeyEvent keyEvent, int sequenceNumber) { + if (!mRequestFilterKeyEvents || (mServiceInterface == null)) { + return false; + } + if((mAccessibilityServiceInfo.getCapabilities() + & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) == 0) { + return false; + } + try { + mServiceInterface.onKeyEvent(keyEvent, sequenceNumber); + } catch (RemoteException e) { + return false; + } + return true; + } + + public void setDynamicallyConfigurableProperties(AccessibilityServiceInfo info) { + mEventTypes = info.eventTypes; + mFeedbackType = info.feedbackType; + String[] packageNames = info.packageNames; + if (packageNames != null) { + mPackageNames.addAll(Arrays.asList(packageNames)); + } + mNotificationTimeout = info.notificationTimeout; + mIsDefault = (info.flags & DEFAULT) != 0; + + if (supportsFlagForNotImportantViews(info)) { + if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) { + mFetchFlags |= AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; + } else { + mFetchFlags &= ~AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; + } + } + + if ((info.flags & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0) { + mFetchFlags |= AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS; + } else { + mFetchFlags &= ~AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS; + } + + mRequestTouchExplorationMode = (info.flags + & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0; + mRequestFilterKeyEvents = (info.flags + & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0; + mRetrieveInteractiveWindows = (info.flags + & AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS) != 0; + mCaptureFingerprintGestures = (info.flags + & AccessibilityServiceInfo.FLAG_REQUEST_FINGERPRINT_GESTURES) != 0; + mRequestAccessibilityButton = (info.flags + & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0; + } + + protected boolean supportsFlagForNotImportantViews(AccessibilityServiceInfo info) { + return info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion + >= Build.VERSION_CODES.JELLY_BEAN; + } + + public boolean canReceiveEventsLocked() { + return (mEventTypes != 0 && mFeedbackType != 0 && mService != null); + } + + @Override + public void setOnKeyEventResult(boolean handled, int sequence) { + mSystemSupport.getKeyEventDispatcher().setOnKeyEventResult(this, handled, sequence); + } + + @Override + public AccessibilityServiceInfo getServiceInfo() { + synchronized (mLock) { + return mAccessibilityServiceInfo; + } + } + + @Override + public void setServiceInfo(AccessibilityServiceInfo info) { + final long identity = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + // If the XML manifest had data to configure the service its info + // should be already set. In such a case update only the dynamically + // configurable properties. + AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo; + if (oldInfo != null) { + oldInfo.updateDynamicallyConfigurableProperties(info); + setDynamicallyConfigurableProperties(oldInfo); + } else { + setDynamicallyConfigurableProperties(info); + } + mSystemSupport.onClientChange(true); + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + protected abstract boolean isCalledForCurrentUserLocked(); + + @Override + public List<AccessibilityWindowInfo> getWindows() { + mSystemSupport.ensureWindowsAvailableTimed(); + synchronized (mLock) { + if (!isCalledForCurrentUserLocked()) { + return null; + } + final boolean permissionGranted = + mSecurityPolicy.canRetrieveWindowsLocked(this); + if (!permissionGranted) { + return null; + } + if (mSecurityPolicy.mWindows == null) { + return null; + } + List<AccessibilityWindowInfo> windows = new ArrayList<>(); + final int windowCount = mSecurityPolicy.mWindows.size(); + for (int i = 0; i < windowCount; i++) { + AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(i); + AccessibilityWindowInfo windowClone = + AccessibilityWindowInfo.obtain(window); + windowClone.setConnectionId(mId); + windows.add(windowClone); + } + return windows; + } + } + + @Override + public AccessibilityWindowInfo getWindow(int windowId) { + mSystemSupport.ensureWindowsAvailableTimed(); + synchronized (mLock) { + if (!isCalledForCurrentUserLocked()) { + return null; + } + final boolean permissionGranted = + mSecurityPolicy.canRetrieveWindowsLocked(this); + if (!permissionGranted) { + return null; + } + AccessibilityWindowInfo window = mSecurityPolicy.findA11yWindowInfoById(windowId); + if (window != null) { + AccessibilityWindowInfo windowClone = AccessibilityWindowInfo.obtain(window); + windowClone.setConnectionId(mId); + return windowClone; + } + return null; + } + } + + @Override + public boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId, + long accessibilityNodeId, String viewIdResName, int interactionId, + IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) + throws RemoteException { + final int resolvedWindowId; + IAccessibilityInteractionConnection connection = null; + Region partialInteractiveRegion = Region.obtain(); + MagnificationSpec spec; + synchronized (mLock) { + mUsesAccessibilityCache = true; + if (!isCalledForCurrentUserLocked()) { + return false; + } + resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); + final boolean permissionGranted = + mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); + if (!permissionGranted) { + return false; + } else { + connection = mSystemSupport.getConnectionLocked(resolvedWindowId); + if (connection == null) { + return false; + } + } + if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( + resolvedWindowId, partialInteractiveRegion)) { + partialInteractiveRegion.recycle(); + partialInteractiveRegion = null; + } + spec = mSystemSupport.getCompatibleMagnificationSpecLocked(resolvedWindowId); + } + final int interrogatingPid = Binder.getCallingPid(); + callback = mSystemSupport.replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, + interrogatingPid, interrogatingTid); + final long identityToken = Binder.clearCallingIdentity(); + try { + connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId, viewIdResName, + partialInteractiveRegion, interactionId, callback, mFetchFlags, + interrogatingPid, interrogatingTid, spec); + return true; + } catch (RemoteException re) { + if (DEBUG) { + Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId()."); + } + } finally { + Binder.restoreCallingIdentity(identityToken); + // Recycle if passed to another process. + if (partialInteractiveRegion != null && Binder.isProxy(connection)) { + partialInteractiveRegion.recycle(); + } + } + return false; + } + + @Override + public boolean findAccessibilityNodeInfosByText(int accessibilityWindowId, + long accessibilityNodeId, String text, int interactionId, + IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) + throws RemoteException { + final int resolvedWindowId; + IAccessibilityInteractionConnection connection = null; + Region partialInteractiveRegion = Region.obtain(); + MagnificationSpec spec; + synchronized (mLock) { + mUsesAccessibilityCache = true; + if (!isCalledForCurrentUserLocked()) { + return false; + } + resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); + final boolean permissionGranted = + mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); + if (!permissionGranted) { + return false; + } else { + connection = mSystemSupport.getConnectionLocked(resolvedWindowId); + if (connection == null) { + return false; + } + } + if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( + resolvedWindowId, partialInteractiveRegion)) { + partialInteractiveRegion.recycle(); + partialInteractiveRegion = null; + } + spec = mSystemSupport.getCompatibleMagnificationSpecLocked(resolvedWindowId); + } + final int interrogatingPid = Binder.getCallingPid(); + callback = mSystemSupport.replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, + interrogatingPid, interrogatingTid); + final long identityToken = Binder.clearCallingIdentity(); + try { + connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text, + partialInteractiveRegion, interactionId, callback, mFetchFlags, + interrogatingPid, interrogatingTid, spec); + return true; + } catch (RemoteException re) { + if (DEBUG) { + Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()"); + } + } finally { + Binder.restoreCallingIdentity(identityToken); + // Recycle if passed to another process. + if (partialInteractiveRegion != null && Binder.isProxy(connection)) { + partialInteractiveRegion.recycle(); + } + } + return false; + } + + @Override + public boolean findAccessibilityNodeInfoByAccessibilityId( + int accessibilityWindowId, long accessibilityNodeId, int interactionId, + IAccessibilityInteractionConnectionCallback callback, int flags, + long interrogatingTid, Bundle arguments) throws RemoteException { + final int resolvedWindowId; + IAccessibilityInteractionConnection connection = null; + Region partialInteractiveRegion = Region.obtain(); + MagnificationSpec spec; + synchronized (mLock) { + mUsesAccessibilityCache = true; + if (!isCalledForCurrentUserLocked()) { + return false; + } + resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); + final boolean permissionGranted = + mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); + if (!permissionGranted) { + return false; + } else { + connection = mSystemSupport.getConnectionLocked(resolvedWindowId); + if (connection == null) { + return false; + } + } + if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( + resolvedWindowId, partialInteractiveRegion)) { + partialInteractiveRegion.recycle(); + partialInteractiveRegion = null; + } + spec = mSystemSupport.getCompatibleMagnificationSpecLocked(resolvedWindowId); + } + final int interrogatingPid = Binder.getCallingPid(); + callback = mSystemSupport.replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, + interrogatingPid, interrogatingTid); + final long identityToken = Binder.clearCallingIdentity(); + try { + connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId, + partialInteractiveRegion, interactionId, callback, mFetchFlags | flags, + interrogatingPid, interrogatingTid, spec, arguments); + return true; + } catch (RemoteException re) { + if (DEBUG) { + Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()"); + } + } finally { + Binder.restoreCallingIdentity(identityToken); + // Recycle if passed to another process. + if (partialInteractiveRegion != null && Binder.isProxy(connection)) { + partialInteractiveRegion.recycle(); + } + } + return false; + } + + @Override + public boolean findFocus(int accessibilityWindowId, long accessibilityNodeId, + int focusType, int interactionId, + IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) + throws RemoteException { + final int resolvedWindowId; + IAccessibilityInteractionConnection connection = null; + Region partialInteractiveRegion = Region.obtain(); + MagnificationSpec spec; + synchronized (mLock) { + if (!isCalledForCurrentUserLocked()) { + return false; + } + resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked( + accessibilityWindowId, focusType); + final boolean permissionGranted = + mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); + if (!permissionGranted) { + return false; + } else { + connection = mSystemSupport.getConnectionLocked(resolvedWindowId); + if (connection == null) { + return false; + } + } + if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( + resolvedWindowId, partialInteractiveRegion)) { + partialInteractiveRegion.recycle(); + partialInteractiveRegion = null; + } + spec = mSystemSupport.getCompatibleMagnificationSpecLocked(resolvedWindowId); + } + final int interrogatingPid = Binder.getCallingPid(); + callback = mSystemSupport.replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, + interrogatingPid, interrogatingTid); + final long identityToken = Binder.clearCallingIdentity(); + try { + connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion, + interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid, + spec); + return true; + } catch (RemoteException re) { + if (DEBUG) { + Slog.e(LOG_TAG, "Error calling findFocus()"); + } + } finally { + Binder.restoreCallingIdentity(identityToken); + // Recycle if passed to another process. + if (partialInteractiveRegion != null && Binder.isProxy(connection)) { + partialInteractiveRegion.recycle(); + } + } + return false; + } + + @Override + public boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId, + int direction, int interactionId, + IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) + throws RemoteException { + final int resolvedWindowId; + IAccessibilityInteractionConnection connection = null; + Region partialInteractiveRegion = Region.obtain(); + MagnificationSpec spec; + synchronized (mLock) { + if (!isCalledForCurrentUserLocked()) { + return false; + } + resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); + final boolean permissionGranted = + mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); + if (!permissionGranted) { + return false; + } else { + connection = mSystemSupport.getConnectionLocked(resolvedWindowId); + if (connection == null) { + return false; + } + } + if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( + resolvedWindowId, partialInteractiveRegion)) { + partialInteractiveRegion.recycle(); + partialInteractiveRegion = null; + } + spec = mSystemSupport.getCompatibleMagnificationSpecLocked(resolvedWindowId); + } + final int interrogatingPid = Binder.getCallingPid(); + callback = mSystemSupport.replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, + interrogatingPid, interrogatingTid); + final long identityToken = Binder.clearCallingIdentity(); + try { + connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion, + interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid, + spec); + return true; + } catch (RemoteException re) { + if (DEBUG) { + Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()"); + } + } finally { + Binder.restoreCallingIdentity(identityToken); + // Recycle if passed to another process. + if (partialInteractiveRegion != null && Binder.isProxy(connection)) { + partialInteractiveRegion.recycle(); + } + } + return false; + } + + @Override + public void sendGesture(int sequence, ParceledListSlice gestureSteps) { + } + + @Override + public boolean performAccessibilityAction(int accessibilityWindowId, + long accessibilityNodeId, int action, Bundle arguments, int interactionId, + IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) + throws RemoteException { + final int resolvedWindowId; + IAccessibilityInteractionConnection connection = null; + synchronized (mLock) { + if (!isCalledForCurrentUserLocked()) { + return false; + } + resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); + if (!mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId)) { + return false; + } + } + boolean returnValue = + mSystemSupport.performAccessibilityAction(resolvedWindowId, accessibilityNodeId, + action, arguments, interactionId, callback, mFetchFlags, interrogatingTid); + return returnValue; + } + + @Override + public boolean performGlobalAction(int action) { + synchronized (mLock) { + if (!isCalledForCurrentUserLocked()) { + return false; + } + } + return mGlobalActionPerformer.performGlobalAction(action); + } + + @Override + public boolean isFingerprintGestureDetectionAvailable() { + if (isCapturingFingerprintGestures()) { + FingerprintGestureDispatcher dispatcher = + mSystemSupport.getFingerprintGestureDispatcher(); + return (dispatcher != null) && dispatcher.isFingerprintGestureDetectionAvailable(); + } + return false; + } + + @Override + public float getMagnificationScale() { + synchronized (mLock) { + if (!isCalledForCurrentUserLocked()) { + return 1.0f; + } + } + final long identity = Binder.clearCallingIdentity(); + try { + return mSystemSupport.getMagnificationController().getScale(); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public Region getMagnificationRegion() { + synchronized (mLock) { + final Region region = Region.obtain(); + if (!isCalledForCurrentUserLocked()) { + return region; + } + MagnificationController magnificationController = + mSystemSupport.getMagnificationController(); + boolean registeredJustForThisCall = + registerMagnificationIfNeeded(magnificationController); + final long identity = Binder.clearCallingIdentity(); + try { + magnificationController.getMagnificationRegion(region); + return region; + } finally { + Binder.restoreCallingIdentity(identity); + if (registeredJustForThisCall) { + magnificationController.unregister(); + } + } + } + } + + @Override + public float getMagnificationCenterX() { + synchronized (mLock) { + if (!isCalledForCurrentUserLocked()) { + return 0.0f; + } + MagnificationController magnificationController = + mSystemSupport.getMagnificationController(); + boolean registeredJustForThisCall = + registerMagnificationIfNeeded(magnificationController); + final long identity = Binder.clearCallingIdentity(); + try { + return magnificationController.getCenterX(); + } finally { + Binder.restoreCallingIdentity(identity); + if (registeredJustForThisCall) { + magnificationController.unregister(); + } + } + } + } + + @Override + public float getMagnificationCenterY() { + synchronized (mLock) { + if (!isCalledForCurrentUserLocked()) { + return 0.0f; + } + MagnificationController magnificationController = + mSystemSupport.getMagnificationController(); + boolean registeredJustForThisCall = + registerMagnificationIfNeeded(magnificationController); + final long identity = Binder.clearCallingIdentity(); + try { + return magnificationController.getCenterY(); + } finally { + Binder.restoreCallingIdentity(identity); + if (registeredJustForThisCall) { + magnificationController.unregister(); + } + } + } + } + + private boolean registerMagnificationIfNeeded( + MagnificationController magnificationController) { + if (!magnificationController.isRegisteredLocked() + && mSecurityPolicy.canControlMagnification(this)) { + magnificationController.register(); + return true; + } + return false; + } + + @Override + public boolean resetMagnification(boolean animate) { + synchronized (mLock) { + if (!isCalledForCurrentUserLocked()) { + return false; + } + if (!mSecurityPolicy.canControlMagnification(this)) { + return false; + } + } + final long identity = Binder.clearCallingIdentity(); + try { + return mSystemSupport.getMagnificationController().reset(animate); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public boolean setMagnificationScaleAndCenter(float scale, float centerX, float centerY, + boolean animate) { + synchronized (mLock) { + if (!isCalledForCurrentUserLocked()) { + return false; + } + if (!mSecurityPolicy.canControlMagnification(this)) { + return false; + } + final long identity = Binder.clearCallingIdentity(); + try { + MagnificationController magnificationController = + mSystemSupport.getMagnificationController(); + if (!magnificationController.isRegisteredLocked()) { + magnificationController.register(); + } + return magnificationController + .setScaleAndCenter(scale, centerX, centerY, animate, mId); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + } + + @Override + public void setMagnificationCallbackEnabled(boolean enabled) { + mInvocationHandler.setMagnificationCallbackEnabled(enabled); + } + + public boolean isMagnificationCallbackEnabled() { + return mInvocationHandler.mIsMagnificationCallbackEnabled; + } + + @Override + public void setSoftKeyboardCallbackEnabled(boolean enabled) { + mInvocationHandler.setSoftKeyboardCallbackEnabled(enabled); + } + + @Override + public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { + if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return; + synchronized (mLock) { + pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo() + .loadLabel(mContext.getPackageManager())); + pw.append(", feedbackType" + + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType)); + pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities()); + pw.append(", eventTypes=" + + AccessibilityEvent.eventTypeToString(mEventTypes)); + pw.append(", notificationTimeout=" + mNotificationTimeout); + pw.append("]"); + } + } + + public void onAdded() { + final long identity = Binder.clearCallingIdentity(); + try { + mWindowManagerService.addWindowToken(mOverlayWindowToken, + TYPE_ACCESSIBILITY_OVERLAY, DEFAULT_DISPLAY); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + public void onRemoved() { + final long identity = Binder.clearCallingIdentity(); + try { + mWindowManagerService.removeWindowToken(mOverlayWindowToken, true, DEFAULT_DISPLAY); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + public void resetLocked() { + mSystemSupport.getKeyEventDispatcher().flush(this); + try { + // Clear the proxy in the other process so this + // IAccessibilityServiceConnection can be garbage collected. + if (mServiceInterface != null) { + mServiceInterface.init(null, mId, null); + } + } catch (RemoteException re) { + /* ignore */ + } + if (mService != null) { + mService.unlinkToDeath(this, 0); + mService = null; + } + + mServiceInterface = null; + mReceivedAccessibilityButtonCallbackSinceBind = false; + } + + public boolean isConnectedLocked() { + return (mService != null); + } + + public void notifyAccessibilityEvent(AccessibilityEvent event) { + synchronized (mLock) { + final boolean serviceWantsEvent = wantsEventLocked(event); + if (!serviceWantsEvent && !mUsesAccessibilityCache && + ((AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK & event.getEventType()) == 0)) { + return; + } + + final int eventType = event.getEventType(); + // Make a copy since during dispatch it is possible the event to + // be modified to remove its source if the receiving service does + // not have permission to access the window content. + AccessibilityEvent newEvent = AccessibilityEvent.obtain(event); + Message message; + if ((mNotificationTimeout > 0) + && (eventType != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)) { + // Allow at most one pending event + final AccessibilityEvent oldEvent = mPendingEvents.get(eventType); + mPendingEvents.put(eventType, newEvent); + if (oldEvent != null) { + mEventDispatchHandler.removeMessages(eventType); + oldEvent.recycle(); + } + message = mEventDispatchHandler.obtainMessage(eventType); + } else { + // Send all messages, bypassing mPendingEvents + message = mEventDispatchHandler.obtainMessage(eventType, newEvent); + } + message.arg1 = serviceWantsEvent ? 1 : 0; + + mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout); + } + } + + /** + * Determines if given event can be dispatched to a service based on the package of the + * event source. Specifically, a service is notified if it is interested in events from the + * package. + * + * @param event The event. + * @return True if the listener should be notified, false otherwise. + */ + private boolean wantsEventLocked(AccessibilityEvent event) { + + if (!canReceiveEventsLocked()) { + return false; + } + + if ((event.getWindowId() != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) + && !event.isImportantForAccessibility() + && (mFetchFlags & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) { + return false; + } + + int eventType = event.getEventType(); + if ((mEventTypes & eventType) != eventType) { + return false; + } + + Set<String> packageNames = mPackageNames; + String packageName = (event.getPackageName() != null) + ? event.getPackageName().toString() : null; + + return (packageNames.isEmpty() || packageNames.contains(packageName)); + } + + /** + * Notifies an accessibility service client for a scheduled event given the event type. + * + * @param eventType The type of the event to dispatch. + */ + private void notifyAccessibilityEventInternal( + int eventType, + AccessibilityEvent event, + boolean serviceWantsEvent) { + IAccessibilityServiceClient listener; + + synchronized (mLock) { + listener = mServiceInterface; + + // If the service died/was disabled while the message for dispatching + // the accessibility event was propagating the listener may be null. + if (listener == null) { + return; + } + + // There are two ways we notify for events, throttled AND non-throttled. If we + // are not throttling, then messages come with events, which we handle with + // minimal fuss. + if (event == null) { + // We are throttling events, so we'll send the event for this type in + // mPendingEvents as long as it it's null. It can only null due to a race + // condition: + // + // 1) A binder thread calls notifyAccessibilityServiceDelayedLocked + // which posts a message for dispatching an event and stores the event + // in mPendingEvents. + // 2) The message is pulled from the queue by the handler on the service + // thread and this method is just about to acquire the lock. + // 3) Another binder thread acquires the lock in notifyAccessibilityEvent + // 4) notifyAccessibilityEvent recycles the event that this method was about + // to process, replaces it with a new one, and posts a second message + // 5) This method grabs the new event, processes it, and removes it from + // mPendingEvents + // 6) The second message dispatched in (4) arrives, but the event has been + // remvoved in (5). + event = mPendingEvents.get(eventType); + if (event == null) { + return; + } + mPendingEvents.remove(eventType); + } + if (mSecurityPolicy.canRetrieveWindowContentLocked(this)) { + event.setConnectionId(mId); + } else { + event.setSource((View) null); + } + event.setSealed(true); + } + + try { + listener.onAccessibilityEvent(event, serviceWantsEvent); + if (DEBUG) { + Slog.i(LOG_TAG, "Event " + event + " sent to " + listener); + } + } catch (RemoteException re) { + Slog.e(LOG_TAG, "Error during sending " + event + " to " + listener, re); + } finally { + event.recycle(); + } + } + + public void notifyGesture(int gestureId) { + mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE, + gestureId, 0).sendToTarget(); + } + + public void notifyClearAccessibilityNodeInfoCache() { + mInvocationHandler.sendEmptyMessage( + InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE); + } + + public void notifyMagnificationChangedLocked(@NonNull Region region, + float scale, float centerX, float centerY) { + mInvocationHandler + .notifyMagnificationChangedLocked(region, scale, centerX, centerY); + } + + public void notifySoftKeyboardShowModeChangedLocked(int showState) { + mInvocationHandler.notifySoftKeyboardShowModeChangedLocked(showState); + } + + public void notifyAccessibilityButtonClickedLocked() { + mInvocationHandler.notifyAccessibilityButtonClickedLocked(); + } + + public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) { + mInvocationHandler.notifyAccessibilityButtonAvailabilityChangedLocked(available); + } + + /** + * Called by the invocation handler to notify the service that the + * state of magnification has changed. + */ + private void notifyMagnificationChangedInternal(@NonNull Region region, + float scale, float centerX, float centerY) { + final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); + if (listener != null) { + try { + listener.onMagnificationChanged(region, scale, centerX, centerY); + } catch (RemoteException re) { + Slog.e(LOG_TAG, "Error sending magnification changes to " + mService, re); + } + } + } + + /** + * Called by the invocation handler to notify the service that the state of the soft + * keyboard show mode has changed. + */ + private void notifySoftKeyboardShowModeChangedInternal(int showState) { + final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); + if (listener != null) { + try { + listener.onSoftKeyboardShowModeChanged(showState); + } catch (RemoteException re) { + Slog.e(LOG_TAG, "Error sending soft keyboard show mode changes to " + mService, + re); + } + } + } + + private void notifyAccessibilityButtonClickedInternal() { + final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); + if (listener != null) { + try { + listener.onAccessibilityButtonClicked(); + } catch (RemoteException re) { + Slog.e(LOG_TAG, "Error sending accessibility button click to " + mService, re); + } + } + } + + private void notifyAccessibilityButtonAvailabilityChangedInternal(boolean available) { + // Only notify the service if it's not been notified or the state has changed + if (mReceivedAccessibilityButtonCallbackSinceBind + && (mLastAccessibilityButtonCallbackState == available)) { + return; + } + mReceivedAccessibilityButtonCallbackSinceBind = true; + mLastAccessibilityButtonCallbackState = available; + final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); + if (listener != null) { + try { + listener.onAccessibilityButtonAvailabilityChanged(available); + } catch (RemoteException re) { + Slog.e(LOG_TAG, + "Error sending accessibility button availability change to " + mService, + re); + } + } + } + + private void notifyGestureInternal(int gestureId) { + final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); + if (listener != null) { + try { + listener.onGesture(gestureId); + } catch (RemoteException re) { + Slog.e(LOG_TAG, "Error during sending gesture " + gestureId + + " to " + mService, re); + } + } + } + + private void notifyClearAccessibilityCacheInternal() { + final IAccessibilityServiceClient listener = getServiceInterfaceSafely(); + if (listener != null) { + try { + listener.clearAccessibilityCache(); + } catch (RemoteException re) { + Slog.e(LOG_TAG, "Error during requesting accessibility info cache" + + " to be cleared.", re); + } + } + } + + private IAccessibilityServiceClient getServiceInterfaceSafely() { + synchronized (mLock) { + return mServiceInterface; + } + } + + private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) { + if (accessibilityWindowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) { + return mSecurityPolicy.getActiveWindowId(); + } + return accessibilityWindowId; + } + + private int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) { + if (windowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) { + return mSecurityPolicy.mActiveWindowId; + } + if (windowId == AccessibilityWindowInfo.ANY_WINDOW_ID) { + if (focusType == AccessibilityNodeInfo.FOCUS_INPUT) { + return mSecurityPolicy.mFocusedWindowId; + } else if (focusType == AccessibilityNodeInfo.FOCUS_ACCESSIBILITY) { + return mSecurityPolicy.mAccessibilityFocusedWindowId; + } + } + return windowId; + } + + private final class InvocationHandler extends Handler { + public static final int MSG_ON_GESTURE = 1; + public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 2; + + private static final int MSG_ON_MAGNIFICATION_CHANGED = 5; + private static final int MSG_ON_SOFT_KEYBOARD_STATE_CHANGED = 6; + private static final int MSG_ON_ACCESSIBILITY_BUTTON_CLICKED = 7; + private static final int MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED = 8; + + private boolean mIsMagnificationCallbackEnabled = false; + private boolean mIsSoftKeyboardCallbackEnabled = false; + + public InvocationHandler(Looper looper) { + super(looper, null, true); + } + + @Override + public void handleMessage(Message message) { + final int type = message.what; + switch (type) { + case MSG_ON_GESTURE: { + final int gestureId = message.arg1; + notifyGestureInternal(gestureId); + } break; + + case MSG_CLEAR_ACCESSIBILITY_CACHE: { + notifyClearAccessibilityCacheInternal(); + } break; + + case MSG_ON_MAGNIFICATION_CHANGED: { + final SomeArgs args = (SomeArgs) message.obj; + final Region region = (Region) args.arg1; + final float scale = (float) args.arg2; + final float centerX = (float) args.arg3; + final float centerY = (float) args.arg4; + notifyMagnificationChangedInternal(region, scale, centerX, centerY); + args.recycle(); + } break; + + case MSG_ON_SOFT_KEYBOARD_STATE_CHANGED: { + final int showState = (int) message.arg1; + notifySoftKeyboardShowModeChangedInternal(showState); + } break; + + case MSG_ON_ACCESSIBILITY_BUTTON_CLICKED: { + notifyAccessibilityButtonClickedInternal(); + } break; + + case MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED: { + final boolean available = (message.arg1 != 0); + notifyAccessibilityButtonAvailabilityChangedInternal(available); + } break; + + default: { + throw new IllegalArgumentException("Unknown message: " + type); + } + } + } + + public void notifyMagnificationChangedLocked(@NonNull Region region, float scale, + float centerX, float centerY) { + if (!mIsMagnificationCallbackEnabled) { + // Callback is disabled, don't bother packing args. + return; + } + + final SomeArgs args = SomeArgs.obtain(); + args.arg1 = region; + args.arg2 = scale; + args.arg3 = centerX; + args.arg4 = centerY; + + final Message msg = obtainMessage(MSG_ON_MAGNIFICATION_CHANGED, args); + msg.sendToTarget(); + } + + public void setMagnificationCallbackEnabled(boolean enabled) { + mIsMagnificationCallbackEnabled = enabled; + } + + public void notifySoftKeyboardShowModeChangedLocked(int showState) { + if (!mIsSoftKeyboardCallbackEnabled) { + return; + } + + final Message msg = obtainMessage(MSG_ON_SOFT_KEYBOARD_STATE_CHANGED, showState, 0); + msg.sendToTarget(); + } + + public void setSoftKeyboardCallbackEnabled(boolean enabled) { + mIsSoftKeyboardCallbackEnabled = enabled; + } + + public void notifyAccessibilityButtonClickedLocked() { + final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_CLICKED); + msg.sendToTarget(); + } + + public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) { + final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED, + (available ? 1 : 0), 0); + msg.sendToTarget(); + } + } +} diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java index 7324b82351f6..c60647fada09 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java @@ -417,7 +417,8 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo final boolean triggerable = (mEnabledFeatures & FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER) != 0; mMagnificationGestureHandler = new MagnificationGestureHandler( - mContext, mAms, detectControlGestures, triggerable); + mContext, mAms.getMagnificationController(), + detectControlGestures, triggerable); addFirstEventHandler(mMagnificationGestureHandler); } diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index a59844d2462b..06c110de6db2 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -16,21 +16,20 @@ package com.android.server.accessibility; -import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT; -import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; +import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS; +import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS; import android.Manifest; import android.accessibilityservice.AccessibilityService; import android.accessibilityservice.AccessibilityServiceInfo; -import android.accessibilityservice.GestureDescription; import android.accessibilityservice.IAccessibilityServiceClient; import android.accessibilityservice.IAccessibilityServiceConnection; import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.ActivityManagerInternal; import android.app.AlertDialog; import android.app.PendingIntent; -import android.app.StatusBarManager; -import android.app.UiAutomation; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; @@ -39,9 +38,7 @@ import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.IntentFilter; -import android.content.ServiceConnection; import android.content.pm.PackageManager; -import android.content.pm.ParceledListSlice; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.UserInfo; @@ -51,7 +48,6 @@ import android.graphics.Rect; import android.graphics.Region; import android.hardware.display.DisplayManager; import android.hardware.fingerprint.IFingerprintService; -import android.hardware.input.InputManager; import android.media.AudioManagerInternal; import android.net.Uri; import android.os.Binder; @@ -81,8 +77,6 @@ import android.util.Slog; import android.util.SparseArray; import android.view.Display; import android.view.IWindow; -import android.view.InputDevice; -import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.MagnificationSpec; import android.view.View; @@ -104,12 +98,10 @@ import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.content.PackageMonitor; -import com.android.internal.os.SomeArgs; import com.android.internal.util.DumpUtils; import com.android.internal.util.IntPair; import com.android.server.LocalServices; import com.android.server.policy.AccessibilityShortcutController; -import com.android.server.statusbar.StatusBarManagerInternal; import org.xmlpull.v1.XmlPullParserException; @@ -117,7 +109,6 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -134,7 +125,8 @@ import java.util.function.Consumer; * event dispatch for {@link AccessibilityEvent}s generated across all processes * on the device. Events are dispatched to {@link AccessibilityService}s. */ -public class AccessibilityManagerService extends IAccessibilityManager.Stub { +public class AccessibilityManagerService extends IAccessibilityManager.Stub + implements AccessibilityClientConnection.SystemSupport { private static final boolean DEBUG = false; @@ -161,9 +153,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private static final String SET_PIP_ACTION_REPLACEMENT = "setPictureInPictureActionReplacingConnection"; - private static final ComponentName sFakeAccessibilityServiceComponentName = - new ComponentName("foo.bar", "FakeService"); - private static final String FUNCTION_DUMP = "dump"; private static final char COMPONENT_NAME_SEPARATOR = ':'; @@ -200,6 +189,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private final MainHandler mMainHandler; + private final GlobalActionPerformer mGlobalActionPerformer; + private MagnificationController mMagnificationController; private InteractionBridge mInteractionBridge; @@ -237,6 +228,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private final UserManager mUserManager; + private final UiAutomationManager mUiAutomationManager = new UiAutomationManager(); + private int mCurrentUserId = UserHandle.USER_SYSTEM; //TODO: Remove this hack @@ -263,11 +256,28 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); mSecurityPolicy = new SecurityPolicy(); mMainHandler = new MainHandler(mContext.getMainLooper()); + mGlobalActionPerformer = new GlobalActionPerformer(mContext, mWindowManagerService); + registerBroadcastReceivers(); new AccessibilityContentObserver(mMainHandler).register( context.getContentResolver()); } + @Override + public int getCurrentUserIdLocked() { + return mCurrentUserId; + } + + @Override + public boolean isAccessibilityButtonShown() { + return mIsAccessibilityButtonShown; + } + + @Nullable + public FingerprintGestureDispatcher getFingerprintGestureDispatcher() { + return mFingerprintGestureDispatcher; + } + private UserState getUserStateLocked(int userId) { UserState state = mUserStates.get(userId); if (state == null) { @@ -293,10 +303,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { // have different attributes, resolve info (does not support equals), // etc. Remove them then to force reload. userState.mInstalledServices.clear(); - if (!userState.isUiAutomationSuppressingOtherServices()) { - if (readConfigurationForUserStateLocked(userState)) { - onUserStateChangedLocked(userState); - } + if (readConfigurationForUserStateLocked(userState)) { + onUserStateChangedLocked(userState); } } } @@ -313,7 +321,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { UserState userState = getUserStateLocked(userId); boolean unboundAService = false; for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) { - Service boundService = userState.mBoundServices.get(i); + AccessibilityServiceConnection boundService = + userState.mBoundServices.get(i); String servicePkg = boundService.mComponentName.getPackageName(); if (servicePkg.equals(packageName)) { boundService.unbindLocked(); @@ -352,10 +361,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { Settings.Secure. TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, userState.mTouchExplorationGrantedServices, userId); - // We will update when the automation service dies. - if (!userState.isUiAutomationSuppressingOtherServices()) { - onUserStateChangedLocked(userState); - } + onUserStateChangedLocked(userState); return; } } @@ -386,10 +392,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { persistComponentNamesToSettingLocked( Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, userState.mEnabledServices, userId); - // We will update when the automation service dies. - if (!userState.isUiAutomationSuppressingOtherServices()) { - onUserStateChangedLocked(userState); - } + onUserStateChangedLocked(userState); } } } @@ -423,10 +426,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { // We will update when the automation service dies. synchronized (mLock) { UserState userState = getCurrentUserStateLocked(); - if (!userState.isUiAutomationSuppressingOtherServices()) { - if (readConfigurationForUserStateLocked(userState)) { - onUserStateChangedLocked(userState); - } + if (readConfigurationForUserStateLocked(userState)) { + onUserStateChangedLocked(userState); } } } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) { @@ -527,6 +528,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { synchronized (mLock) { notifyAccessibilityServicesDelayedLocked(event, false); notifyAccessibilityServicesDelayedLocked(event, true); + mUiAutomationManager.sendAccessibilityEventLocked(event); } } @@ -543,16 +545,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { // performs the current profile parent resolution. final int resolvedUserId = mSecurityPolicy .resolveCallingUserIdEnforcingPermissionsLocked(userId); - // The automation service is a fake one and should not be reported - // to clients as being installed - it really is not. - UserState userState = getUserStateLocked(resolvedUserId); - if (userState.mUiAutomationService != null) { - List<AccessibilityServiceInfo> installedServices = new ArrayList<>(); - installedServices.addAll(userState.mInstalledServices); - installedServices.remove(userState.mUiAutomationService.mAccessibilityServiceInfo); - return installedServices; - } - return userState.mInstalledServices; + return getUserStateLocked(resolvedUserId).mInstalledServices; } } @@ -568,18 +561,16 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { // The automation service can suppress other services. final UserState userState = getUserStateLocked(resolvedUserId); - if (userState.isUiAutomationSuppressingOtherServices()) { + if (mUiAutomationManager.suppressingAccessibilityServicesLocked()) { return Collections.emptyList(); } - final List<Service> services = userState.mBoundServices; + final List<AccessibilityServiceConnection> services = userState.mBoundServices; final int serviceCount = services.size(); final List<AccessibilityServiceInfo> result = new ArrayList<>(serviceCount); for (int i = 0; i < serviceCount; ++i) { - final Service service = services.get(i); - // Don't report the UIAutomation (fake service) - if (!sFakeAccessibilityServiceComponentName.equals(service.mComponentName) - && (service.mFeedbackType & feedbackType) != 0) { + final AccessibilityServiceConnection service = services.get(i); + if ((service.mFeedbackType & feedbackType) != 0) { result.add(service.mAccessibilityServiceInfo); } } @@ -600,11 +591,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { if (resolvedUserId != mCurrentUserId) { return; } - List<Service> services = getUserStateLocked(resolvedUserId).mBoundServices; + List<AccessibilityServiceConnection> services = + getUserStateLocked(resolvedUserId).mBoundServices; int numServices = services.size(); interfacesToInterrupt = new ArrayList<>(numServices); for (int i = 0; i < numServices; i++) { - Service service = services.get(i); + AccessibilityServiceConnection service = services.get(i); IBinder a11yServiceBinder = service.mService; IAccessibilityServiceClient a11yServiceInterface = service.mServiceInterface; if ((a11yServiceBinder != null) && (a11yServiceInterface != null)) { @@ -744,59 +736,19 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT, FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE); - accessibilityServiceInfo.setComponentName(sFakeAccessibilityServiceComponentName); - synchronized (mLock) { - UserState userState = getCurrentUserStateLocked(); - - if (userState.mUiAutomationService != null) { - throw new IllegalStateException("UiAutomationService " + serviceClient - + "already registered!"); - } - - try { - owner.linkToDeath(userState.mUiAutomationSerivceOnwerDeathRecipient, 0); - } catch (RemoteException re) { - Slog.e(LOG_TAG, "Couldn't register for the death of a" - + " UiTestAutomationService!", re); - return; - } - - userState.mUiAutomationServiceOwner = owner; - userState.mUiAutomationServiceClient = serviceClient; - userState.mUiAutomationFlags = flags; - userState.mInstalledServices.add(accessibilityServiceInfo); - if ((flags & UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) == 0) { - // Set the temporary state, and use it instead of settings - userState.mIsTouchExplorationEnabled = false; - userState.mIsDisplayMagnificationEnabled = false; - userState.mIsNavBarMagnificationEnabled = false; - userState.mIsAutoclickEnabled = false; - userState.mEnabledServices.clear(); - } - userState.mEnabledServices.add(sFakeAccessibilityServiceComponentName); - userState.mTouchExplorationGrantedServices.add(sFakeAccessibilityServiceComponentName); - - // Use the new state instead of settings. - onUserStateChangedLocked(userState); + mUiAutomationManager.registerUiTestAutomationServiceLocked(owner, serviceClient, + mContext, accessibilityServiceInfo, sIdCounter++, mMainHandler, mLock, + mSecurityPolicy, this, mWindowManagerService, mGlobalActionPerformer, flags); + onUserStateChangedLocked(getCurrentUserStateLocked()); } } @Override public void unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient) { synchronized (mLock) { - UserState userState = getCurrentUserStateLocked(); - // Automation service is not bound, so pretend it died to perform clean up. - if (userState.mUiAutomationService != null - && serviceClient != null - && userState.mUiAutomationService.mServiceInterface != null - && userState.mUiAutomationService.mServiceInterface.asBinder() - == serviceClient.asBinder()) { - userState.mUiAutomationService.binderDied(); - } else { - throw new IllegalStateException("UiAutomationService " + serviceClient - + " not registered!"); - } + mUiAutomationManager.unregisterUiTestAutomationServiceLocked(serviceClient); + onUserStateChangedLocked(getCurrentUserStateLocked()); } } @@ -813,11 +765,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { // Set the temporary state. UserState userState = getCurrentUserStateLocked(); - // This is a nop if UI automation is enabled. - if (userState.isUiAutomationSuppressingOtherServices()) { - return; - } - userState.mIsTouchExplorationEnabled = touchExplorationEnabled; userState.mIsDisplayMagnificationEnabled = false; userState.mIsNavBarMagnificationEnabled = false; @@ -847,7 +794,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { if (resolvedUserId != mCurrentUserId) { return null; } - if (mSecurityPolicy.findWindowById(windowId) == null) { + if (mSecurityPolicy.findA11yWindowInfoById(windowId) == null) { return null; } IBinder token = mGlobalWindowTokens.get(windowId); @@ -907,7 +854,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @VisibleForTesting public boolean notifyKeyEvent(KeyEvent event, int policyFlags) { synchronized (mLock) { - List<Service> boundServices = getCurrentUserStateLocked().mBoundServices; + List<AccessibilityServiceConnection> boundServices = + getCurrentUserStateLocked().mBoundServices; if (boundServices.isEmpty()) { return false; } @@ -947,6 +895,22 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } + @Override + public MotionEventInjector getMotionEventInjectorLocked() { + final long endMillis = SystemClock.uptimeMillis() + WAIT_MOTION_INJECTOR_TIMEOUT_MILLIS; + while ((mMotionEventInjector == null) && (SystemClock.uptimeMillis() < endMillis)) { + try { + mLock.wait(endMillis - SystemClock.uptimeMillis()); + } catch (InterruptedException ie) { + /* ignore */ + } + } + if (mMotionEventInjector == null) { + Slog.e(LOG_TAG, "MotionEventInjector installation timed out"); + } + return mMotionEventInjector; + } + /** * Gets a point within the accessibility focused node where we can send down * and up events to perform a click. @@ -1035,10 +999,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { mCurrentUserId = userId; UserState userState = getCurrentUserStateLocked(); - if (userState.mUiAutomationService != null) { - // Switching users disables the UI automation service. - userState.mUiAutomationService.binderDied(); - } readConfigurationForUserStateLocked(userState); // Even if reading did not yield change, we have to update @@ -1107,7 +1067,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { // enabled accessibility services. UserState state = getCurrentUserStateLocked(); for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { - Service service = state.mBoundServices.get(i); + AccessibilityServiceConnection service = state.mBoundServices.get(i); if (service.mRequestTouchExplorationMode && service.mIsDefault == isDefault) { service.notifyGesture(gestureId); return true; @@ -1119,7 +1079,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private void notifyClearAccessibilityCacheLocked() { UserState state = getCurrentUserStateLocked(); for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { - Service service = state.mBoundServices.get(i); + AccessibilityServiceConnection service = state.mBoundServices.get(i); service.notifyClearAccessibilityNodeInfoCache(); } } @@ -1128,7 +1088,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { float scale, float centerX, float centerY) { final UserState state = getCurrentUserStateLocked(); for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { - final Service service = state.mBoundServices.get(i); + final AccessibilityServiceConnection service = state.mBoundServices.get(i); service.notifyMagnificationChangedLocked(region, scale, centerX, centerY); } } @@ -1136,7 +1096,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private void notifySoftKeyboardShowModeChangedLocked(int showMode) { final UserState state = getCurrentUserStateLocked(); for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { - final Service service = state.mBoundServices.get(i); + final AccessibilityServiceConnection service = state.mBoundServices.get(i); service.notifySoftKeyboardShowModeChangedLocked(showMode); } } @@ -1146,7 +1106,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { int potentialTargets = state.mIsNavBarMagnificationEnabled ? 1 : 0; for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { - final Service service = state.mBoundServices.get(i); + final AccessibilityServiceConnection service = state.mBoundServices.get(i); if (service.mRequestAccessibilityButton) { potentialTargets++; } @@ -1162,7 +1122,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return; } else { for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { - final Service service = state.mBoundServices.get(i); + final AccessibilityServiceConnection service = state.mBoundServices.get(i); if (service.mRequestAccessibilityButton) { service.notifyAccessibilityButtonClickedLocked(); return; @@ -1181,7 +1141,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return; } else { for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { - final Service service = state.mBoundServices.get(i); + final AccessibilityServiceConnection service = state.mBoundServices.get(i); if (service.mRequestAccessibilityButton && (service.mComponentName.equals( state.mServiceAssignedToAccessibilityButton))) { service.notifyAccessibilityButtonClickedLocked(); @@ -1199,10 +1159,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { final UserState state = getCurrentUserStateLocked(); mIsAccessibilityButtonShown = available; for (int i = state.mBoundServices.size() - 1; i >= 0; i--) { - final Service service = state.mBoundServices.get(i); - if (service.mRequestAccessibilityButton) { - service.notifyAccessibilityButtonAvailabilityChangedLocked( - service.isAccessibilityButtonAvailableLocked(state)); + final AccessibilityServiceConnection clientConnection = state.mBoundServices.get(i); + if (clientConnection.mRequestAccessibilityButton) { + clientConnection.notifyAccessibilityButtonAvailabilityChangedLocked( + clientConnection.isAccessibilityButtonAvailableLocked(state)); } } } @@ -1278,9 +1238,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { if (!mTempComponentNameSet.equals(userState.mEnabledServices)) { userState.mEnabledServices.clear(); userState.mEnabledServices.addAll(mTempComponentNameSet); - if (userState.mUiAutomationService != null) { - userState.mEnabledServices.add(sFakeAccessibilityServiceComponentName); - } mTempComponentNameSet.clear(); return true; } @@ -1316,16 +1273,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { try { UserState state = getCurrentUserStateLocked(); for (int i = 0, count = state.mBoundServices.size(); i < count; i++) { - Service service = state.mBoundServices.get(i); + AccessibilityServiceConnection service = state.mBoundServices.get(i); if (service.mIsDefault == isDefault) { - if (doesServiceWantEventLocked(service, event)) { - service.notifyAccessibilityEvent(event, true); - } else if (service.mUsesAccessibilityCache - && (AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK - & event.getEventType()) != 0) { - service.notifyAccessibilityEvent(event, false); - } + service.notifyAccessibilityEvent(event); } } } catch (IndexOutOfBoundsException oobe) { @@ -1335,42 +1286,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } - private void addServiceLocked(Service service, UserState userState) { - try { - if (!userState.mBoundServices.contains(service)) { - service.onAdded(); - userState.mBoundServices.add(service); - userState.mComponentNameToServiceMap.put(service.mComponentName, service); - scheduleNotifyClientsOfServicesStateChange(userState); - } - } catch (RemoteException re) { - /* do nothing */ - } - } - - /** - * Removes a service. - * - * @param service The service. - */ - private void removeServiceLocked(Service service, UserState userState) { - userState.mBoundServices.remove(service); - service.onRemoved(); - // It may be possible to bind a service twice, which confuses the map. Rebuild the map - // to make sure we can still reach a service - userState.mComponentNameToServiceMap.clear(); - for (int i = 0; i < userState.mBoundServices.size(); i++) { - Service boundService = userState.mBoundServices.get(i); - userState.mComponentNameToServiceMap.put(boundService.mComponentName, boundService); - } - scheduleNotifyClientsOfServicesStateChange(userState); - } - private void updateRelevantEventsLocked(UserState userState) { int relevantEventTypes = AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK; - for (Service service : userState.mBoundServices) { + for (AccessibilityServiceConnection service : userState.mBoundServices) { relevantEventTypes |= service.mEventTypes; } + relevantEventTypes |= mUiAutomationManager.getRequestedEventMaskLocked(); int finalRelevantEventTypes = relevantEventTypes; if (userState.mLastSentRelevantEventTypes != finalRelevantEventTypes) { @@ -1395,48 +1316,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { userState.mUserClients.broadcast(clientAction); } - /** - * Determines if given event can be dispatched to a service based on the package of the - * event source. Specifically, a service is notified if it is interested in events from the - * package. - * - * @param service The potential receiver. - * @param event The event. - * @return True if the listener should be notified, false otherwise. - */ - private boolean doesServiceWantEventLocked(Service service, AccessibilityEvent event) { - - if (!service.canReceiveEventsLocked()) { - return false; - } - - if ((event.getWindowId() != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) - && !event.isImportantForAccessibility() - && (service.mFetchFlags & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) - == 0) { - return false; - } - - int eventType = event.getEventType(); - if ((service.mEventTypes & eventType) != eventType) { - return false; - } - - Set<String> packageNames = service.mPackageNames; - String packageName = (event.getPackageName() != null) - ? event.getPackageName().toString() : null; - - return (packageNames.isEmpty() || packageNames.contains(packageName)); - } - private void unbindAllServicesLocked(UserState userState) { - List<Service> services = userState.mBoundServices; - for (int i = 0, count = services.size(); i < count; i++) { - Service service = services.get(i); - if (service.unbindLocked()) { - i--; - count--; - } + List<AccessibilityServiceConnection> services = userState.mBoundServices; + for (int count = services.size(); count > 1; count--) { + // When the service is unbound, it disappears from the list, so there's no need to + // keep track of the index + services.get(0).unbindLocked(); } } @@ -1486,14 +1371,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } - /** - * Persists the component names in the specified setting in a - * colon separated fashion. - * - * @param settingName The setting name. - * @param componentNames The component names. - */ - private void persistComponentNamesToSettingLocked(String settingName, + @Override + public void persistComponentNamesToSettingLocked(String settingName, Set<ComponentName> componentNames, int userId) { StringBuilder builder = new StringBuilder(); for (ComponentName componentName : componentNames) { @@ -1512,7 +1391,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } private void updateServicesLocked(UserState userState) { - Map<ComponentName, Service> componentNameToServiceMap = + Map<ComponentName, AccessibilityServiceConnection> componentNameToServiceMap = userState.mComponentNameToServiceMap; boolean isUnlockingOrUnlocked = LocalServices.getService(UserManagerInternal.class) .isUserUnlockingOrUnlocked(userState.mUserId); @@ -1522,7 +1401,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { ComponentName componentName = ComponentName.unflattenFromString( installedService.getId()); - Service service = componentNameToServiceMap.get(componentName); + AccessibilityServiceConnection service = componentNameToServiceMap.get(componentName); // Ignore non-encryption-aware services until user is unlocked if (!isUnlockingOrUnlocked && !installedService.isDirectBootAware()) { @@ -1534,9 +1413,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { if (userState.mBindingServices.contains(componentName)) { continue; } - if (userState.mEnabledServices.contains(componentName)) { + if (userState.mEnabledServices.contains(componentName) + && !mUiAutomationManager.suppressingAccessibilityServicesLocked()) { if (service == null) { - service = new Service(userState.mUserId, componentName, installedService); + service = new AccessibilityServiceConnection(userState, mContext, componentName, + installedService, sIdCounter++, mMainHandler, mLock, mSecurityPolicy, + this, mWindowManagerService, mGlobalActionPerformer); } else if (userState.mBoundServices.contains(service)) { continue; } @@ -1597,6 +1479,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } private void updateInputFilter(UserState userState) { + if (mUiAutomationManager.suppressingAccessibilityServicesLocked()) return; + boolean setInputFilter = false; AccessibilityInputFilter inputFilter = null; synchronized (mLock) { @@ -1611,8 +1495,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { flags |= AccessibilityInputFilter.FLAG_FEATURE_CONTROL_SCREEN_MAGNIFIER; } // Touch exploration without accessibility makes no sense. - if (userState.isHandlingAccessibilityEvents() - && userState.mIsTouchExplorationEnabled) { + if (userState.isHandlingAccessibilityEvents() && userState.mIsTouchExplorationEnabled) { flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION; } if (userState.mIsFilterKeyEventsEnabled) { @@ -1649,13 +1532,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } - private void showEnableTouchExplorationDialog(final Service service) { + private void showEnableTouchExplorationDialog(final AccessibilityServiceConnection service) { synchronized (mLock) { - String label = service.mResolveInfo.loadLabel( - mContext.getPackageManager()).toString(); + String label = service.getServiceInfo().getResolveInfo() + .loadLabel(mContext.getPackageManager()).toString(); - final UserState state = getCurrentUserStateLocked(); - if (state.mIsTouchExplorationEnabled) { + final UserState userState = getCurrentUserStateLocked(); + if (userState.mIsTouchExplorationEnabled) { return; } if (mEnableTouchExplorationDialog != null @@ -1668,18 +1551,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @Override public void onClick(DialogInterface dialog, int which) { // The user allowed the service to toggle touch exploration. - state.mTouchExplorationGrantedServices.add(service.mComponentName); + userState.mTouchExplorationGrantedServices.add(service.mComponentName); persistComponentNamesToSettingLocked( Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, - state.mTouchExplorationGrantedServices, state.mUserId); + userState.mTouchExplorationGrantedServices, userState.mUserId); // Enable touch exploration. - UserState userState = getUserStateLocked(service.mUserId); userState.mIsTouchExplorationEnabled = true; final long identity = Binder.clearCallingIdentity(); try { Settings.Secure.putIntForUser(mContext.getContentResolver(), Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1, - service.mUserId); + userState.mUserId); } finally { Binder.restoreCallingIdentity(identity); } @@ -1742,10 +1624,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { // is typically the one that operates with interactive windows, So, // this is fine. Note that to allow a service to work across windows // we have to allow accessibility focus stay in any of them. Sigh... - List<Service> boundServices = userState.mBoundServices; + List<AccessibilityServiceConnection> boundServices = userState.mBoundServices; final int boundServiceCount = boundServices.size(); for (int i = 0; i < boundServiceCount; i++) { - Service boundService = boundServices.get(i); + AccessibilityServiceConnection boundService = boundServices.get(i); if (boundService.canRetrieveInteractiveWindowsLocked()) { userState.mAccessibilityFocusOnlyInActiveWindow = false; return; @@ -1761,20 +1643,25 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { // binding we do an update pass after each bind event, so we run this // code and register the callback if needed. - List<Service> boundServices = userState.mBoundServices; + boolean observingWindows = mUiAutomationManager.canRetrieveInteractiveWindowsLocked(); + List<AccessibilityServiceConnection> boundServices = userState.mBoundServices; final int boundServiceCount = boundServices.size(); - for (int i = 0; i < boundServiceCount; i++) { - Service boundService = boundServices.get(i); + for (int i = 0; !observingWindows && (i < boundServiceCount); i++) { + AccessibilityServiceConnection boundService = boundServices.get(i); if (boundService.canRetrieveInteractiveWindowsLocked()) { - if (mWindowsForAccessibilityCallback == null) { - mWindowsForAccessibilityCallback = new WindowsForAccessibilityCallback(); - mWindowManagerService.setWindowsForAccessibilityCallback( - mWindowsForAccessibilityCallback); - } - return; + observingWindows = true; } } + if (observingWindows) { + if (mWindowsForAccessibilityCallback == null) { + mWindowsForAccessibilityCallback = new WindowsForAccessibilityCallback(); + mWindowManagerService.setWindowsForAccessibilityCallback( + mWindowsForAccessibilityCallback); + } + return; + } + if (mWindowsForAccessibilityCallback != null) { mWindowsForAccessibilityCallback = null; mWindowManagerService.setWindowsForAccessibilityCallback(null); @@ -1808,7 +1695,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private void updatePerformGesturesLocked(UserState userState) { final int serviceCount = userState.mBoundServices.size(); for (int i = 0; i < serviceCount; i++) { - Service service = userState.mBoundServices.get(i); + AccessibilityServiceConnection service = userState.mBoundServices.get(i); if ((service.mAccessibilityServiceInfo.getCapabilities() & AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0) { userState.mIsPerformGesturesEnabled = true; @@ -1821,7 +1708,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private void updateFilterKeyEventsLocked(UserState userState) { final int serviceCount = userState.mBoundServices.size(); for (int i = 0; i < serviceCount; i++) { - Service service = userState.mBoundServices.get(i); + AccessibilityServiceConnection service = userState.mBoundServices.get(i); if (service.mRequestFilterKeyEvents && (service.mAccessibilityServiceInfo.getCapabilities() & AccessibilityServiceInfo @@ -1848,10 +1735,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private void updateAccessibilityEnabledSetting(UserState userState) { final long identity = Binder.clearCallingIdentity(); + final boolean isA11yEnabled = mUiAutomationManager.isUiAutomationRunningLocked() + || userState.isHandlingAccessibilityEvents(); try { Settings.Secure.putIntForUser(mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED, - userState.isHandlingAccessibilityEvents() ? 1 : 0, + (isA11yEnabled) ? 1 : 0, userState.mUserId); } finally { Binder.restoreCallingIdentity(identity); @@ -1924,11 +1813,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } private void updateTouchExplorationLocked(UserState userState) { - boolean enabled = false; + boolean enabled = mUiAutomationManager.isTouchExplorationEnabledLocked(); final int serviceCount = userState.mBoundServices.size(); for (int i = 0; i < serviceCount; i++) { - Service service = userState.mBoundServices.get(i); - if (canRequestAndRequestsTouchExplorationLocked(service)) { + AccessibilityServiceConnection service = userState.mBoundServices.get(i); + if (canRequestAndRequestsTouchExplorationLocked(service, userState)) { enabled = true; break; } @@ -2030,21 +1919,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } - private boolean canRequestAndRequestsTouchExplorationLocked(Service service) { + private boolean canRequestAndRequestsTouchExplorationLocked( + AccessibilityServiceConnection service, UserState userState) { // Service not ready or cannot request the feature - well nothing to do. if (!service.canReceiveEventsLocked() || !service.mRequestTouchExplorationMode) { return false; } - // UI test automation service can always enable it. - if (service.mIsAutomation) { - return true; - } - if (service.mResolveInfo.serviceInfo.applicationInfo.targetSdkVersion + if (service.getServiceInfo().getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1) { // Up to JB-MR1 we had a white list with services that can enable touch // exploration. When a service is first started we show a dialog to the // use to get a permission to white list the service. - UserState userState = getUserStateLocked(service.mUserId); if (userState.mTouchExplorationGrantedServices.contains(service.mComponentName)) { return true; } else if (mEnableTouchExplorationDialog == null @@ -2078,8 +1963,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return; } - if (userState.mIsDisplayMagnificationEnabled || userState.mIsNavBarMagnificationEnabled - || userHasListeningMagnificationServicesLocked(userState)) { + if (!mUiAutomationManager.suppressingAccessibilityServicesLocked() + && (userState.mIsDisplayMagnificationEnabled + || userState.mIsNavBarMagnificationEnabled + || userHasListeningMagnificationServicesLocked(userState))) { // Initialize the magnification controller if necessary getMagnificationController(); mMagnificationController.register(); @@ -2093,9 +1980,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { * controlling magnification. */ private boolean userHasMagnificationServicesLocked(UserState userState) { - final List<Service> services = userState.mBoundServices; + final List<AccessibilityServiceConnection> services = userState.mBoundServices; for (int i = 0, count = services.size(); i < count; i++) { - final Service service = services.get(i); + final AccessibilityServiceConnection service = services.get(i); if (mSecurityPolicy.canControlMagnification(service)) { return true; } @@ -2108,11 +1995,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { * controlling magnification and are actively listening for magnification updates. */ private boolean userHasListeningMagnificationServicesLocked(UserState userState) { - final List<Service> services = userState.mBoundServices; + final List<AccessibilityServiceConnection> services = userState.mBoundServices; for (int i = 0, count = services.size(); i < count; i++) { - final Service service = services.get(i); + final AccessibilityServiceConnection service = services.get(i); if (mSecurityPolicy.canControlMagnification(service) - && service.mInvocationHandler.mIsMagnificationCallbackEnabled) { + && service.isMagnificationCallbackEnabled()) { return true; } } @@ -2124,7 +2011,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { // Only check whether we need to reset the soft keyboard mode if it is not set to the // default. if ((userId == mCurrentUserId) && (userState.mSoftKeyboardShowMode != 0)) { - // Check whether the last Accessibility Service that changed the soft keyboard mode to + // Check whether the last AccessibilityService that changed the soft keyboard mode to // something other than the default is still enabled and, if not, remove flag and // reset to the default soft keyboard behavior. boolean serviceChangingSoftKeyboardModeIsEnabled = @@ -2148,7 +2035,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } private void updateFingerprintGestureHandling(UserState userState) { - final List<Service> services; + final List<AccessibilityServiceConnection> services; synchronized (mLock) { services = userState.mBoundServices; if ((mFingerprintGestureDispatcher == null) @@ -2181,7 +2068,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private void updateAccessibilityButtonTargetsLocked(UserState userState) { for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) { - final Service service = userState.mBoundServices.get(i); + final AccessibilityServiceConnection service = userState.mBoundServices.get(i); if (service.mRequestAccessibilityButton) { service.notifyAccessibilityButtonAvailabilityChangedLocked( service.isAccessibilityButtonAvailableLocked(userState)); @@ -2190,7 +2077,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } @GuardedBy("mLock") - private MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId) { + @Override + public MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId) { IBinder windowToken = mGlobalWindowTokens.get(windowId); if (windowToken == null) { windowToken = getCurrentUserStateLocked().mWindowTokens.get(windowId); @@ -2202,7 +2090,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return null; } - private KeyEventDispatcher getKeyEventDispatcher() { + @Override + public KeyEventDispatcher getKeyEventDispatcher() { if (mKeyEventDispatcher == null) { mKeyEventDispatcher = new KeyEventDispatcher( mMainHandler, MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER, mLock, @@ -2211,6 +2100,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return mKeyEventDispatcher; } + @Override + public PendingIntent getPendingIntentActivity(Context context, int requestCode, Intent intent, + int flags) { + return PendingIntent.getActivity(context, requestCode, intent, flags); + } /** * AIDL-exposed method to be called when the accessibility shortcut is enabled. Requires * permission to write secure settings, since someone with that permission can enable @@ -2314,9 +2208,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { pw.append(", navBarMagnificationEnabled=" + userState.mIsNavBarMagnificationEnabled); pw.append(", autoclickEnabled=" + userState.mIsAutoclickEnabled); - if (userState.mUiAutomationService != null) { + if (mUiAutomationManager.isUiAutomationRunningLocked()) { pw.append(", "); - userState.mUiAutomationService.dump(fd, pw, args); + mUiAutomationManager.dumpUiAutomationService(fd, pw, args); pw.println(); } pw.append("}"); @@ -2329,7 +2223,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { pw.println(); pw.append(" "); } - Service service = userState.mBoundServices.get(j); + AccessibilityServiceConnection service = userState.mBoundServices.get(j); service.dump(fd, pw, args); } pw.println("}]"); @@ -2380,7 +2274,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } - private final class MainHandler extends Handler { + final class MainHandler extends Handler { public static final int MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER = 1; public static final int MSG_SEND_STATE_TO_CLIENTS = 2; public static final int MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER = 3; @@ -2394,6 +2288,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { public static final int MSG_SEND_RELEVANT_EVENTS_CHANGED_TO_CLIENTS = 12; public static final int MSG_SEND_ACCESSIBILITY_BUTTON_TO_INPUT_FILTER = 13; public static final int MSG_SHOW_ACCESSIBILITY_BUTTON_CHOOSER = 14; + public static final int MSG_INIT_SERVICE = 15; public MainHandler(Looper looper) { super(looper); @@ -2446,7 +2341,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } break; case MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG: { - Service service = (Service) msg.obj; + AccessibilityServiceConnection service = + (AccessibilityServiceConnection) msg.obj; showEnableTouchExplorationDialog(service); } break; @@ -2492,6 +2388,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { case MSG_SHOW_ACCESSIBILITY_BUTTON_CHOOSER: { showAccessibilityButtonTargetSelection(); } break; + + case MSG_INIT_SERVICE: { + final AccessibilityServiceConnection service = + (AccessibilityServiceConnection) msg.obj; + service.initializeService(); + } break; } } @@ -2561,7 +2463,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return -1; } - private void ensureWindowsAvailableTimed() { + @Override + public void ensureWindowsAvailableTimed() { synchronized (mLock) { if (mSecurityPolicy.mWindows != null) { return; @@ -2594,7 +2497,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } - MagnificationController getMagnificationController() { + @Override + public MagnificationController getMagnificationController() { synchronized (mLock) { if (mMagnificationController == null) { mMagnificationController = new MagnificationController(mContext, this, mLock); @@ -2604,1586 +2508,96 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } - /** - * This class represents an accessibility service. It stores all per service - * data required for the service management, provides API for starting/stopping the - * service and is responsible for adding/removing the service in the data structures - * for service management. The class also exposes configuration interface that is - * passed to the service it represents as soon it is bound. It also serves as the - * connection for the service. - */ - class Service extends IAccessibilityServiceConnection.Stub - implements ServiceConnection, DeathRecipient, KeyEventDispatcher.KeyEventFilter, - FingerprintGestureDispatcher.FingerprintGestureClient { - - final int mUserId; - - int mId = 0; - - AccessibilityServiceInfo mAccessibilityServiceInfo; - - // The service that's bound to this instance. Whenever this value is non-null, this - // object is registered as a death recipient - IBinder mService; - - IAccessibilityServiceClient mServiceInterface; - - int mEventTypes; - - int mFeedbackType; - - Set<String> mPackageNames = new HashSet<>(); - - boolean mIsDefault; - - boolean mRequestTouchExplorationMode; - - boolean mRequestFilterKeyEvents; - - boolean mRetrieveInteractiveWindows; - - boolean mCaptureFingerprintGestures; - - boolean mRequestAccessibilityButton; - - boolean mReceivedAccessibilityButtonCallbackSinceBind; - - boolean mLastAccessibilityButtonCallbackState; - - int mFetchFlags; - - long mNotificationTimeout; - - ComponentName mComponentName; - - Intent mIntent; - - boolean mIsAutomation; - - final ResolveInfo mResolveInfo; - - final IBinder mOverlayWindowToken = new Binder(); - - // the events pending events to be dispatched to this service - final SparseArray<AccessibilityEvent> mPendingEvents = - new SparseArray<>(); - - boolean mWasConnectedAndDied; - - /** Whether this service relies on its {@link AccessibilityCache} being up to date */ - boolean mUsesAccessibilityCache = false; - - // Handler only for dispatching accessibility events since we use event - // types as message types allowing us to remove messages per event type. - public Handler mEventDispatchHandler = new Handler(mMainHandler.getLooper()) { - @Override - public void handleMessage(Message message) { - final int eventType = message.what; - AccessibilityEvent event = (AccessibilityEvent) message.obj; - boolean serviceWantsEvent = message.arg1 != 0; - notifyAccessibilityEventInternal(eventType, event, serviceWantsEvent); - } - }; - - // Handler for scheduling method invocations on the main thread. - public final InvocationHandler mInvocationHandler = new InvocationHandler( - mMainHandler.getLooper()); - - public Service(int userId, ComponentName componentName, - AccessibilityServiceInfo accessibilityServiceInfo) { - mUserId = userId; - mResolveInfo = accessibilityServiceInfo.getResolveInfo(); - mId = sIdCounter++; - mComponentName = componentName; - mAccessibilityServiceInfo = accessibilityServiceInfo; - mIsAutomation = (sFakeAccessibilityServiceComponentName.equals(componentName)); - if (!mIsAutomation) { - mIntent = new Intent().setComponent(mComponentName); - mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL, - com.android.internal.R.string.accessibility_binding_label); - final long idendtity = Binder.clearCallingIdentity(); - try { - mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( - mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0)); - } finally { - Binder.restoreCallingIdentity(idendtity); - } - } - setDynamicallyConfigurableProperties(accessibilityServiceInfo); - } - - @Override - public boolean onKeyEvent(KeyEvent keyEvent, int sequenceNumber) { - if (!mRequestFilterKeyEvents || (mServiceInterface == null)) { - return false; - } - if((mAccessibilityServiceInfo.getCapabilities() - & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) == 0) { - return false; - } - try { - mServiceInterface.onKeyEvent(keyEvent, sequenceNumber); - } catch (RemoteException e) { - return false; - } - return true; - } - - @Override - public boolean isCapturingFingerprintGestures() { - return (mServiceInterface != null) - && mSecurityPolicy.canCaptureFingerprintGestures(this) - && mCaptureFingerprintGestures; - } - - @Override - public void onFingerprintGestureDetectionActiveChanged(boolean active) { - if (!isCapturingFingerprintGestures()) { - return; - } - IAccessibilityServiceClient serviceInterface; - synchronized (mLock) { - serviceInterface = mServiceInterface; - } - if (serviceInterface != null) { - try { - mServiceInterface.onFingerprintCapturingGesturesChanged(active); - } catch (RemoteException e) { - } - } - } - - @Override - public void onFingerprintGesture(int gesture) { - if (!isCapturingFingerprintGestures()) { - return; - } - IAccessibilityServiceClient serviceInterface; - synchronized (mLock) { - serviceInterface = mServiceInterface; - } - if (serviceInterface != null) { - try { - mServiceInterface.onFingerprintGesture(gesture); - } catch (RemoteException e) { - } - } - } - - public void setDynamicallyConfigurableProperties(AccessibilityServiceInfo info) { - mEventTypes = info.eventTypes; - mFeedbackType = info.feedbackType; - String[] packageNames = info.packageNames; - if (packageNames != null) { - mPackageNames.addAll(Arrays.asList(packageNames)); - } - mNotificationTimeout = info.notificationTimeout; - mIsDefault = (info.flags & DEFAULT) != 0; - - if (mIsAutomation || info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion - >= Build.VERSION_CODES.JELLY_BEAN) { - if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) { - mFetchFlags |= AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; - } else { - mFetchFlags &= ~AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; - } - } - - if ((info.flags & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0) { - mFetchFlags |= AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS; - } else { - mFetchFlags &= ~AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS; - } - - mRequestTouchExplorationMode = (info.flags - & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0; - mRequestFilterKeyEvents = (info.flags - & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0; - mRetrieveInteractiveWindows = (info.flags - & AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS) != 0; - mCaptureFingerprintGestures = (info.flags - & AccessibilityServiceInfo.FLAG_REQUEST_FINGERPRINT_GESTURES) != 0; - mRequestAccessibilityButton = (info.flags - & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0; - } - - /** - * Binds to the accessibility service. - * - * @return True if binding is successful. - */ - public boolean bindLocked() { - UserState userState = getUserStateLocked(mUserId); - if (!mIsAutomation) { - final long identity = Binder.clearCallingIdentity(); - try { - if (mService == null && mContext.bindServiceAsUser( - mIntent, this, - Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, - new UserHandle(mUserId))) { - userState.mBindingServices.add(mComponentName); - } - } finally { - Binder.restoreCallingIdentity(identity); - } - } else { - userState.mBindingServices.add(mComponentName); - mMainHandler.post(new Runnable() { - @Override - public void run() { - // Simulate asynchronous connection since in onServiceConnected - // we may modify the state data in case of an error but bind is - // called while iterating over the data and bad things can happen. - onServiceConnected(mComponentName, - userState.mUiAutomationServiceClient.asBinder()); - } - }); - userState.mUiAutomationService = this; - } - return false; - } - - /** - * Unbinds from the accessibility service and removes it from the data - * structures for service management. - * - * @return True if unbinding is successful. - */ - public boolean unbindLocked() { - UserState userState = getUserStateLocked(mUserId); - getKeyEventDispatcher().flush(this); - if (!mIsAutomation) { - mContext.unbindService(this); - } else { - userState.destroyUiAutomationService(); - } - removeServiceLocked(this, userState); - resetLocked(); - return true; - } - - @Override - public void disableSelf() { - synchronized(mLock) { - UserState userState = getUserStateLocked(mUserId); - if (userState.mEnabledServices.remove(mComponentName)) { - final long identity = Binder.clearCallingIdentity(); - try { - persistComponentNamesToSettingLocked( - Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, - userState.mEnabledServices, mUserId); - } finally { - Binder.restoreCallingIdentity(identity); - } - onUserStateChangedLocked(userState); - } - } - } - - public boolean canReceiveEventsLocked() { - return (mEventTypes != 0 && mFeedbackType != 0 && mService != null); - } - - @Override - public void setOnKeyEventResult(boolean handled, int sequence) { - getKeyEventDispatcher().setOnKeyEventResult(this, handled, sequence); - } - - @Override - public AccessibilityServiceInfo getServiceInfo() { - synchronized (mLock) { - return mAccessibilityServiceInfo; - } - } - - public boolean canRetrieveInteractiveWindowsLocked() { - return mSecurityPolicy.canRetrieveWindowContentLocked(this) - && mRetrieveInteractiveWindows; - } - - @Override - public void setServiceInfo(AccessibilityServiceInfo info) { - final long identity = Binder.clearCallingIdentity(); - try { - synchronized (mLock) { - // If the XML manifest had data to configure the service its info - // should be already set. In such a case update only the dynamically - // configurable properties. - AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo; - if (oldInfo != null) { - oldInfo.updateDynamicallyConfigurableProperties(info); - setDynamicallyConfigurableProperties(oldInfo); - } else { - setDynamicallyConfigurableProperties(info); - } - UserState userState = getUserStateLocked(mUserId); - onUserStateChangedLocked(userState); - scheduleNotifyClientsOfServicesStateChange(userState); - } - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public void onServiceConnected(ComponentName componentName, IBinder service) { - synchronized (mLock) { - if (mService != service) { - if (mService != null) { - mService.unlinkToDeath(this, 0); - } - mService = service; - try { - mService.linkToDeath(this, 0); - } catch (RemoteException re) { - Slog.e(LOG_TAG, "Failed registering death link"); - binderDied(); - return; - } - } - mServiceInterface = IAccessibilityServiceClient.Stub.asInterface(service); - UserState userState = getUserStateLocked(mUserId); - addServiceLocked(this, userState); - if (userState.mBindingServices.contains(mComponentName) || mWasConnectedAndDied) { - userState.mBindingServices.remove(mComponentName); - mWasConnectedAndDied = false; - try { - mServiceInterface.init(this, mId, mOverlayWindowToken); - onUserStateChangedLocked(userState); - } catch (RemoteException re) { - Slog.w(LOG_TAG, "Error while setting connection for service: " - + service, re); - binderDied(); - } - } else { - binderDied(); - } - } - } - - private boolean isCalledForCurrentUserLocked() { - // We treat calls from a profile as if made by its parent as profiles - // share the accessibility state of the parent. The call below - // performs the current profile parent resolution. - final int resolvedUserId = mSecurityPolicy - .resolveCallingUserIdEnforcingPermissionsLocked(UserHandle.USER_CURRENT); - return resolvedUserId == mCurrentUserId; - } - - @Override - public List<AccessibilityWindowInfo> getWindows() { - ensureWindowsAvailableTimed(); - synchronized (mLock) { - if (!isCalledForCurrentUserLocked()) { - return null; - } - final boolean permissionGranted = - mSecurityPolicy.canRetrieveWindowsLocked(this); - if (!permissionGranted) { - return null; - } - if (mSecurityPolicy.mWindows == null) { - return null; - } - List<AccessibilityWindowInfo> windows = new ArrayList<>(); - final int windowCount = mSecurityPolicy.mWindows.size(); - for (int i = 0; i < windowCount; i++) { - AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(i); - AccessibilityWindowInfo windowClone = - AccessibilityWindowInfo.obtain(window); - windowClone.setConnectionId(mId); - windows.add(windowClone); - } - return windows; - } - } - - @Override - public AccessibilityWindowInfo getWindow(int windowId) { - ensureWindowsAvailableTimed(); - synchronized (mLock) { - if (!isCalledForCurrentUserLocked()) { - return null; - } - final boolean permissionGranted = - mSecurityPolicy.canRetrieveWindowsLocked(this); - if (!permissionGranted) { - return null; - } - AccessibilityWindowInfo window = mSecurityPolicy.findWindowById(windowId); - if (window != null) { - AccessibilityWindowInfo windowClone = AccessibilityWindowInfo.obtain(window); - windowClone.setConnectionId(mId); - return windowClone; - } - return null; - } - } - - @Override - public boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId, - long accessibilityNodeId, String viewIdResName, int interactionId, - IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) - throws RemoteException { - final int resolvedWindowId; - IAccessibilityInteractionConnection connection = null; - Region partialInteractiveRegion = Region.obtain(); - MagnificationSpec spec; - synchronized (mLock) { - mUsesAccessibilityCache = true; - if (!isCalledForCurrentUserLocked()) { - return false; - } - resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); - final boolean permissionGranted = - mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); - if (!permissionGranted) { - return false; - } else { - connection = getConnectionLocked(resolvedWindowId); - if (connection == null) { - return false; - } - } - if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( - resolvedWindowId, partialInteractiveRegion)) { - partialInteractiveRegion.recycle(); - partialInteractiveRegion = null; - } - spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); - } - final int interrogatingPid = Binder.getCallingPid(); - callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, - interrogatingPid, interrogatingTid); - final long identityToken = Binder.clearCallingIdentity(); - try { - connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId, viewIdResName, - partialInteractiveRegion, interactionId, callback, mFetchFlags, - interrogatingPid, interrogatingTid, spec); - return true; - } catch (RemoteException re) { - if (DEBUG) { - Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId()."); - } - } finally { - Binder.restoreCallingIdentity(identityToken); - // Recycle if passed to another process. - if (partialInteractiveRegion != null && Binder.isProxy(connection)) { - partialInteractiveRegion.recycle(); - } - } - return false; - } - - @Override - public boolean findAccessibilityNodeInfosByText(int accessibilityWindowId, - long accessibilityNodeId, String text, int interactionId, - IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) - throws RemoteException { - final int resolvedWindowId; - IAccessibilityInteractionConnection connection = null; - Region partialInteractiveRegion = Region.obtain(); - MagnificationSpec spec; - synchronized (mLock) { - mUsesAccessibilityCache = true; - if (!isCalledForCurrentUserLocked()) { - return false; - } - resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); - final boolean permissionGranted = - mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); - if (!permissionGranted) { - return false; - } else { - connection = getConnectionLocked(resolvedWindowId); - if (connection == null) { - return false; - } - } - if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( - resolvedWindowId, partialInteractiveRegion)) { - partialInteractiveRegion.recycle(); - partialInteractiveRegion = null; - } - spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); - } - final int interrogatingPid = Binder.getCallingPid(); - callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, - interrogatingPid, interrogatingTid); - final long identityToken = Binder.clearCallingIdentity(); - try { - connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text, - partialInteractiveRegion, interactionId, callback, mFetchFlags, - interrogatingPid, interrogatingTid, spec); - return true; - } catch (RemoteException re) { - if (DEBUG) { - Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()"); - } - } finally { - Binder.restoreCallingIdentity(identityToken); - // Recycle if passed to another process. - if (partialInteractiveRegion != null && Binder.isProxy(connection)) { - partialInteractiveRegion.recycle(); - } - } - return false; - } - - @Override - public boolean findAccessibilityNodeInfoByAccessibilityId( - int accessibilityWindowId, long accessibilityNodeId, int interactionId, - IAccessibilityInteractionConnectionCallback callback, int flags, - long interrogatingTid, Bundle arguments) throws RemoteException { - final int resolvedWindowId; - IAccessibilityInteractionConnection connection = null; - Region partialInteractiveRegion = Region.obtain(); - MagnificationSpec spec; - synchronized (mLock) { - mUsesAccessibilityCache = true; - if (!isCalledForCurrentUserLocked()) { - return false; - } - resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); - final boolean permissionGranted = - mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); - if (!permissionGranted) { - return false; - } else { - connection = getConnectionLocked(resolvedWindowId); - if (connection == null) { - return false; - } - } - if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( - resolvedWindowId, partialInteractiveRegion)) { - partialInteractiveRegion.recycle(); - partialInteractiveRegion = null; - } - spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); - } - final int interrogatingPid = Binder.getCallingPid(); - callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, - interrogatingPid, interrogatingTid); - final long identityToken = Binder.clearCallingIdentity(); - try { - connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId, - partialInteractiveRegion, interactionId, callback, mFetchFlags | flags, - interrogatingPid, interrogatingTid, spec, arguments); - return true; - } catch (RemoteException re) { - if (DEBUG) { - Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()"); - } - } finally { - Binder.restoreCallingIdentity(identityToken); - // Recycle if passed to another process. - if (partialInteractiveRegion != null && Binder.isProxy(connection)) { - partialInteractiveRegion.recycle(); - } - } - return false; - } - - @Override - public boolean findFocus(int accessibilityWindowId, long accessibilityNodeId, - int focusType, int interactionId, - IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) - throws RemoteException { - final int resolvedWindowId; - IAccessibilityInteractionConnection connection = null; - Region partialInteractiveRegion = Region.obtain(); - MagnificationSpec spec; - synchronized (mLock) { - if (!isCalledForCurrentUserLocked()) { - return false; - } - resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked( - accessibilityWindowId, focusType); - final boolean permissionGranted = - mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); - if (!permissionGranted) { - return false; - } else { - connection = getConnectionLocked(resolvedWindowId); - if (connection == null) { - return false; - } - } - if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( - resolvedWindowId, partialInteractiveRegion)) { - partialInteractiveRegion.recycle(); - partialInteractiveRegion = null; - } - spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); - } - final int interrogatingPid = Binder.getCallingPid(); - callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, - interrogatingPid, interrogatingTid); - final long identityToken = Binder.clearCallingIdentity(); - try { - connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion, - interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid, - spec); - return true; - } catch (RemoteException re) { - if (DEBUG) { - Slog.e(LOG_TAG, "Error calling findFocus()"); - } - } finally { - Binder.restoreCallingIdentity(identityToken); - // Recycle if passed to another process. - if (partialInteractiveRegion != null && Binder.isProxy(connection)) { - partialInteractiveRegion.recycle(); - } - } - return false; - } + @Override + public boolean performAccessibilityAction(int resolvedWindowId, + long accessibilityNodeId, int action, Bundle arguments, int interactionId, + IAccessibilityInteractionConnectionCallback callback, int fetchFlags, + long interrogatingTid) { + IAccessibilityInteractionConnection connection = null; + IBinder activityToken = null; + synchronized (mLock) { + connection = getConnectionLocked(resolvedWindowId); + if (connection == null) return false; + final boolean isA11yFocusAction = (action == ACTION_ACCESSIBILITY_FOCUS) + || (action == ACTION_CLEAR_ACCESSIBILITY_FOCUS); + final AccessibilityWindowInfo a11yWindowInfo = + mSecurityPolicy.findA11yWindowInfoById(resolvedWindowId); + if (!isA11yFocusAction) { + final WindowInfo windowInfo = + mSecurityPolicy.findWindowInfoById(resolvedWindowId); + if (windowInfo != null) activityToken = windowInfo.activityToken; + } + if ((a11yWindowInfo != null) && a11yWindowInfo.isInPictureInPictureMode() + && (mPictureInPictureActionReplacingConnection != null) && !isA11yFocusAction) { + connection = mPictureInPictureActionReplacingConnection.mConnection; + } + } + final int interrogatingPid = Binder.getCallingPid(); + final long identityToken = Binder.clearCallingIdentity(); + try { + // Regardless of whether or not the action succeeds, it was generated by an + // accessibility service that is driven by user actions, so note user activity. + mPowerManager.userActivity(SystemClock.uptimeMillis(), + PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0); - @Override - public boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId, - int direction, int interactionId, - IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) - throws RemoteException { - final int resolvedWindowId; - IAccessibilityInteractionConnection connection = null; - Region partialInteractiveRegion = Region.obtain(); - MagnificationSpec spec; - synchronized (mLock) { - if (!isCalledForCurrentUserLocked()) { - return false; - } - resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); - final boolean permissionGranted = - mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); - if (!permissionGranted) { - return false; - } else { - connection = getConnectionLocked(resolvedWindowId); - if (connection == null) { - return false; - } - } - if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( - resolvedWindowId, partialInteractiveRegion)) { - partialInteractiveRegion.recycle(); - partialInteractiveRegion = null; - } - spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); + if (activityToken != null) { + LocalServices.getService(ActivityManagerInternal.class) + .setFocusedActivity(activityToken); } - final int interrogatingPid = Binder.getCallingPid(); - callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId, - interrogatingPid, interrogatingTid); - final long identityToken = Binder.clearCallingIdentity(); - try { - connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion, - interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid, - spec); - return true; - } catch (RemoteException re) { - if (DEBUG) { - Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()"); - } - } finally { - Binder.restoreCallingIdentity(identityToken); - // Recycle if passed to another process. - if (partialInteractiveRegion != null && Binder.isProxy(connection)) { - partialInteractiveRegion.recycle(); - } + connection.performAccessibilityAction(accessibilityNodeId, action, arguments, + interactionId, callback, fetchFlags, interrogatingPid, interrogatingTid); + } catch (RemoteException re) { + if (DEBUG) { + Slog.e(LOG_TAG, "Error calling performAccessibilityAction: " + re); } return false; + } finally { + Binder.restoreCallingIdentity(identityToken); } + return true; + } - @Override - public void sendGesture(int sequence, ParceledListSlice gestureSteps) { - synchronized (mLock) { - if (mSecurityPolicy.canPerformGestures(this)) { - final long endMillis = - SystemClock.uptimeMillis() + WAIT_MOTION_INJECTOR_TIMEOUT_MILLIS; - while ((mMotionEventInjector == null) - && (SystemClock.uptimeMillis() < endMillis)) { - try { - mLock.wait(endMillis - SystemClock.uptimeMillis()); - } catch (InterruptedException ie) { - /* ignore */ - } - } - if (mMotionEventInjector != null) { - List<GestureDescription.GestureStep> steps = gestureSteps.getList(); - mMotionEventInjector.injectEvents(steps, mServiceInterface, sequence); - return; - } else { - Slog.e(LOG_TAG, "MotionEventInjector installation timed out"); - } - } - } - try { - mServiceInterface.onPerformGestureResult(sequence, false); - } catch (RemoteException re) { - Slog.e(LOG_TAG, "Error sending motion event injection failure to " - + mServiceInterface, re); - } - } - - @Override - public boolean performAccessibilityAction(int accessibilityWindowId, - long accessibilityNodeId, int action, Bundle arguments, int interactionId, - IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) - throws RemoteException { - final int resolvedWindowId; - IAccessibilityInteractionConnection connection = null; - synchronized (mLock) { - if (!isCalledForCurrentUserLocked()) { - return false; - } - resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); - final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked( - this, resolvedWindowId); - if (!permissionGranted) { - return false; - } else { - connection = getConnectionLocked(resolvedWindowId); - if (connection == null) { - return false; - } - AccessibilityWindowInfo windowInfo = - mSecurityPolicy.findWindowById(resolvedWindowId); - if ((windowInfo != null) && windowInfo.inPictureInPicture()) { - boolean isA11yFocusAction = - (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) - || (action == - AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); - if ((mPictureInPictureActionReplacingConnection != null) - && !isA11yFocusAction) { - connection = mPictureInPictureActionReplacingConnection.mConnection; - } - } - } - } - final int interrogatingPid = Binder.getCallingPid(); - final long identityToken = Binder.clearCallingIdentity(); - try { - // Regardless of whether or not the action succeeds, it was generated by an - // accessibility service that is driven by user actions, so note user activity. - mPowerManager.userActivity(SystemClock.uptimeMillis(), - PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0); - - connection.performAccessibilityAction(accessibilityNodeId, action, arguments, - interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid); - } catch (RemoteException re) { - if (DEBUG) { - Slog.e(LOG_TAG, "Error calling performAccessibilityAction()"); - } - } finally { - Binder.restoreCallingIdentity(identityToken); - } - return true; - } - - @Override - public boolean performGlobalAction(int action) { - synchronized (mLock) { - if (!isCalledForCurrentUserLocked()) { - return false; - } - } - final long identity = Binder.clearCallingIdentity(); - try { - mPowerManager.userActivity(SystemClock.uptimeMillis(), - PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0); - switch (action) { - case AccessibilityService.GLOBAL_ACTION_BACK: { - sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK); - } return true; - case AccessibilityService.GLOBAL_ACTION_HOME: { - sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME); - } return true; - case AccessibilityService.GLOBAL_ACTION_RECENTS: { - return openRecents(); - } - case AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS: { - expandNotifications(); - } return true; - case AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS: { - expandQuickSettings(); - } return true; - case AccessibilityService.GLOBAL_ACTION_POWER_DIALOG: { - showGlobalActions(); - } return true; - case AccessibilityService.GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN: { - toggleSplitScreen(); - } return true; - } - return false; - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public boolean isFingerprintGestureDetectionAvailable() { - return isCapturingFingerprintGestures() - && (mFingerprintGestureDispatcher != null) - && mFingerprintGestureDispatcher.isFingerprintGestureDetectionAvailable(); - } - - @Override - public float getMagnificationScale() { - synchronized (mLock) { - if (!isCalledForCurrentUserLocked()) { - return 1.0f; - } - } - final long identity = Binder.clearCallingIdentity(); - try { - return getMagnificationController().getScale(); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public Region getMagnificationRegion() { - synchronized (mLock) { - final Region region = Region.obtain(); - if (!isCalledForCurrentUserLocked()) { - return region; - } - MagnificationController magnificationController = getMagnificationController(); - boolean forceRegistration = mSecurityPolicy.canControlMagnification(this); - boolean initiallyRegistered = magnificationController.isRegisteredLocked(); - if (!initiallyRegistered && forceRegistration) { - magnificationController.register(); - } - final long identity = Binder.clearCallingIdentity(); - try { - magnificationController.getMagnificationRegion(region); - return region; - } finally { - Binder.restoreCallingIdentity(identity); - if (!initiallyRegistered && forceRegistration) { - magnificationController.unregister(); - } - } - } - } - - @Override - public float getMagnificationCenterX() { - synchronized (mLock) { - if (!isCalledForCurrentUserLocked()) { - return 0.0f; - } - } - final long identity = Binder.clearCallingIdentity(); - try { - return getMagnificationController().getCenterX(); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public float getMagnificationCenterY() { - synchronized (mLock) { - if (!isCalledForCurrentUserLocked()) { - return 0.0f; - } - } - final long identity = Binder.clearCallingIdentity(); - try { - return getMagnificationController().getCenterY(); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public boolean resetMagnification(boolean animate) { - synchronized (mLock) { - if (!isCalledForCurrentUserLocked()) { - return false; - } - final boolean permissionGranted = mSecurityPolicy.canControlMagnification(this); - if (!permissionGranted) { - return false; - } - } - final long identity = Binder.clearCallingIdentity(); - try { - return getMagnificationController().reset(animate); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - @Override - public boolean setMagnificationScaleAndCenter(float scale, float centerX, float centerY, - boolean animate) { - synchronized (mLock) { - if (!isCalledForCurrentUserLocked()) { - return false; - } - final boolean permissionGranted = mSecurityPolicy.canControlMagnification(this); - if (!permissionGranted) { - return false; - } - final long identity = Binder.clearCallingIdentity(); - try { - MagnificationController magnificationController = getMagnificationController(); - if (!magnificationController.isRegisteredLocked()) { - magnificationController.register(); - } - return magnificationController - .setScaleAndCenter(scale, centerX, centerY, animate, mId); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - } - - @Override - public void setMagnificationCallbackEnabled(boolean enabled) { - mInvocationHandler.setMagnificationCallbackEnabled(enabled); - } - - @Override - public boolean setSoftKeyboardShowMode(int showMode) { - final UserState userState; - synchronized (mLock) { - if (!isCalledForCurrentUserLocked()) { - return false; - } - - userState = getCurrentUserStateLocked(); - } - - final long identity = Binder.clearCallingIdentity(); - try { - // Keep track of the last service to request a non-default show mode. The show mode - // should be restored to default should this service be disabled. - if (showMode == Settings.Secure.SHOW_MODE_AUTO) { - userState.mServiceChangingSoftKeyboardMode = null; - } else { - userState.mServiceChangingSoftKeyboardMode = mComponentName; - } - - Settings.Secure.putIntForUser(mContext.getContentResolver(), - Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, showMode, - userState.mUserId); - } finally { - Binder.restoreCallingIdentity(identity); - } - return true; - } - - @Override - public void setSoftKeyboardCallbackEnabled(boolean enabled) { - mInvocationHandler.setSoftKeyboardCallbackEnabled(enabled); - } - - @Override - public boolean isAccessibilityButtonAvailable() { - final UserState userState; - synchronized (mLock) { - if (!isCalledForCurrentUserLocked()) { - return false; - } - userState = getCurrentUserStateLocked(); - return isAccessibilityButtonAvailableLocked(userState); - } - } - - @Override - public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { - if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return; - synchronized (mLock) { - pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo() - .loadLabel(mContext.getPackageManager())); - pw.append(", feedbackType" - + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType)); - pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities()); - pw.append(", eventTypes=" - + AccessibilityEvent.eventTypeToString(mEventTypes)); - pw.append(", notificationTimeout=" + mNotificationTimeout); - pw.append("]"); - } - } - - @Override - public void onServiceDisconnected(ComponentName componentName) { - binderDied(); - } - - public void onAdded() throws RemoteException { - final long identity = Binder.clearCallingIdentity(); - try { - mWindowManagerService.addWindowToken(mOverlayWindowToken, - TYPE_ACCESSIBILITY_OVERLAY, DEFAULT_DISPLAY); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - public void onRemoved() { - final long identity = Binder.clearCallingIdentity(); - try { - mWindowManagerService.removeWindowToken(mOverlayWindowToken, true, DEFAULT_DISPLAY); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - - public void resetLocked() { - try { - // Clear the proxy in the other process so this - // IAccessibilityServiceConnection can be garbage collected. - if (mServiceInterface != null) { - mServiceInterface.init(null, mId, null); - } - } catch (RemoteException re) { - /* ignore */ - } - if (mService != null) { - mService.unlinkToDeath(this, 0); - mService = null; - } - mServiceInterface = null; - mReceivedAccessibilityButtonCallbackSinceBind = false; - } - - public boolean isConnectedLocked() { - return (mService != null); - } - - public void binderDied() { - synchronized (mLock) { - // It is possible that this service's package was force stopped during - // whose handling the death recipient is unlinked and still get a call - // on binderDied since the call was made before we unlink but was - // waiting on the lock we held during the force stop handling. - if (!isConnectedLocked()) { - return; - } - mWasConnectedAndDied = true; - getKeyEventDispatcher().flush(this); - UserState userState = getUserStateLocked(mUserId); - resetLocked(); - if (mIsAutomation) { - // This is typically done when unbinding, but UiAutomation isn't bound. - removeServiceLocked(this, userState); - // We no longer have an automation service, so restore - // the state based on values in the settings database. - userState.mInstalledServices.remove(mAccessibilityServiceInfo); - userState.mEnabledServices.remove(mComponentName); - userState.destroyUiAutomationService(); - readConfigurationForUserStateLocked(userState); - } - if (mId == getMagnificationController().getIdOfLastServiceToMagnify()) { - getMagnificationController().resetIfNeeded(true); - } - onUserStateChangedLocked(userState); - } - } - - /** - * Performs a notification for an {@link AccessibilityEvent}. - * - * @param event The event. - * @param serviceWantsEvent whether the event should be received by - * {@link AccessibilityService#onAccessibilityEvent} (true), - * as opposed to just {@link AccessibilityInteractionClient#onAccessibilityEvent} (false) - */ - public void notifyAccessibilityEvent(AccessibilityEvent event, boolean serviceWantsEvent) { - synchronized (mLock) { - final int eventType = event.getEventType(); - // Make a copy since during dispatch it is possible the event to - // be modified to remove its source if the receiving service does - // not have permission to access the window content. - AccessibilityEvent newEvent = AccessibilityEvent.obtain(event); - Message message; - if ((mNotificationTimeout > 0) - && (eventType != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)) { - // Allow at most one pending event - final AccessibilityEvent oldEvent = mPendingEvents.get(eventType); - mPendingEvents.put(eventType, newEvent); - if (oldEvent != null) { - mEventDispatchHandler.removeMessages(eventType); - oldEvent.recycle(); - } - message = mEventDispatchHandler.obtainMessage(eventType); - } else { - // Send all messages, bypassing mPendingEvents - message = mEventDispatchHandler.obtainMessage(eventType, newEvent); - } - message.arg1 = serviceWantsEvent ? 1 : 0; - - mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout); - } - } - - private boolean isAccessibilityButtonAvailableLocked(UserState userState) { - // If the service does not request the accessibility button, it isn't available - if (!mRequestAccessibilityButton) { - return false; - } - - // If the accessibility button isn't currently shown, it cannot be available to services - if (!mIsAccessibilityButtonShown) { - return false; - } - - // If magnification is on and assigned to the accessibility button, services cannot be - if (userState.mIsNavBarMagnificationEnabled - && userState.mIsNavBarMagnificationAssignedToAccessibilityButton) { - return false; - } - - int requestingServices = 0; - for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) { - final Service service = userState.mBoundServices.get(i); - if (service.mRequestAccessibilityButton) { - requestingServices++; - } - } - - if (requestingServices == 1) { - // If only a single service is requesting, it must be this service, and the - // accessibility button is available to it - return true; - } else { - // With more than one active service, we derive the target from the user's settings - if (userState.mServiceAssignedToAccessibilityButton == null) { - // If the user has not made an assignment, we treat the button as available to - // all services until the user interacts with the button to make an assignment - return true; - } else { - // If an assignment was made, it defines availability - return mComponentName.equals(userState.mServiceAssignedToAccessibilityButton); - } - } - } - - /** - * Notifies an accessibility service client for a scheduled event given the event type. - * - * @param eventType The type of the event to dispatch. - */ - private void notifyAccessibilityEventInternal( - int eventType, - AccessibilityEvent event, - boolean serviceWantsEvent) { - IAccessibilityServiceClient listener; - - synchronized (mLock) { - listener = mServiceInterface; - - // If the service died/was disabled while the message for dispatching - // the accessibility event was propagating the listener may be null. - if (listener == null) { - return; - } - - // There are two ways we notify for events, throttled and non-throttled. If we - // are not throttling, then messages come with events, which we handle with - // minimal fuss. - if (event == null) { - // We are throttling events, so we'll send the event for this type in - // mPendingEvents as long as it it's null. It can only null due to a race - // condition: - // - // 1) A binder thread calls notifyAccessibilityServiceDelayedLocked - // which posts a message for dispatching an event and stores the event - // in mPendingEvents. - // 2) The message is pulled from the queue by the handler on the service - // thread and this method is just about to acquire the lock. - // 3) Another binder thread acquires the lock in notifyAccessibilityEvent - // 4) notifyAccessibilityEvent recycles the event that this method was about - // to process, replaces it with a new one, and posts a second message - // 5) This method grabs the new event, processes it, and removes it from - // mPendingEvents - // 6) The second message dispatched in (4) arrives, but the event has been - // remvoved in (5). - event = mPendingEvents.get(eventType); - if (event == null) { - return; - } - mPendingEvents.remove(eventType); - } - if (mSecurityPolicy.canRetrieveWindowContentLocked(this)) { - event.setConnectionId(mId); - } else { - event.setSource((View) null); - } - event.setSealed(true); - } - - try { - listener.onAccessibilityEvent(event, serviceWantsEvent); - if (DEBUG) { - Slog.i(LOG_TAG, "Event " + event + " sent to " + listener); - } - } catch (RemoteException re) { - Slog.e(LOG_TAG, "Error during sending " + event + " to " + listener, re); - } finally { - event.recycle(); - } - } - - public void notifyGesture(int gestureId) { - mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE, - gestureId, 0).sendToTarget(); - } - - public void notifyClearAccessibilityNodeInfoCache() { - mInvocationHandler.sendEmptyMessage( - InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE); - } - - public void notifyMagnificationChangedLocked(@NonNull Region region, - float scale, float centerX, float centerY) { - mInvocationHandler - .notifyMagnificationChangedLocked(region, scale, centerX, centerY); - } - - public void notifySoftKeyboardShowModeChangedLocked(int showState) { - mInvocationHandler.notifySoftKeyboardShowModeChangedLocked(showState); - } - - public void notifyAccessibilityButtonClickedLocked() { - mInvocationHandler.notifyAccessibilityButtonClickedLocked(); - } - - public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) { - mInvocationHandler.notifyAccessibilityButtonAvailabilityChangedLocked(available); - } - - /** - * Called by the invocation handler to notify the service that the - * state of magnification has changed. - */ - private void notifyMagnificationChangedInternal(@NonNull Region region, - float scale, float centerX, float centerY) { - final IAccessibilityServiceClient listener; - synchronized (mLock) { - listener = mServiceInterface; - } - if (listener != null) { - try { - listener.onMagnificationChanged(region, scale, centerX, centerY); - } catch (RemoteException re) { - Slog.e(LOG_TAG, "Error sending magnification changes to " + mService, re); - } - } - } - - /** - * Called by the invocation handler to notify the service that the state of the soft - * keyboard show mode has changed. - */ - private void notifySoftKeyboardShowModeChangedInternal(int showState) { - final IAccessibilityServiceClient listener; - synchronized (mLock) { - listener = mServiceInterface; - } - if (listener != null) { - try { - listener.onSoftKeyboardShowModeChanged(showState); - } catch (RemoteException re) { - Slog.e(LOG_TAG, "Error sending soft keyboard show mode changes to " + mService, - re); - } - } - } - - private void notifyAccessibilityButtonClickedInternal() { - final IAccessibilityServiceClient listener; - synchronized (mLock) { - listener = mServiceInterface; - } - if (listener != null) { - try { - listener.onAccessibilityButtonClicked(); - } catch (RemoteException re) { - Slog.e(LOG_TAG, "Error sending accessibility button click to " + mService, re); - } - } - } - - private void notifyAccessibilityButtonAvailabilityChangedInternal(boolean available) { - // Only notify the service if it's not been notified or the state has changed - if (mReceivedAccessibilityButtonCallbackSinceBind - && (mLastAccessibilityButtonCallbackState == available)) { - return; - } - mReceivedAccessibilityButtonCallbackSinceBind = true; - mLastAccessibilityButtonCallbackState = available; - final IAccessibilityServiceClient listener; - synchronized (mLock) { - listener = mServiceInterface; - } - if (listener != null) { - try { - listener.onAccessibilityButtonAvailabilityChanged(available); - } catch (RemoteException re) { - Slog.e(LOG_TAG, - "Error sending accessibility button availability change to " + mService, - re); - } - } - } - - private void notifyGestureInternal(int gestureId) { - final IAccessibilityServiceClient listener; - synchronized (mLock) { - listener = mServiceInterface; - } - if (listener != null) { - try { - listener.onGesture(gestureId); - } catch (RemoteException re) { - Slog.e(LOG_TAG, "Error during sending gesture " + gestureId - + " to " + mService, re); - } - } - } - - private void notifyClearAccessibilityCacheInternal() { - final IAccessibilityServiceClient listener; - synchronized (mLock) { - listener = mServiceInterface; - } - if (listener != null) { - try { - listener.clearAccessibilityCache(); - } catch (RemoteException re) { - Slog.e(LOG_TAG, "Error during requesting accessibility info cache" - + " to be cleared.", re); - } - } - } - - private void sendDownAndUpKeyEvents(int keyCode) { - final long token = Binder.clearCallingIdentity(); - - // Inject down. - final long downTime = SystemClock.uptimeMillis(); - KeyEvent down = KeyEvent.obtain(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode, 0, 0, - KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM, - InputDevice.SOURCE_KEYBOARD, null); - InputManager.getInstance().injectInputEvent(down, - InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); - down.recycle(); - - // Inject up. - final long upTime = SystemClock.uptimeMillis(); - KeyEvent up = KeyEvent.obtain(downTime, upTime, KeyEvent.ACTION_UP, keyCode, 0, 0, - KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM, - InputDevice.SOURCE_KEYBOARD, null); - InputManager.getInstance().injectInputEvent(up, - InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); - up.recycle(); - - Binder.restoreCallingIdentity(token); - } - - private void expandNotifications() { - final long token = Binder.clearCallingIdentity(); - - StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService( - android.app.Service.STATUS_BAR_SERVICE); - statusBarManager.expandNotificationsPanel(); - - Binder.restoreCallingIdentity(token); - } - - private void expandQuickSettings() { - final long token = Binder.clearCallingIdentity(); - - StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService( - android.app.Service.STATUS_BAR_SERVICE); - statusBarManager.expandSettingsPanel(); - - Binder.restoreCallingIdentity(token); - } - - private boolean openRecents() { - final long token = Binder.clearCallingIdentity(); - try { - StatusBarManagerInternal statusBarService = LocalServices.getService( - StatusBarManagerInternal.class); - if (statusBarService == null) { - return false; - } - statusBarService.toggleRecentApps(); - } finally { - Binder.restoreCallingIdentity(token); - } - return true; + @Override + public IAccessibilityInteractionConnection getConnectionLocked(int windowId) { + if (DEBUG) { + Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId); } - - private void showGlobalActions() { - mWindowManagerService.showGlobalActions(); + AccessibilityManagerService.AccessibilityConnectionWrapper wrapper = + mGlobalInteractionConnections.get(windowId); + if (wrapper == null) { + wrapper = getCurrentUserStateLocked().mInteractionConnections.get(windowId); } - - private void toggleSplitScreen() { - LocalServices.getService(StatusBarManagerInternal.class).toggleSplitScreen(); + if (wrapper != null && wrapper.mConnection != null) { + return wrapper.mConnection; } - - private IAccessibilityInteractionConnection getConnectionLocked(int windowId) { - if (DEBUG) { - Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId); - } - AccessibilityConnectionWrapper wrapper = mGlobalInteractionConnections.get(windowId); - if (wrapper == null) { - wrapper = getCurrentUserStateLocked().mInteractionConnections.get(windowId); - } - if (wrapper != null && wrapper.mConnection != null) { - return wrapper.mConnection; - } - if (DEBUG) { - Slog.e(LOG_TAG, "No interaction connection to window: " + windowId); - } - return null; - } - - private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) { - if (accessibilityWindowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) { - return mSecurityPolicy.getActiveWindowId(); - } - return accessibilityWindowId; - } - - private int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) { - if (windowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) { - return mSecurityPolicy.mActiveWindowId; - } - if (windowId == AccessibilityWindowInfo.ANY_WINDOW_ID) { - if (focusType == AccessibilityNodeInfo.FOCUS_INPUT) { - return mSecurityPolicy.mFocusedWindowId; - } else if (focusType == AccessibilityNodeInfo.FOCUS_ACCESSIBILITY) { - return mSecurityPolicy.mAccessibilityFocusedWindowId; - } - } - return windowId; + if (DEBUG) { + Slog.e(LOG_TAG, "No interaction connection to window: " + windowId); } + return null; + } - private IAccessibilityInteractionConnectionCallback replaceCallbackIfNeeded( - IAccessibilityInteractionConnectionCallback originalCallback, - int resolvedWindowId, int interactionId, int interrogatingPid, - long interrogatingTid) { - AccessibilityWindowInfo windowInfo = mSecurityPolicy.findWindowById(resolvedWindowId); - if ((windowInfo == null) || !windowInfo.inPictureInPicture() - || (mPictureInPictureActionReplacingConnection == null)) { - return originalCallback; - } - return new ActionReplacingCallback(originalCallback, - mPictureInPictureActionReplacingConnection.mConnection, interactionId, - interrogatingPid, interrogatingTid); + @Override + public IAccessibilityInteractionConnectionCallback replaceCallbackIfNeeded( + IAccessibilityInteractionConnectionCallback originalCallback, + int resolvedWindowId, int interactionId, int interrogatingPid, + long interrogatingTid) { + AccessibilityWindowInfo windowInfo = + mSecurityPolicy.findA11yWindowInfoById(resolvedWindowId); + if ((windowInfo == null) || !windowInfo.isInPictureInPictureMode() + || (mPictureInPictureActionReplacingConnection == null)) { + return originalCallback; } + return new ActionReplacingCallback(originalCallback, + mPictureInPictureActionReplacingConnection.mConnection, interactionId, + interrogatingPid, interrogatingTid); + } - private final class InvocationHandler extends Handler { - public static final int MSG_ON_GESTURE = 1; - public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 2; - - private static final int MSG_ON_MAGNIFICATION_CHANGED = 5; - private static final int MSG_ON_SOFT_KEYBOARD_STATE_CHANGED = 6; - private static final int MSG_ON_ACCESSIBILITY_BUTTON_CLICKED = 7; - private static final int MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED = 8; - - private boolean mIsMagnificationCallbackEnabled = false; - private boolean mIsSoftKeyboardCallbackEnabled = false; - - public InvocationHandler(Looper looper) { - super(looper, null, true); - } - - @Override - public void handleMessage(Message message) { - final int type = message.what; - switch (type) { - case MSG_ON_GESTURE: { - final int gestureId = message.arg1; - notifyGestureInternal(gestureId); - } break; - - case MSG_CLEAR_ACCESSIBILITY_CACHE: { - notifyClearAccessibilityCacheInternal(); - } break; - - case MSG_ON_MAGNIFICATION_CHANGED: { - final SomeArgs args = (SomeArgs) message.obj; - final Region region = (Region) args.arg1; - final float scale = (float) args.arg2; - final float centerX = (float) args.arg3; - final float centerY = (float) args.arg4; - notifyMagnificationChangedInternal(region, scale, centerX, centerY); - } break; - - case MSG_ON_SOFT_KEYBOARD_STATE_CHANGED: { - final int showState = (int) message.arg1; - notifySoftKeyboardShowModeChangedInternal(showState); - } break; - - case MSG_ON_ACCESSIBILITY_BUTTON_CLICKED: { - notifyAccessibilityButtonClickedInternal(); - } break; - - case MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED: { - final boolean available = (message.arg1 != 0); - notifyAccessibilityButtonAvailabilityChangedInternal(available); - } break; - - default: { - throw new IllegalArgumentException("Unknown message: " + type); - } - } - } - - public void notifyMagnificationChangedLocked(@NonNull Region region, float scale, - float centerX, float centerY) { - if (!mIsMagnificationCallbackEnabled) { - // Callback is disabled, don't bother packing args. - return; - } - - final SomeArgs args = SomeArgs.obtain(); - args.arg1 = region; - args.arg2 = scale; - args.arg3 = centerX; - args.arg4 = centerY; - - final Message msg = obtainMessage(MSG_ON_MAGNIFICATION_CHANGED, args); - msg.sendToTarget(); - } - - public void setMagnificationCallbackEnabled(boolean enabled) { - mIsMagnificationCallbackEnabled = enabled; - } - - public void notifySoftKeyboardShowModeChangedLocked(int showState) { - if (!mIsSoftKeyboardCallbackEnabled) { - return; - } - - final Message msg = obtainMessage(MSG_ON_SOFT_KEYBOARD_STATE_CHANGED, showState, 0); - msg.sendToTarget(); - } - - public void setSoftKeyboardCallbackEnabled(boolean enabled) { - mIsSoftKeyboardCallbackEnabled = enabled; - } - - public void notifyAccessibilityButtonClickedLocked() { - final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_CLICKED); - msg.sendToTarget(); - } - - public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) { - final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED, - (available ? 1 : 0), 0); - msg.sendToTarget(); - } + @Override + public void onClientChange(boolean serviceInfoChanged) { + AccessibilityManagerService.UserState userState = getUserStateLocked(mCurrentUserId); + onUserStateChangedLocked(userState); + if (serviceInfoChanged) { + scheduleNotifyClientsOfServicesStateChange(userState); } } @@ -4193,24 +2607,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @Override public void onWindowsForAccessibilityChanged(List<WindowInfo> windows) { synchronized (mLock) { - // Populate the windows to report. - List<AccessibilityWindowInfo> reportedWindows = new ArrayList<>(); - final int receivedWindowCount = windows.size(); - for (int i = 0; i < receivedWindowCount; i++) { - WindowInfo receivedWindow = windows.get(i); - AccessibilityWindowInfo reportedWindow = populateReportedWindow( - receivedWindow); - if (reportedWindow != null) { - reportedWindows.add(reportedWindow); - } - } - if (DEBUG) { - Slog.i(LOG_TAG, "Windows changed: " + reportedWindows); + Slog.i(LOG_TAG, "Windows changed: " + windows); } // Let the policy update the focused and active windows. - mSecurityPolicy.updateWindowsLocked(reportedWindows); + mSecurityPolicy.updateWindowsLocked(windows); // Someone may be waiting for the windows - advertise it. mLock.notifyAll(); @@ -4308,17 +2710,32 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } private final class InteractionBridge { + private final ComponentName COMPONENT_NAME = + new ComponentName("com.android.server.accessibility", "InteractionBridge"); + private final Display mDefaultDisplay; private final int mConnectionId; private final AccessibilityInteractionClient mClient; public InteractionBridge() { - AccessibilityServiceInfo info = new AccessibilityServiceInfo(); + final AccessibilityServiceInfo info = new AccessibilityServiceInfo(); info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT); info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS; info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; - Service service = new Service(UserHandle.USER_NULL, - sFakeAccessibilityServiceComponentName, info); + final UserState userState; + synchronized (mLock) { + userState = getCurrentUserStateLocked(); + } + AccessibilityServiceConnection service = new AccessibilityServiceConnection( + userState, mContext, + COMPONENT_NAME, info, sIdCounter++, mMainHandler, mLock, mSecurityPolicy, + AccessibilityManagerService.this, mWindowManagerService, + mGlobalActionPerformer) { + @Override + public boolean supportsFlagForNotImportantViews(AccessibilityServiceInfo info) { + return true; + } + }; mConnectionId = service.mId; @@ -4411,7 +2828,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } - final class SecurityPolicy { + public class SecurityPolicy { public static final int INVALID_WINDOW_ID = -1; private static final int RETRIEVAL_ALLOWING_EVENT_TYPES = @@ -4432,7 +2849,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { // In Z order public List<AccessibilityWindowInfo> mWindows; - public SparseArray<AccessibilityWindowInfo> mWindowsById = new SparseArray<>(); + public SparseArray<AccessibilityWindowInfo> mA11yWindowInfoById = new SparseArray<>(); + public SparseArray<WindowInfo> mWindowInfoById = new SparseArray<>(); public int mActiveWindowId = INVALID_WINDOW_ID; public int mFocusedWindowId = INVALID_WINDOW_ID; @@ -4476,14 +2894,14 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } public void clearWindowsLocked() { - List<AccessibilityWindowInfo> windows = Collections.emptyList(); + List<WindowInfo> windows = Collections.emptyList(); final int activeWindowId = mActiveWindowId; updateWindowsLocked(windows); mActiveWindowId = activeWindowId; mWindows = null; } - public void updateWindowsLocked(List<AccessibilityWindowInfo> windows) { + public void updateWindowsLocked(List<WindowInfo> windows) { if (mWindows == null) { mWindows = new ArrayList<>(); } @@ -4492,7 +2910,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { for (int i = oldWindowCount - 1; i >= 0; i--) { mWindows.remove(i).recycle(); } - mWindowsById.clear(); + mA11yWindowInfoById.clear(); + + for (int i = 0; i < mWindowInfoById.size(); i++) { + mWindowInfoById.valueAt(i).recycle(); + } + mWindowInfoById.clear(); mFocusedWindowId = INVALID_WINDOW_ID; if (!mTouchInteractionInProgress) { @@ -4509,19 +2932,25 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { final int windowCount = windows.size(); if (windowCount > 0) { for (int i = 0; i < windowCount; i++) { - AccessibilityWindowInfo window = windows.get(i); - final int windowId = window.getId(); - if (window.isFocused()) { - mFocusedWindowId = windowId; - if (!mTouchInteractionInProgress) { - mActiveWindowId = windowId; - window.setActive(true); - } else if (windowId == mActiveWindowId) { - activeWindowGone = false; + WindowInfo windowInfo = windows.get(i); + AccessibilityWindowInfo window = (mWindowsForAccessibilityCallback != null) + ? mWindowsForAccessibilityCallback.populateReportedWindow(windowInfo) + : null; + if (window != null) { + final int windowId = window.getId(); + if (window.isFocused()) { + mFocusedWindowId = windowId; + if (!mTouchInteractionInProgress) { + mActiveWindowId = windowId; + window.setActive(true); + } else if (windowId == mActiveWindowId) { + activeWindowGone = false; + } } + mWindows.add(window); + mA11yWindowInfoById.put(windowId, window); + mWindowInfoById.put(windowId, WindowInfo.obtain(windowInfo)); } - mWindows.add(window); - mWindowsById.put(windowId, window); } if (mTouchInteractionInProgress && activeWindowGone) { @@ -4530,7 +2959,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { // Focused window may change the active one, so set the // active window once we decided which it is. - for (int i = 0; i < windowCount; i++) { + final int accessibilityWindowCount = mWindows.size(); + for (int i = 0; i < accessibilityWindowCount; i++) { AccessibilityWindowInfo window = mWindows.get(i); if (window.getId() == mActiveWindowId) { window.setActive(true); @@ -4739,30 +3169,31 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } - public boolean canGetAccessibilityNodeInfoLocked(Service service, int windowId) { + public boolean canGetAccessibilityNodeInfoLocked( + AccessibilityClientConnection service, int windowId) { return canRetrieveWindowContentLocked(service) && isRetrievalAllowingWindow(windowId); } - public boolean canRetrieveWindowsLocked(Service service) { + public boolean canRetrieveWindowsLocked(AccessibilityClientConnection service) { return canRetrieveWindowContentLocked(service) && service.mRetrieveInteractiveWindows; } - public boolean canRetrieveWindowContentLocked(Service service) { + public boolean canRetrieveWindowContentLocked(AccessibilityClientConnection service) { return (service.mAccessibilityServiceInfo.getCapabilities() & AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0; } - public boolean canControlMagnification(Service service) { + public boolean canControlMagnification(AccessibilityClientConnection service) { return (service.mAccessibilityServiceInfo.getCapabilities() & AccessibilityServiceInfo.CAPABILITY_CAN_CONTROL_MAGNIFICATION) != 0; } - public boolean canPerformGestures(Service service) { + public boolean canPerformGestures(AccessibilityServiceConnection service) { return (service.mAccessibilityServiceInfo.getCapabilities() & AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0; } - public boolean canCaptureFingerprintGestures(Service service) { + public boolean canCaptureFingerprintGestures(AccessibilityServiceConnection service) { return (service.mAccessibilityServiceInfo.getCapabilities() & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES) != 0; } @@ -4833,11 +3264,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { if (windowId == mActiveWindowId) { return true; } - return findWindowById(windowId) != null; + return findA11yWindowInfoById(windowId) != null; } - private AccessibilityWindowInfo findWindowById(int windowId) { - return mWindowsById.get(windowId); + public AccessibilityWindowInfo findA11yWindowInfoById(int windowId) { + return mA11yWindowInfoById.get(windowId); + } + + private WindowInfo findWindowInfoById(int windowId) { + return mWindowInfoById.get(windowId); } private AccessibilityWindowInfo getPictureInPictureWindow() { @@ -4876,7 +3311,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } - private class UserState { + public class UserState { public final int mUserId; // Non-transient state. @@ -4891,18 +3326,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { // Transient state. - public final CopyOnWriteArrayList<Service> mBoundServices = + public final CopyOnWriteArrayList<AccessibilityServiceConnection> mBoundServices = new CopyOnWriteArrayList<>(); public int mLastSentRelevantEventTypes = AccessibilityEvent.TYPES_ALL_MASK; - public final Map<ComponentName, Service> mComponentNameToServiceMap = + public final Map<ComponentName, AccessibilityServiceConnection> mComponentNameToServiceMap = new HashMap<>(); public final List<AccessibilityServiceInfo> mInstalledServices = new ArrayList<>(); - public final Set<ComponentName> mBindingServices = new HashSet<>(); + private final Set<ComponentName> mBindingServices = new HashSet<>(); public final Set<ComponentName> mEnabledServices = new HashSet<>(); @@ -4929,35 +3364,19 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { public boolean mIsFilterKeyEventsEnabled; public boolean mAccessibilityFocusOnlyInActiveWindow; - private Service mUiAutomationService; - private int mUiAutomationFlags; - private IAccessibilityServiceClient mUiAutomationServiceClient; - - private IBinder mUiAutomationServiceOwner; - private final DeathRecipient mUiAutomationSerivceOnwerDeathRecipient = - new DeathRecipient() { - @Override - public void binderDied() { - mUiAutomationServiceOwner.unlinkToDeath( - mUiAutomationSerivceOnwerDeathRecipient, 0); - mUiAutomationServiceOwner = null; - if (mUiAutomationService != null) { - mUiAutomationService.binderDied(); - } - } - }; - public UserState(int userId) { mUserId = userId; } public int getClientState() { int clientState = 0; - if (isHandlingAccessibilityEvents()) { + final boolean a11yEnabled = (mUiAutomationManager.isUiAutomationRunningLocked() + || isHandlingAccessibilityEvents()); + if (a11yEnabled) { clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED; } // Touch exploration relies on enabled accessibility. - if (isHandlingAccessibilityEvents() && mIsTouchExplorationEnabled) { + if (a11yEnabled && mIsTouchExplorationEnabled) { clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED; } if (mIsTextHighContrastEnabled) { @@ -4971,11 +3390,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } public void onSwitchToAnotherUser() { - // Clear UI test automation state. - if (mUiAutomationService != null) { - mUiAutomationService.binderDied(); - } - // Unbind all services. unbindAllServicesLocked(this); @@ -4998,20 +3412,35 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { mSoftKeyboardShowMode = 0; } - public void destroyUiAutomationService() { - mUiAutomationService = null; - mUiAutomationFlags = 0; - mUiAutomationServiceClient = null; - if (mUiAutomationServiceOwner != null) { - mUiAutomationServiceOwner.unlinkToDeath( - mUiAutomationSerivceOnwerDeathRecipient, 0); - mUiAutomationServiceOwner = null; + public void addServiceLocked(AccessibilityServiceConnection serviceConnection) { + if (!mBoundServices.contains(serviceConnection)) { + serviceConnection.onAdded(); + mBoundServices.add(serviceConnection); + mComponentNameToServiceMap.put(serviceConnection.mComponentName, serviceConnection); + scheduleNotifyClientsOfServicesStateChange(this); } } - boolean isUiAutomationSuppressingOtherServices() { - return ((mUiAutomationService != null) && (mUiAutomationFlags - & UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) == 0); + /** + * Removes a service. + * + * @param serviceConnection The service. + */ + public void removeServiceLocked(AccessibilityServiceConnection serviceConnection) { + mBoundServices.remove(serviceConnection); + serviceConnection.onRemoved(); + // It may be possible to bind a service twice, which confuses the map. Rebuild the map + // to make sure we can still reach a service + mComponentNameToServiceMap.clear(); + for (int i = 0; i < mBoundServices.size(); i++) { + AccessibilityServiceConnection boundClient = mBoundServices.get(i); + mComponentNameToServiceMap.put(boundClient.mComponentName, boundClient); + } + scheduleNotifyClientsOfServicesStateChange(this); + } + + public Set<ComponentName> getBindingServicesLocked() { + return mBindingServices; } } @@ -5097,11 +3526,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { // we are checking for changes only the parent settings. UserState userState = getCurrentUserStateLocked(); - // If the automation service is suppressing, we will update when it dies. - if (userState.isUiAutomationSuppressingOtherServices()) { - return; - } - if (mTouchExplorationEnabledUri.equals(uri)) { if (readTouchExplorationEnabledSettingLocked(userState)) { onUserStateChangedLocked(userState); diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java new file mode 100644 index 000000000000..eb26752988aa --- /dev/null +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java @@ -0,0 +1,364 @@ +/* + ** Copyright 2017, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +package com.android.server.accessibility; + +import static android.provider.Settings.Secure.SHOW_MODE_AUTO; + +import android.accessibilityservice.AccessibilityServiceInfo; +import android.accessibilityservice.GestureDescription; +import android.accessibilityservice.IAccessibilityServiceClient; +import android.accessibilityservice.IAccessibilityServiceConnection; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ParceledListSlice; +import android.os.Binder; +import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.UserHandle; +import android.provider.Settings; +import android.util.Slog; +import android.view.WindowManagerInternal; + +import com.android.server.accessibility.AccessibilityManagerService.SecurityPolicy; +import com.android.server.accessibility.AccessibilityManagerService.UserState; + +import java.lang.ref.WeakReference; +import java.util.List; +import java.util.Set; + +/** + * This class represents an accessibility service. It stores all per service + * data required for the service management, provides API for starting/stopping the + * service and is responsible for adding/removing the service in the data structures + * for service management. The class also exposes configuration interface that is + * passed to the service it represents as soon it is bound. It also serves as the + * connection for the service. + */ +class AccessibilityServiceConnection extends AccessibilityClientConnection { + private static final String LOG_TAG = "AccessibilityServiceConnection"; + /* + Holding a weak reference so there isn't a loop of references. UserState keeps lists of bound + and binding services. These are freed on user changes, but just in case it somehow gets lost + the weak reference will let the memory get GCed. + + Having the reference be null when being called is a very bad sign, but we check the condition. + */ + final WeakReference<UserState> mUserStateWeakReference; + final Intent mIntent; + + private final Handler mMainHandler; + + private boolean mWasConnectedAndDied; + + + public AccessibilityServiceConnection(UserState userState, Context context, + ComponentName componentName, + AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler, + Object lock, SecurityPolicy securityPolicy, SystemSupport systemSupport, + WindowManagerInternal windowManagerInternal, + GlobalActionPerformer globalActionPerfomer) { + super(context, componentName, accessibilityServiceInfo, id, mainHandler, lock, + securityPolicy, systemSupport, windowManagerInternal, globalActionPerfomer); + mUserStateWeakReference = new WeakReference<UserState>(userState); + mIntent = new Intent().setComponent(mComponentName); + mMainHandler = mainHandler; + mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL, + com.android.internal.R.string.accessibility_binding_label); + final long identity = Binder.clearCallingIdentity(); + try { + mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, mSystemSupport.getPendingIntentActivity( + mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0)); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + public void bindLocked() { + UserState userState = mUserStateWeakReference.get(); + if (userState == null) return; + final long identity = Binder.clearCallingIdentity(); + try { + if (mService == null && mContext.bindServiceAsUser( + mIntent, this, + Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, + new UserHandle(userState.mUserId))) { + userState.getBindingServicesLocked().add(mComponentName); + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + public void unbindLocked() { + mContext.unbindService(this); + UserState userState = mUserStateWeakReference.get(); + if (userState == null) return; + userState.removeServiceLocked(this); + resetLocked(); + } + + public boolean canRetrieveInteractiveWindowsLocked() { + return mSecurityPolicy.canRetrieveWindowContentLocked(this) && mRetrieveInteractiveWindows; + } + + @Override + public void disableSelf() { + synchronized (mLock) { + UserState userState = mUserStateWeakReference.get(); + if (userState == null) return; + if (userState.mEnabledServices.remove(mComponentName)) { + final long identity = Binder.clearCallingIdentity(); + try { + mSystemSupport.persistComponentNamesToSettingLocked( + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, + userState.mEnabledServices, userState.mUserId); + } finally { + Binder.restoreCallingIdentity(identity); + } + mSystemSupport.onClientChange(false); + } + } + } + + @Override + public void onServiceConnected(ComponentName componentName, IBinder service) { + synchronized (mLock) { + if (mService != service) { + if (mService != null) { + mService.unlinkToDeath(this, 0); + } + mService = service; + try { + mService.linkToDeath(this, 0); + } catch (RemoteException re) { + Slog.e(LOG_TAG, "Failed registering death link"); + binderDied(); + return; + } + } + mServiceInterface = IAccessibilityServiceClient.Stub.asInterface(service); + UserState userState = mUserStateWeakReference.get(); + if (userState == null) return; + userState.addServiceLocked(this); + mSystemSupport.onClientChange(false); + // Initialize the service on the main handler after we're done setting up for + // the new configuration (for example, initializing the input filter). + mMainHandler.obtainMessage( + AccessibilityManagerService.MainHandler.MSG_INIT_SERVICE, this).sendToTarget(); + } + } + + public void initializeService() { + IAccessibilityServiceClient serviceInterface = null; + synchronized (mLock) { + UserState userState = mUserStateWeakReference.get(); + if (userState == null) return; + Set<ComponentName> bindingServices = userState.getBindingServicesLocked(); + if (bindingServices.contains(mComponentName) || mWasConnectedAndDied) { + bindingServices.remove(mComponentName); + mWasConnectedAndDied = false; + serviceInterface = mServiceInterface; + } + } + if (serviceInterface == null) { + binderDied(); + return; + } + try { + serviceInterface.init(this, mId, mOverlayWindowToken); + } catch (RemoteException re) { + Slog.w(LOG_TAG, "Error while setting connection for service: " + + serviceInterface, re); + binderDied(); + } + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + binderDied(); + } + + @Override + protected boolean isCalledForCurrentUserLocked() { + // We treat calls from a profile as if made by its parent as profiles + // share the accessibility state of the parent. The call below + // performs the current profile parent resolution. + final int resolvedUserId = mSecurityPolicy + .resolveCallingUserIdEnforcingPermissionsLocked(UserHandle.USER_CURRENT); + return resolvedUserId == mSystemSupport.getCurrentUserIdLocked(); + } + + @Override + public boolean setSoftKeyboardShowMode(int showMode) { + synchronized (mLock) { + if (!isCalledForCurrentUserLocked()) { + return false; + } + } + UserState userState = mUserStateWeakReference.get(); + if (userState == null) return false; + final long identity = Binder.clearCallingIdentity(); + try { + // Keep track of the last service to request a non-default show mode. The show mode + // should be restored to default should this service be disabled. + userState.mServiceChangingSoftKeyboardMode = (showMode == SHOW_MODE_AUTO) + ? null : mComponentName; + + Settings.Secure.putIntForUser(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, showMode, + userState.mUserId); + } finally { + Binder.restoreCallingIdentity(identity); + } + return true; + } + + @Override + public boolean isAccessibilityButtonAvailable() { + synchronized (mLock) { + if (!isCalledForCurrentUserLocked()) { + return false; + } + UserState userState = mUserStateWeakReference.get(); + return (userState != null) && isAccessibilityButtonAvailableLocked(userState); + } + } + + public void binderDied() { + synchronized (mLock) { + // It is possible that this service's package was force stopped during + // whose handling the death recipient is unlinked and still get a call + // on binderDied since the call was made before we unlink but was + // waiting on the lock we held during the force stop handling. + if (!isConnectedLocked()) { + return; + } + mWasConnectedAndDied = true; + resetLocked(); + if (mId == mSystemSupport.getMagnificationController().getIdOfLastServiceToMagnify()) { + mSystemSupport.getMagnificationController().resetIfNeeded(true); + } + mSystemSupport.onClientChange(false); + } + } + + public boolean isAccessibilityButtonAvailableLocked(UserState userState) { + // If the service does not request the accessibility button, it isn't available + if (!mRequestAccessibilityButton) { + return false; + } + + // If the accessibility button isn't currently shown, it cannot be available to services + if (!mSystemSupport.isAccessibilityButtonShown()) { + return false; + } + + // If magnification is on and assigned to the accessibility button, services cannot be + if (userState.mIsNavBarMagnificationEnabled + && userState.mIsNavBarMagnificationAssignedToAccessibilityButton) { + return false; + } + + int requestingServices = 0; + for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) { + final AccessibilityServiceConnection service = userState.mBoundServices.get(i); + if (service.mRequestAccessibilityButton) { + requestingServices++; + } + } + + if (requestingServices == 1) { + // If only a single service is requesting, it must be this service, and the + // accessibility button is available to it + return true; + } else { + // With more than one active service, we derive the target from the user's settings + if (userState.mServiceAssignedToAccessibilityButton == null) { + // If the user has not made an assignment, we treat the button as available to + // all services until the user interacts with the button to make an assignment + return true; + } else { + // If an assignment was made, it defines availability + return mComponentName.equals(userState.mServiceAssignedToAccessibilityButton); + } + } + } + + @Override + public boolean isCapturingFingerprintGestures() { + return (mServiceInterface != null) + && mSecurityPolicy.canCaptureFingerprintGestures(this) + && mCaptureFingerprintGestures; + } + + @Override + public void onFingerprintGestureDetectionActiveChanged(boolean active) { + if (!isCapturingFingerprintGestures()) { + return; + } + IAccessibilityServiceClient serviceInterface; + synchronized (mLock) { + serviceInterface = mServiceInterface; + } + if (serviceInterface != null) { + try { + mServiceInterface.onFingerprintCapturingGesturesChanged(active); + } catch (RemoteException e) { + } + } + } + + @Override + public void onFingerprintGesture(int gesture) { + if (!isCapturingFingerprintGestures()) { + return; + } + IAccessibilityServiceClient serviceInterface; + synchronized (mLock) { + serviceInterface = mServiceInterface; + } + if (serviceInterface != null) { + try { + mServiceInterface.onFingerprintGesture(gesture); + } catch (RemoteException e) { + } + } + } + + @Override + public void sendGesture(int sequence, ParceledListSlice gestureSteps) { + synchronized (mLock) { + if (mSecurityPolicy.canPerformGestures(this)) { + MotionEventInjector motionEventInjector = + mSystemSupport.getMotionEventInjectorLocked(); + if (motionEventInjector != null) { + motionEventInjector.injectEvents( + gestureSteps.getList(), mServiceInterface, sequence); + } else { + try { + mServiceInterface.onPerformGestureResult(sequence, false); + } catch (RemoteException re) { + Slog.e(LOG_TAG, "Error sending motion event injection failure to " + + mServiceInterface, re); + } + } + } + } + } +} diff --git a/services/accessibility/java/com/android/server/accessibility/GestureUtils.java b/services/accessibility/java/com/android/server/accessibility/GestureUtils.java index bc761914caf2..abfdb683c04c 100644 --- a/services/accessibility/java/com/android/server/accessibility/GestureUtils.java +++ b/services/accessibility/java/com/android/server/accessibility/GestureUtils.java @@ -12,32 +12,27 @@ final class GestureUtils { /* cannot be instantiated */ } - public static boolean isTap(MotionEvent down, MotionEvent up, int tapTimeSlop, - int tapDistanceSlop, int actionIndex) { - return eventsWithinTimeAndDistanceSlop(down, up, tapTimeSlop, tapDistanceSlop, actionIndex); - } - public static boolean isMultiTap(MotionEvent firstUp, MotionEvent secondUp, - int multiTapTimeSlop, int multiTapDistanceSlop, int actionIndex) { + int multiTapTimeSlop, int multiTapDistanceSlop) { + if (firstUp == null || secondUp == null) return false; return eventsWithinTimeAndDistanceSlop(firstUp, secondUp, multiTapTimeSlop, - multiTapDistanceSlop, actionIndex); + multiTapDistanceSlop); } private static boolean eventsWithinTimeAndDistanceSlop(MotionEvent first, MotionEvent second, - int timeout, int distance, int actionIndex) { + int timeout, int distance) { if (isTimedOut(first, second, timeout)) { return false; } - final double deltaMove = computeDistance(first, second, actionIndex); + final double deltaMove = distance(first, second); if (deltaMove >= distance) { return false; } return true; } - public static double computeDistance(MotionEvent first, MotionEvent second, int pointerIndex) { - return MathUtils.dist(first.getX(pointerIndex), first.getY(pointerIndex), - second.getX(pointerIndex), second.getY(pointerIndex)); + public static double distance(MotionEvent first, MotionEvent second) { + return MathUtils.dist(first.getX(), first.getY(), second.getX(), second.getY()); } public static boolean isTimedOut(MotionEvent firstUp, MotionEvent secondUp, int timeout) { @@ -54,7 +49,6 @@ final class GestureUtils { /** * Determines whether a two pointer gesture is a dragging one. * - * @param event The event with the pointer data. * @return True if the gesture is a dragging one. */ public static boolean isDraggingGesture(float firstPtrDownX, float firstPtrDownY, diff --git a/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java b/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java new file mode 100644 index 000000000000..5db6f7da8102 --- /dev/null +++ b/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java @@ -0,0 +1,156 @@ +/* + ** Copyright 2017, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +package com.android.server.accessibility; + +import android.accessibilityservice.AccessibilityService; +import android.app.StatusBarManager; +import android.content.Context; +import android.hardware.input.InputManager; +import android.os.Binder; +import android.os.SystemClock; +import android.view.InputDevice; +import android.view.KeyCharacterMap; +import android.view.KeyEvent; +import android.view.WindowManagerInternal; + +import com.android.server.LocalServices; +import com.android.server.statusbar.StatusBarManagerInternal; + +/** + * Handle the back-end of AccessibilityService#performGlobalAction + */ +public class GlobalActionPerformer { + private final WindowManagerInternal mWindowManagerService; + private final Context mContext; + + public GlobalActionPerformer(Context context, WindowManagerInternal windowManagerInternal) { + mContext = context; + mWindowManagerService = windowManagerInternal; + } + + public boolean performGlobalAction(int action) { + final long identity = Binder.clearCallingIdentity(); + try { + switch (action) { + case AccessibilityService.GLOBAL_ACTION_BACK: { + sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK); + } + return true; + case AccessibilityService.GLOBAL_ACTION_HOME: { + sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME); + } + return true; + case AccessibilityService.GLOBAL_ACTION_RECENTS: { + return openRecents(); + } + case AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS: { + expandNotifications(); + } + return true; + case AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS: { + expandQuickSettings(); + } + return true; + case AccessibilityService.GLOBAL_ACTION_POWER_DIALOG: { + showGlobalActions(); + } + return true; + case AccessibilityService.GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN: { + return toggleSplitScreen(); + } + } + return false; + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + private void sendDownAndUpKeyEvents(int keyCode) { + final long token = Binder.clearCallingIdentity(); + + // Inject down. + final long downTime = SystemClock.uptimeMillis(); + sendKeyEventIdentityCleared(keyCode, KeyEvent.ACTION_DOWN, downTime, downTime); + sendKeyEventIdentityCleared( + keyCode, KeyEvent.ACTION_UP, downTime, SystemClock.uptimeMillis()); + + Binder.restoreCallingIdentity(token); + } + + private void sendKeyEventIdentityCleared(int keyCode, int action, long downTime, long time) { + KeyEvent event = KeyEvent.obtain(downTime, time, action, keyCode, 0, 0, + KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM, + InputDevice.SOURCE_KEYBOARD, null); + InputManager.getInstance() + .injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); + event.recycle(); + } + + private void expandNotifications() { + final long token = Binder.clearCallingIdentity(); + + StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService( + android.app.Service.STATUS_BAR_SERVICE); + statusBarManager.expandNotificationsPanel(); + + Binder.restoreCallingIdentity(token); + } + + private void expandQuickSettings() { + final long token = Binder.clearCallingIdentity(); + + StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService( + android.app.Service.STATUS_BAR_SERVICE); + statusBarManager.expandSettingsPanel(); + + Binder.restoreCallingIdentity(token); + } + + private boolean openRecents() { + final long token = Binder.clearCallingIdentity(); + try { + StatusBarManagerInternal statusBarService = LocalServices.getService( + StatusBarManagerInternal.class); + if (statusBarService == null) { + return false; + } + statusBarService.toggleRecentApps(); + } finally { + Binder.restoreCallingIdentity(token); + } + return true; + } + + private void showGlobalActions() { + mWindowManagerService.showGlobalActions(); + } + + private boolean toggleSplitScreen() { + final long token = Binder.clearCallingIdentity(); + try { + StatusBarManagerInternal statusBarService = LocalServices.getService( + StatusBarManagerInternal.class); + if (statusBarService == null) { + return false; + } + statusBarService.toggleSplitScreen(); + } finally { + Binder.restoreCallingIdentity(token); + } + return true; + } +} diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java index caa74b9512d1..98b8e6b723ac 100644 --- a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java @@ -16,11 +16,6 @@ package com.android.server.accessibility; -import com.android.internal.R; -import com.android.internal.annotations.GuardedBy; -import com.android.internal.os.SomeArgs; -import com.android.server.LocalServices; - import android.animation.ValueAnimator; import android.annotation.NonNull; import android.content.BroadcastReceiver; @@ -42,6 +37,12 @@ import android.view.View; import android.view.WindowManagerInternal; import android.view.animation.DecelerateInterpolator; +import com.android.internal.R; +import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.os.SomeArgs; +import com.android.server.LocalServices; + import java.util.Locale; /** @@ -138,7 +139,7 @@ class MagnificationController implements Handler.Callback { private final WindowManagerInternal mWindowManager; // Flag indicating that we are registered with window manager. - private boolean mRegistered; + @VisibleForTesting boolean mRegistered; private boolean mUnregisterPending; @@ -148,9 +149,14 @@ class MagnificationController implements Handler.Callback { mHandler = new Handler(context.getMainLooper(), this); } - public MagnificationController(Context context, AccessibilityManagerService ams, Object lock, - Handler handler, WindowManagerInternal windowManagerInternal, - ValueAnimator valueAnimator, SettingsBridge settingsBridge) { + public MagnificationController( + Context context, + AccessibilityManagerService ams, + Object lock, + Handler handler, + WindowManagerInternal windowManagerInternal, + ValueAnimator valueAnimator, + SettingsBridge settingsBridge) { mHandler = handler; mWindowManager = windowManagerInternal; mMainThreadId = context.getMainLooper().getThread().getId(); @@ -672,8 +678,7 @@ class MagnificationController implements Handler.Callback { * Resets magnification if magnification and auto-update are both enabled. * * @param animate whether the animate the transition - * @return {@code true} if magnification was reset to the disabled state, - * {@code false} if magnification is still active + * @return whether was {@link #isMagnifying magnifying} */ boolean resetIfNeeded(boolean animate) { synchronized (mLock) { @@ -790,6 +795,19 @@ class MagnificationController implements Handler.Callback { return true; } + @Override + public String toString() { + return "MagnificationController{" + + "mCurrentMagnificationSpec=" + mCurrentMagnificationSpec + + ", mMagnificationRegion=" + mMagnificationRegion + + ", mMagnificationBounds=" + mMagnificationBounds + + ", mUserId=" + mUserId + + ", mIdOfLastServiceToMagnify=" + mIdOfLastServiceToMagnify + + ", mRegistered=" + mRegistered + + ", mUnregisterPending=" + mUnregisterPending + + '}'; + } + /** * Class responsible for animating spec on the main thread and sending spec * updates to the window manager. diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java index 7e82edaae3e5..d6452f87d155 100644 --- a/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java +++ b/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java @@ -16,6 +16,21 @@ package com.android.server.accessibility; +import static android.view.InputDevice.SOURCE_TOUCHSCREEN; +import static android.view.MotionEvent.ACTION_DOWN; +import static android.view.MotionEvent.ACTION_MOVE; +import static android.view.MotionEvent.ACTION_POINTER_DOWN; +import static android.view.MotionEvent.ACTION_POINTER_UP; +import static android.view.MotionEvent.ACTION_UP; + +import static com.android.server.accessibility.GestureUtils.distance; + +import static java.lang.Math.abs; +import static java.util.Arrays.asList; +import static java.util.Arrays.copyOfRange; + +import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -27,7 +42,6 @@ import android.util.Slog; import android.util.TypedValue; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; -import android.view.InputDevice; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.MotionEvent.PointerCoords; @@ -37,6 +51,8 @@ import android.view.ScaleGestureDetector.OnScaleGestureListener; import android.view.ViewConfiguration; import android.view.accessibility.AccessibilityEvent; +import com.android.internal.annotations.VisibleForTesting; + /** * This class handles magnification in response to touch events. * @@ -85,91 +101,109 @@ import android.view.accessibility.AccessibilityEvent; * * 7. The magnification scale will be persisted in settings and in the cloud. */ +@SuppressWarnings("WeakerAccess") class MagnificationGestureHandler implements EventStreamTransformation { private static final String LOG_TAG = "MagnificationEventHandler"; - private static final boolean DEBUG_STATE_TRANSITIONS = false; - private static final boolean DEBUG_DETECTING = false; - private static final boolean DEBUG_PANNING = false; + private static final boolean DEBUG_ALL = false; + private static final boolean DEBUG_STATE_TRANSITIONS = false || DEBUG_ALL; + private static final boolean DEBUG_DETECTING = false || DEBUG_ALL; + private static final boolean DEBUG_PANNING = false || DEBUG_ALL; - private static final int STATE_DELEGATING = 1; - private static final int STATE_DETECTING = 2; - private static final int STATE_VIEWPORT_DRAGGING = 3; - private static final int STATE_MAGNIFIED_INTERACTION = 4; + /** @see #handleMotionEventStateDelegating */ + @VisibleForTesting static final int STATE_DELEGATING = 1; + /** @see DetectingStateHandler */ + @VisibleForTesting static final int STATE_DETECTING = 2; + /** @see ViewportDraggingStateHandler */ + @VisibleForTesting static final int STATE_VIEWPORT_DRAGGING = 3; + /** @see PanningScalingStateHandler */ + @VisibleForTesting static final int STATE_PANNING_SCALING = 4; private static final float MIN_SCALE = 2.0f; private static final float MAX_SCALE = 5.0f; - private final MagnificationController mMagnificationController; - private final DetectingStateHandler mDetectingStateHandler; - private final MagnifiedContentInteractionStateHandler mMagnifiedContentInteractionStateHandler; - private final StateViewportDraggingHandler mStateViewportDraggingHandler; + @VisibleForTesting final MagnificationController mMagnificationController; + + @VisibleForTesting final DetectingStateHandler mDetectingStateHandler; + @VisibleForTesting final PanningScalingStateHandler mPanningScalingStateHandler; + @VisibleForTesting final ViewportDraggingStateHandler mViewportDraggingStateHandler; private final ScreenStateReceiver mScreenStateReceiver; - private final boolean mDetectTripleTap; - private final boolean mTriggerable; + /** + * {@code true} if this detector should detect and respond to triple-tap + * gestures for engaging and disengaging magnification, + * {@code false} if it should ignore such gestures + */ + final boolean mDetectTripleTap; + + /** + * Whether {@link #mShortcutTriggered shortcut} is enabled + */ + final boolean mDetectShortcutTrigger; - private EventStreamTransformation mNext; + EventStreamTransformation mNext; - private int mCurrentState; - private int mPreviousState; + @VisibleForTesting int mCurrentState; + @VisibleForTesting int mPreviousState; - private boolean mTranslationEnabledBeforePan; + @VisibleForTesting boolean mShortcutTriggered; - private boolean mShortcutTriggered; + /** + * Time of last {@link MotionEvent#ACTION_DOWN} while in {@link #STATE_DELEGATING} + */ + long mDelegatingStateDownTime; private PointerCoords[] mTempPointerCoords; private PointerProperties[] mTempPointerProperties; - private long mDelegatingStateDownTime; - /** * @param context Context for resolving various magnification-related resources - * @param ams AccessibilityManagerService used to obtain a {@link MagnificationController} + * @param magnificationController the {@link MagnificationController} + * * @param detectTripleTap {@code true} if this detector should detect and respond to triple-tap - * gestures for engaging and disengaging magnification, - * {@code false} if it should ignore such gestures - * @param triggerable {@code true} if this detector should be "triggerable" by some external - * shortcut invoking {@link #notifyShortcutTriggered}, {@code - * false} if it should ignore such triggers. + * gestures for engaging and disengaging magnification, + * {@code false} if it should ignore such gestures + * @param detectShortcutTrigger {@code true} if this detector should be "triggerable" by some + * external shortcut invoking {@link #notifyShortcutTriggered}, + * {@code false} if it should ignore such triggers. */ - public MagnificationGestureHandler(Context context, AccessibilityManagerService ams, - boolean detectTripleTap, boolean triggerable) { - mMagnificationController = ams.getMagnificationController(); + public MagnificationGestureHandler(Context context, + MagnificationController magnificationController, + boolean detectTripleTap, + boolean detectShortcutTrigger) { + mMagnificationController = magnificationController; + mDetectingStateHandler = new DetectingStateHandler(context); - mStateViewportDraggingHandler = new StateViewportDraggingHandler(); - mMagnifiedContentInteractionStateHandler = - new MagnifiedContentInteractionStateHandler(context); + mViewportDraggingStateHandler = new ViewportDraggingStateHandler(); + mPanningScalingStateHandler = + new PanningScalingStateHandler(context); + mDetectTripleTap = detectTripleTap; - mTriggerable = triggerable; + mDetectShortcutTrigger = detectShortcutTrigger; - if (triggerable) { + if (mDetectShortcutTrigger) { mScreenStateReceiver = new ScreenStateReceiver(context, this); mScreenStateReceiver.register(); } else { mScreenStateReceiver = null; } - transitionToState(STATE_DETECTING); + transitionTo(STATE_DETECTING); } @Override public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { - if (!event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)) { - if (mNext != null) { - mNext.onMotionEvent(event, rawEvent, policyFlags); - } - return; - } - if (!mDetectTripleTap && !mTriggerable) { - if (mNext != null) { - dispatchTransformedEvent(event, rawEvent, policyFlags); - } + if ((!mDetectTripleTap && !mDetectShortcutTrigger) + || !event.isFromSource(SOURCE_TOUCHSCREEN)) { + dispatchTransformedEvent(event, rawEvent, policyFlags); return; } - mMagnifiedContentInteractionStateHandler.onMotionEvent(event, rawEvent, policyFlags); - switch (mCurrentState) { + // Local copy to avoid dispatching the same event to more than one state handler + // in case mPanningScalingStateHandler changes mCurrentState + int currentState = mCurrentState; + mPanningScalingStateHandler.onMotionEvent(event, rawEvent, policyFlags); + switch (currentState) { case STATE_DELEGATING: { handleMotionEventStateDelegating(event, rawEvent, policyFlags); } @@ -179,17 +213,17 @@ class MagnificationGestureHandler implements EventStreamTransformation { } break; case STATE_VIEWPORT_DRAGGING: { - mStateViewportDraggingHandler.onMotionEvent(event, rawEvent, policyFlags); + mViewportDraggingStateHandler.onMotionEvent(event, rawEvent, policyFlags); } break; - case STATE_MAGNIFIED_INTERACTION: { - // mMagnifiedContentInteractionStateHandler handles events only + case STATE_PANNING_SCALING: { + // mPanningScalingStateHandler handles events only // if this is the current state since it uses ScaleGestureDetector // and a GestureDetector which need well formed event stream. } break; default: { - throw new IllegalStateException("Unknown state: " + mCurrentState); + throw new IllegalStateException("Unknown state: " + currentState); } } } @@ -215,8 +249,8 @@ class MagnificationGestureHandler implements EventStreamTransformation { @Override public void clearEvents(int inputSource) { - if (inputSource == InputDevice.SOURCE_TOUCHSCREEN) { - clear(); + if (inputSource == SOURCE_TOUCHSCREEN) { + clearAndTransitionToStateDetecting(); } if (mNext != null) { @@ -229,20 +263,25 @@ class MagnificationGestureHandler implements EventStreamTransformation { if (mScreenStateReceiver != null) { mScreenStateReceiver.unregister(); } - clear(); + clearAndTransitionToStateDetecting(); } void notifyShortcutTriggered() { - if (mTriggerable) { - if (mMagnificationController.resetIfNeeded(true)) { - clear(); + if (mDetectShortcutTrigger) { + boolean wasMagnifying = mMagnificationController.resetIfNeeded(/* animate */ true); + if (wasMagnifying) { + clearAndTransitionToStateDetecting(); } else { - setMagnificationShortcutTriggered(!mShortcutTriggered); + toggleShortcutTriggered(); } } } - private void setMagnificationShortcutTriggered(boolean state) { + private void toggleShortcutTriggered() { + setShortcutTriggered(!mShortcutTriggered); + } + + private void setShortcutTriggered(boolean state) { if (mShortcutTriggered == state) { return; } @@ -251,27 +290,25 @@ class MagnificationGestureHandler implements EventStreamTransformation { mMagnificationController.setForceShowMagnifiableBounds(state); } - private void clear() { + void clearAndTransitionToStateDetecting() { + setShortcutTriggered(false); mCurrentState = STATE_DETECTING; - setMagnificationShortcutTriggered(false); mDetectingStateHandler.clear(); - mStateViewportDraggingHandler.clear(); - mMagnifiedContentInteractionStateHandler.clear(); + mViewportDraggingStateHandler.clear(); + mPanningScalingStateHandler.clear(); } private void handleMotionEventStateDelegating(MotionEvent event, MotionEvent rawEvent, int policyFlags) { - switch (event.getActionMasked()) { - case MotionEvent.ACTION_DOWN: { - mDelegatingStateDownTime = event.getDownTime(); - } - break; - case MotionEvent.ACTION_UP: { - if (mDetectingStateHandler.mDelayedEventQueue == null) { - transitionToState(STATE_DETECTING); - } - } - break; + if (event.getActionMasked() == ACTION_UP) { + transitionTo(STATE_DETECTING); + } + delegateEvent(event, rawEvent, policyFlags); + } + + void delegateEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + mDelegatingStateDownTime = event.getDownTime(); } if (mNext != null) { // We cache some events to see if the user wants to trigger magnification. @@ -287,13 +324,15 @@ class MagnificationGestureHandler implements EventStreamTransformation { private void dispatchTransformedEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { - // If the event is within the magnified portion of the screen we have + if (mNext == null) return; // Nowhere to dispatch to + + // If the touchscreen event is within the magnified portion of the screen we have // to change its location to be where the user thinks he is poking the // UI which may have been magnified and panned. - final float eventX = event.getX(); - final float eventY = event.getY(); if (mMagnificationController.isMagnifying() - && mMagnificationController.magnificationRegionContains(eventX, eventY)) { + && event.isFromSource(SOURCE_TOUCHSCREEN) + && mMagnificationController.magnificationRegionContains( + event.getX(), event.getY())) { final float scale = mMagnificationController.getScale(); final float scaledOffsetX = mMagnificationController.getOffsetX(); final float scaledOffsetY = mMagnificationController.getOffsetY(); @@ -347,34 +386,27 @@ class MagnificationGestureHandler implements EventStreamTransformation { return mTempPointerProperties; } - private void transitionToState(int state) { + private void transitionTo(int state) { if (DEBUG_STATE_TRANSITIONS) { - switch (state) { - case STATE_DELEGATING: { - Slog.i(LOG_TAG, "mCurrentState: STATE_DELEGATING"); - } - break; - case STATE_DETECTING: { - Slog.i(LOG_TAG, "mCurrentState: STATE_DETECTING"); - } - break; - case STATE_VIEWPORT_DRAGGING: { - Slog.i(LOG_TAG, "mCurrentState: STATE_VIEWPORT_DRAGGING"); - } - break; - case STATE_MAGNIFIED_INTERACTION: { - Slog.i(LOG_TAG, "mCurrentState: STATE_MAGNIFIED_INTERACTION"); - } - break; - default: { - throw new IllegalArgumentException("Unknown state: " + state); - } - } + Slog.i(LOG_TAG, (stateToString(mCurrentState) + " -> " + stateToString(state) + + " at " + asList(copyOfRange(new RuntimeException().getStackTrace(), 1, 5))) + .replace(getClass().getName(), "")); } mPreviousState = mCurrentState; mCurrentState = state; } + private static String stateToString(int state) { + switch (state) { + case STATE_DELEGATING: return "STATE_DELEGATING"; + case STATE_DETECTING: return "STATE_DETECTING"; + case STATE_VIEWPORT_DRAGGING: return "STATE_VIEWPORT_DRAGGING"; + case STATE_PANNING_SCALING: return "STATE_PANNING_SCALING"; + case 0: return "0"; + default: throw new IllegalArgumentException("Unknown state: " + state); + } + } + private interface MotionEventHandler { void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags); @@ -384,21 +416,20 @@ class MagnificationGestureHandler implements EventStreamTransformation { /** * This class determines if the user is performing a scale or pan gesture. + * + * @see #STATE_PANNING_SCALING */ - private final class MagnifiedContentInteractionStateHandler extends SimpleOnGestureListener + final class PanningScalingStateHandler extends SimpleOnGestureListener implements OnScaleGestureListener, MotionEventHandler { private final ScaleGestureDetector mScaleGestureDetector; - private final GestureDetector mGestureDetector; + final float mScalingThreshold; - private final float mScalingThreshold; + float mInitialScaleFactor = -1; + boolean mScaling; - private float mInitialScaleFactor = -1; - - private boolean mScaling; - - public MagnifiedContentInteractionStateHandler(Context context) { + public PanningScalingStateHandler(Context context) { final TypedValue scaleValue = new TypedValue(); context.getResources().getValue( com.android.internal.R.dimen.config_screen_magnification_scaling_threshold, @@ -411,26 +442,39 @@ class MagnificationGestureHandler implements EventStreamTransformation { @Override public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { + // Dispatches #onScaleBegin, #onScale, #onScaleEnd mScaleGestureDetector.onTouchEvent(event); + // Dispatches #onScroll mGestureDetector.onTouchEvent(event); - if (mCurrentState != STATE_MAGNIFIED_INTERACTION) { + + if (mCurrentState != STATE_PANNING_SCALING) { return; } - if (event.getActionMasked() == MotionEvent.ACTION_UP) { - clear(); - mMagnificationController.persistScale(); - if (mPreviousState == STATE_VIEWPORT_DRAGGING) { - transitionToState(STATE_VIEWPORT_DRAGGING); - } else { - transitionToState(STATE_DETECTING); - } + + int action = event.getActionMasked(); + if (action == ACTION_POINTER_UP + && event.getPointerCount() == 2 // includes the pointer currently being released + && mPreviousState == STATE_VIEWPORT_DRAGGING) { + + persistScaleAndTransitionTo(STATE_VIEWPORT_DRAGGING); + + } else if (action == ACTION_UP) { + + persistScaleAndTransitionTo(STATE_DETECTING); + } } + public void persistScaleAndTransitionTo(int state) { + mMagnificationController.persistScale(); + clear(); + transitionTo(state); + } + @Override - public boolean onScroll(MotionEvent first, MotionEvent second, float distanceX, - float distanceY) { - if (mCurrentState != STATE_MAGNIFIED_INTERACTION) { + public boolean onScroll(MotionEvent first, MotionEvent second, + float distanceX, float distanceY) { + if (mCurrentState != STATE_PANNING_SCALING) { return true; } if (DEBUG_PANNING) { @@ -447,14 +491,15 @@ class MagnificationGestureHandler implements EventStreamTransformation { if (!mScaling) { if (mInitialScaleFactor < 0) { mInitialScaleFactor = detector.getScaleFactor(); + return false; + } + final float deltaScale = detector.getScaleFactor() - mInitialScaleFactor; + if (abs(deltaScale) > mScalingThreshold) { + mScaling = true; + return true; } else { - final float deltaScale = detector.getScaleFactor() - mInitialScaleFactor; - if (Math.abs(deltaScale) > mScalingThreshold) { - mScaling = true; - return true; - } + return false; } - return false; } final float initialScale = mMagnificationController.getScale(); @@ -485,7 +530,7 @@ class MagnificationGestureHandler implements EventStreamTransformation { @Override public boolean onScaleBegin(ScaleGestureDetector detector) { - return (mCurrentState == STATE_MAGNIFIED_INTERACTION); + return (mCurrentState == STATE_PANNING_SCALING); } @Override @@ -498,60 +543,65 @@ class MagnificationGestureHandler implements EventStreamTransformation { mInitialScaleFactor = -1; mScaling = false; } + + @Override + public String toString() { + return "MagnifiedContentInteractionStateHandler{" + + "mInitialScaleFactor=" + mInitialScaleFactor + + ", mScaling=" + mScaling + + '}'; + } } /** * This class handles motion events when the event dispatcher has * determined that the user is performing a single-finger drag of the * magnification viewport. + * + * @see #STATE_VIEWPORT_DRAGGING */ - private final class StateViewportDraggingHandler implements MotionEventHandler { + final class ViewportDraggingStateHandler implements MotionEventHandler { + /** Whether to disable zoom after dragging ends */ + boolean mZoomedInBeforeDrag; private boolean mLastMoveOutsideMagnifiedRegion; @Override public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { final int action = event.getActionMasked(); switch (action) { - case MotionEvent.ACTION_DOWN: { - throw new IllegalArgumentException("Unexpected event type: ACTION_DOWN"); - } - case MotionEvent.ACTION_POINTER_DOWN: { + case ACTION_POINTER_DOWN: { clear(); - transitionToState(STATE_MAGNIFIED_INTERACTION); + transitionTo(STATE_PANNING_SCALING); } break; - case MotionEvent.ACTION_MOVE: { + case ACTION_MOVE: { if (event.getPointerCount() != 1) { throw new IllegalStateException("Should have one pointer down."); } final float eventX = event.getX(); final float eventY = event.getY(); if (mMagnificationController.magnificationRegionContains(eventX, eventY)) { - if (mLastMoveOutsideMagnifiedRegion) { - mLastMoveOutsideMagnifiedRegion = false; - mMagnificationController.setCenter(eventX, eventY, true, - AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID); - } else { - mMagnificationController.setCenter(eventX, eventY, false, - AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID); - } + mMagnificationController.setCenter(eventX, eventY, + /* animate */ mLastMoveOutsideMagnifiedRegion, + AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID); + mLastMoveOutsideMagnifiedRegion = false; } else { mLastMoveOutsideMagnifiedRegion = true; } } break; - case MotionEvent.ACTION_UP: { - if (!mTranslationEnabledBeforePan) { - mMagnificationController.reset(true); - } + case ACTION_UP: { + if (!mZoomedInBeforeDrag) zoomOff(); clear(); - transitionToState(STATE_DETECTING); + transitionTo(STATE_DETECTING); } break; - case MotionEvent.ACTION_POINTER_UP: { + + case ACTION_DOWN: + case ACTION_POINTER_UP: { throw new IllegalArgumentException( - "Unexpected event type: ACTION_POINTER_UP"); + "Unexpected event type: " + MotionEvent.actionToString(action)); } } } @@ -560,211 +610,224 @@ class MagnificationGestureHandler implements EventStreamTransformation { public void clear() { mLastMoveOutsideMagnifiedRegion = false; } + + @Override + public String toString() { + return "ViewportDraggingStateHandler{" + + "mZoomedInBeforeDrag=" + mZoomedInBeforeDrag + + ", mLastMoveOutsideMagnifiedRegion=" + mLastMoveOutsideMagnifiedRegion + + '}'; + } } /** * This class handles motion events when the event dispatch has not yet * determined what the user is doing. It watches for various tap events. + * + * @see #STATE_DETECTING */ - private final class DetectingStateHandler implements MotionEventHandler { - - private static final int MESSAGE_ON_ACTION_TAP_AND_HOLD = 1; + final class DetectingStateHandler implements MotionEventHandler, Handler.Callback { + private static final int MESSAGE_ON_TRIPLE_TAP_AND_HOLD = 1; private static final int MESSAGE_TRANSITION_TO_DELEGATING_STATE = 2; - private static final int ACTION_TAP_COUNT = 3; - - private final int mTapTimeSlop = ViewConfiguration.getJumpTapTimeout(); - - private final int mMultiTapTimeSlop; - - private final int mTapDistanceSlop; - - private final int mMultiTapDistanceSlop; + final int mLongTapMinDelay = ViewConfiguration.getJumpTapTimeout(); + final int mSwipeMinDistance; + final int mMultiTapMaxDelay; + final int mMultiTapMaxDistance; private MotionEventInfo mDelayedEventQueue; + MotionEvent mLastDown; + private MotionEvent mPreLastDown; + private MotionEvent mLastUp; + private MotionEvent mPreLastUp; - private MotionEvent mLastDownEvent; - - private MotionEvent mLastTapUpEvent; - - private int mTapCount; + Handler mHandler = new Handler(this); public DetectingStateHandler(Context context) { - mMultiTapTimeSlop = ViewConfiguration.getDoubleTapTimeout() + mMultiTapMaxDelay = ViewConfiguration.getDoubleTapTimeout() + context.getResources().getInteger( com.android.internal.R.integer.config_screen_magnification_multi_tap_adjustment); - mTapDistanceSlop = ViewConfiguration.get(context).getScaledTouchSlop(); - mMultiTapDistanceSlop = ViewConfiguration.get(context).getScaledDoubleTapSlop(); - } - - private final Handler mHandler = new Handler() { - @Override - public void handleMessage(Message message) { - final int type = message.what; - switch (type) { - case MESSAGE_ON_ACTION_TAP_AND_HOLD: { - MotionEvent event = (MotionEvent) message.obj; - final int policyFlags = message.arg1; - onActionTapAndHold(event, policyFlags); - } - break; - case MESSAGE_TRANSITION_TO_DELEGATING_STATE: { - transitionToState(STATE_DELEGATING); - sendDelayedMotionEvents(); - clear(); - } - break; - default: { - throw new IllegalArgumentException("Unknown message type: " + type); - } + mSwipeMinDistance = ViewConfiguration.get(context).getScaledTouchSlop(); + mMultiTapMaxDistance = ViewConfiguration.get(context).getScaledDoubleTapSlop(); + } + + @Override + public boolean handleMessage(Message message) { + final int type = message.what; + switch (type) { + case MESSAGE_ON_TRIPLE_TAP_AND_HOLD: { + onTripleTapAndHold(/* down */ (MotionEvent) message.obj); + } + break; + case MESSAGE_TRANSITION_TO_DELEGATING_STATE: { + transitionToDelegatingState(/* andClear */ true); + } + break; + default: { + throw new IllegalArgumentException("Unknown message type: " + type); } } - }; + return true; + } @Override public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { cacheDelayedMotionEvent(event, rawEvent, policyFlags); - final int action = event.getActionMasked(); - switch (action) { + switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: { + mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE); + if (!mMagnificationController.magnificationRegionContains( event.getX(), event.getY())) { - transitionToDelegatingState(!mShortcutTriggered); - return; - } - if (mShortcutTriggered) { - Message message = mHandler.obtainMessage(MESSAGE_ON_ACTION_TAP_AND_HOLD, - policyFlags, 0, event); - mHandler.sendMessageDelayed(message, - ViewConfiguration.getLongPressTimeout()); - return; - } - if (mDetectTripleTap) { - if ((mTapCount == ACTION_TAP_COUNT - 1) && (mLastDownEvent != null) - && GestureUtils.isMultiTap(mLastDownEvent, event, mMultiTapTimeSlop, - mMultiTapDistanceSlop, 0)) { - Message message = mHandler.obtainMessage(MESSAGE_ON_ACTION_TAP_AND_HOLD, - policyFlags, 0, event); - mHandler.sendMessageDelayed(message, - ViewConfiguration.getLongPressTimeout()); - } else if (mTapCount < ACTION_TAP_COUNT) { - Message message = mHandler.obtainMessage( - MESSAGE_TRANSITION_TO_DELEGATING_STATE); - mHandler.sendMessageDelayed(message, mMultiTapTimeSlop); - } - clearLastDownEvent(); - mLastDownEvent = MotionEvent.obtain(event); - } else if (mMagnificationController.isMagnifying()) { - // If magnified, consume an ACTION_DOWN until mMultiTapTimeSlop or - // mTapDistanceSlop is reached to ensure MAGNIFIED_INTERACTION is reachable. - Message message = mHandler.obtainMessage( - MESSAGE_TRANSITION_TO_DELEGATING_STATE); - mHandler.sendMessageDelayed(message, mMultiTapTimeSlop); - return; + + transitionToDelegatingState(/* andClear */ !mShortcutTriggered); + + } else if (isMultiTapTriggered(2 /* taps */)) { + + // 3tap and hold + delayedTransitionToDraggingState(event); + + } else if (mDetectTripleTap + // If magnified, delay an ACTION_DOWN for mMultiTapMaxDelay + // to ensure reachability of + // STATE_PANNING_SCALING(triggerable with ACTION_POINTER_DOWN) + || mMagnificationController.isMagnifying()) { + + delayedTransitionToDelegatingState(); + } else { - transitionToDelegatingState(true); - return; + + // Delegate pending events without delay + transitionToDelegatingState(/* andClear */ true); } } break; - case MotionEvent.ACTION_POINTER_DOWN: { + case ACTION_POINTER_DOWN: { if (mMagnificationController.isMagnifying()) { - mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE); - transitionToState(STATE_MAGNIFIED_INTERACTION); + transitionTo(STATE_PANNING_SCALING); clear(); } else { - transitionToDelegatingState(true); + transitionToDelegatingState(/* andClear */ true); } } break; - case MotionEvent.ACTION_MOVE: { - if (mLastDownEvent != null && mTapCount < ACTION_TAP_COUNT - 1) { - final double distance = GestureUtils.computeDistance(mLastDownEvent, - event, 0); - if (Math.abs(distance) > mTapDistanceSlop) { - transitionToDelegatingState(true); - } + case ACTION_MOVE: { + if (isFingerDown() + && distance(mLastDown, /* move */ event) > mSwipeMinDistance + // For convenience, viewport dragging on 3tap&hold takes precedence + // over insta-delegating on 3tap&swipe + // (which is a rare combo to be used aside from magnification) + && !isMultiTapTriggered(2 /* taps */)) { + + // Swipe detected - delegate skipping timeout + transitionToDelegatingState(/* andClear */ true); } } break; - case MotionEvent.ACTION_UP: { + case ACTION_UP: { + + mHandler.removeMessages(MESSAGE_ON_TRIPLE_TAP_AND_HOLD); + if (!mMagnificationController.magnificationRegionContains( event.getX(), event.getY())) { - transitionToDelegatingState(!mShortcutTriggered); - return; - } - if (mShortcutTriggered) { - clear(); - onActionTap(event, policyFlags); - return; - } - if (mLastDownEvent == null) { - return; - } - mHandler.removeMessages(MESSAGE_ON_ACTION_TAP_AND_HOLD); - if (!GestureUtils.isTap(mLastDownEvent, event, mTapTimeSlop, - mTapDistanceSlop, 0)) { - transitionToDelegatingState(true); - return; - } - if (mLastTapUpEvent != null && !GestureUtils.isMultiTap( - mLastTapUpEvent, event, mMultiTapTimeSlop, mMultiTapDistanceSlop, 0)) { - transitionToDelegatingState(true); - return; - } - mTapCount++; - if (DEBUG_DETECTING) { - Slog.i(LOG_TAG, "Tap count:" + mTapCount); - } - if (mTapCount == ACTION_TAP_COUNT) { - clear(); - onActionTap(event, policyFlags); - return; + + transitionToDelegatingState(/* andClear */ !mShortcutTriggered); + + } else if (isMultiTapTriggered(3 /* taps */)) { + + onTripleTap(/* up */ event); + + } else if ( + // Possible to be false on: 3tap&drag -> scale -> PTR_UP -> UP + isFingerDown() + //TODO long tap should never happen here + && (timeBetween(mLastDown, /* mLastUp */ event) >= mLongTapMinDelay) + || distance(mLastDown, /* mLastUp */ event) + >= mSwipeMinDistance) { + + transitionToDelegatingState(/* andClear */ true); + } - clearLastTapUpEvent(); - mLastTapUpEvent = MotionEvent.obtain(event); - } - break; - case MotionEvent.ACTION_POINTER_UP: { - /* do nothing */ } break; } } - @Override - public void clear() { - setMagnificationShortcutTriggered(false); - mHandler.removeMessages(MESSAGE_ON_ACTION_TAP_AND_HOLD); - mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE); - clearTapDetectionState(); - clearDelayedMotionEvents(); + public boolean isMultiTapTriggered(int numTaps) { + + // Shortcut acts as the 2 initial taps + if (mShortcutTriggered) return tapCount() + 2 >= numTaps; + + return mDetectTripleTap + && tapCount() >= numTaps + && isMultiTap(mPreLastDown, mLastDown) + && isMultiTap(mPreLastUp, mLastUp); } - private void clearTapDetectionState() { - mTapCount = 0; - clearLastTapUpEvent(); - clearLastDownEvent(); + private boolean isMultiTap(MotionEvent first, MotionEvent second) { + return GestureUtils.isMultiTap(first, second, mMultiTapMaxDelay, mMultiTapMaxDistance); } - private void clearLastTapUpEvent() { - if (mLastTapUpEvent != null) { - mLastTapUpEvent.recycle(); - mLastTapUpEvent = null; - } + public boolean isFingerDown() { + return mLastDown != null; } - private void clearLastDownEvent() { - if (mLastDownEvent != null) { - mLastDownEvent.recycle(); - mLastDownEvent = null; - } + private long timeBetween(@Nullable MotionEvent a, @Nullable MotionEvent b) { + if (a == null && b == null) return 0; + return abs(timeOf(a) - timeOf(b)); + } + + /** + * Nullsafe {@link MotionEvent#getEventTime} that interprets null event as something that + * has happened long enough ago to be gone from the event queue. + * Thus the time for a null event is a small number, that is below any other non-null + * event's time. + * + * @return {@link MotionEvent#getEventTime}, or {@link Long#MIN_VALUE} if the event is null + */ + private long timeOf(@Nullable MotionEvent event) { + return event != null ? event.getEventTime() : Long.MIN_VALUE; + } + + public int tapCount() { + return MotionEventInfo.countOf(mDelayedEventQueue, ACTION_UP); } + /** -> {@link #STATE_DELEGATING} */ + public void delayedTransitionToDelegatingState() { + mHandler.sendEmptyMessageDelayed( + MESSAGE_TRANSITION_TO_DELEGATING_STATE, + mMultiTapMaxDelay); + } + + /** -> {@link #STATE_VIEWPORT_DRAGGING} */ + public void delayedTransitionToDraggingState(MotionEvent event) { + mHandler.sendMessageDelayed( + mHandler.obtainMessage(MESSAGE_ON_TRIPLE_TAP_AND_HOLD, event), + ViewConfiguration.getLongPressTimeout()); + } + + @Override + public void clear() { + setShortcutTriggered(false); + mHandler.removeMessages(MESSAGE_ON_TRIPLE_TAP_AND_HOLD); + mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE); + clearDelayedMotionEvents(); + } + + private void cacheDelayedMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { + if (event.getActionMasked() == ACTION_DOWN) { + mPreLastDown = mLastDown; + mLastDown = event; + } else if (event.getActionMasked() == ACTION_UP) { + mPreLastUp = mLastUp; + mLastUp = event; + } + MotionEventInfo info = MotionEventInfo.obtain(event, rawEvent, policyFlags); if (mDelayedEventQueue == null) { @@ -782,8 +845,13 @@ class MagnificationGestureHandler implements EventStreamTransformation { while (mDelayedEventQueue != null) { MotionEventInfo info = mDelayedEventQueue; mDelayedEventQueue = info.mNext; - MagnificationGestureHandler.this.onMotionEvent(info.mEvent, info.mRawEvent, - info.mPolicyFlags); + + // Because MagnifiedInteractionStateHandler requires well-formed event stream + mPanningScalingStateHandler.onMotionEvent( + info.event, info.rawEvent, info.policyFlags); + + delegateEvent(info.event, info.rawEvent, info.policyFlags); + info.recycle(); } } @@ -794,91 +862,136 @@ class MagnificationGestureHandler implements EventStreamTransformation { mDelayedEventQueue = info.mNext; info.recycle(); } + mPreLastDown = null; + mPreLastUp = null; + mLastDown = null; + mLastUp = null; } - private void transitionToDelegatingState(boolean andClear) { - transitionToState(STATE_DELEGATING); + void transitionToDelegatingState(boolean andClear) { + transitionTo(STATE_DELEGATING); sendDelayedMotionEvents(); - if (andClear) { - clear(); - } + if (andClear) clear(); } - private void onActionTap(MotionEvent up, int policyFlags) { + private void onTripleTap(MotionEvent up) { + if (DEBUG_DETECTING) { - Slog.i(LOG_TAG, "onActionTap()"); + Slog.i(LOG_TAG, "onTripleTap(); delayed: " + + MotionEventInfo.toString(mDelayedEventQueue)); } + clear(); - if (!mMagnificationController.isMagnifying()) { - final float targetScale = mMagnificationController.getPersistedScale(); - final float scale = MathUtils.constrain(targetScale, MIN_SCALE, MAX_SCALE); - mMagnificationController.setScaleAndCenter(scale, up.getX(), up.getY(), true, - AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID); + // Toggle zoom + if (mMagnificationController.isMagnifying()) { + zoomOff(); } else { - mMagnificationController.reset(true); + zoomOn(up.getX(), up.getY()); } } - private void onActionTapAndHold(MotionEvent down, int policyFlags) { - if (DEBUG_DETECTING) { - Slog.i(LOG_TAG, "onActionTapAndHold()"); - } + void onTripleTapAndHold(MotionEvent down) { + if (DEBUG_DETECTING) Slog.i(LOG_TAG, "onTripleTapAndHold()"); clear(); - mTranslationEnabledBeforePan = mMagnificationController.isMagnifying(); - final float targetScale = mMagnificationController.getPersistedScale(); - final float scale = MathUtils.constrain(targetScale, MIN_SCALE, MAX_SCALE); - mMagnificationController.setScaleAndCenter(scale, down.getX(), down.getY(), true, - AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID); + mViewportDraggingStateHandler.mZoomedInBeforeDrag = + mMagnificationController.isMagnifying(); + + zoomOn(down.getX(), down.getY()); - transitionToState(STATE_VIEWPORT_DRAGGING); + transitionTo(STATE_VIEWPORT_DRAGGING); + } + + @Override + public String toString() { + return "DetectingStateHandler{" + + "tapCount()=" + tapCount() + + ", mDelayedEventQueue=" + MotionEventInfo.toString(mDelayedEventQueue) + + '}'; } } + private void zoomOn(float centerX, float centerY) { + final float scale = MathUtils.constrain( + mMagnificationController.getPersistedScale(), + MIN_SCALE, MAX_SCALE); + mMagnificationController.setScaleAndCenter( + scale, centerX, centerY, + /* animate */ true, + AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID); + } + + private void zoomOff() { + mMagnificationController.reset(/* animate */ true); + } + + private static MotionEvent recycleAndNullify(@Nullable MotionEvent event) { + if (event != null) { + event.recycle(); + } + return null; + } + + @Override + public String toString() { + return "MagnificationGestureHandler{" + + "mDetectingStateHandler=" + mDetectingStateHandler + + ", mMagnifiedInteractionStateHandler=" + mPanningScalingStateHandler + + ", mViewportDraggingStateHandler=" + mViewportDraggingStateHandler + + ", mDetectTripleTap=" + mDetectTripleTap + + ", mDetectShortcutTrigger=" + mDetectShortcutTrigger + + ", mCurrentState=" + stateToString(mCurrentState) + + ", mPreviousState=" + stateToString(mPreviousState) + + ", mShortcutTriggered=" + mShortcutTriggered + + ", mDelegatingStateDownTime=" + mDelegatingStateDownTime + + ", mMagnificationController=" + mMagnificationController + + '}'; + } + private static final class MotionEventInfo { private static final int MAX_POOL_SIZE = 10; - private static final Object sLock = new Object(); - private static MotionEventInfo sPool; - private static int sPoolSize; private MotionEventInfo mNext; - private boolean mInPool; - public MotionEvent mEvent; - - public MotionEvent mRawEvent; - - public int mPolicyFlags; + public MotionEvent event; + public MotionEvent rawEvent; + public int policyFlags; public static MotionEventInfo obtain(MotionEvent event, MotionEvent rawEvent, int policyFlags) { synchronized (sLock) { - MotionEventInfo info; - if (sPoolSize > 0) { - sPoolSize--; - info = sPool; - sPool = info.mNext; - info.mNext = null; - info.mInPool = false; - } else { - info = new MotionEventInfo(); - } + MotionEventInfo info = obtainInternal(); info.initialize(event, rawEvent, policyFlags); return info; } } + @NonNull + private static MotionEventInfo obtainInternal() { + MotionEventInfo info; + if (sPoolSize > 0) { + sPoolSize--; + info = sPool; + sPool = info.mNext; + info.mNext = null; + info.mInPool = false; + } else { + info = new MotionEventInfo(); + } + return info; + } + private void initialize(MotionEvent event, MotionEvent rawEvent, int policyFlags) { - mEvent = MotionEvent.obtain(event); - mRawEvent = MotionEvent.obtain(rawEvent); - mPolicyFlags = policyFlags; + this.event = MotionEvent.obtain(event); + this.rawEvent = MotionEvent.obtain(rawEvent); + this.policyFlags = policyFlags; } public void recycle() { @@ -897,11 +1010,22 @@ class MagnificationGestureHandler implements EventStreamTransformation { } private void clear() { - mEvent.recycle(); - mEvent = null; - mRawEvent.recycle(); - mRawEvent = null; - mPolicyFlags = 0; + event = recycleAndNullify(event); + rawEvent = recycleAndNullify(rawEvent); + policyFlags = 0; + } + + static int countOf(MotionEventInfo info, int eventType) { + if (info == null) return 0; + return (info.event.getAction() == eventType ? 1 : 0) + + countOf(info.mNext, eventType); + } + + public static String toString(MotionEventInfo info) { + return info == null + ? "" + : MotionEvent.actionToString(info.event.getAction()).replace("ACTION_", "") + + " " + MotionEventInfo.toString(info.mNext); } } @@ -927,7 +1051,7 @@ class MagnificationGestureHandler implements EventStreamTransformation { @Override public void onReceive(Context context, Intent intent) { - mGestureHandler.setMagnificationShortcutTriggered(false); + mGestureHandler.setShortcutTriggered(false); } } } diff --git a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java new file mode 100644 index 000000000000..3a1de98e739a --- /dev/null +++ b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java @@ -0,0 +1,244 @@ +/* + ** Copyright 2017, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +package com.android.server.accessibility; + +import android.accessibilityservice.AccessibilityServiceInfo; +import android.accessibilityservice.IAccessibilityServiceClient; +import android.app.UiAutomation; +import android.content.ComponentName; +import android.content.Context; +import android.os.Handler; +import android.os.IBinder; +import android.os.IBinder.DeathRecipient; +import android.os.RemoteException; +import android.util.Slog; +import android.view.WindowManagerInternal; +import android.view.accessibility.AccessibilityEvent; + +import java.io.FileDescriptor; +import java.io.PrintWriter; + +/** + * Class to manage UiAutomation. + */ +class UiAutomationManager { + private static final ComponentName COMPONENT_NAME = + new ComponentName("com.android.server.accessibility", "UiAutomation"); + private static final String LOG_TAG = "UiAutomationManager"; + + private UiAutomationService mUiAutomationService; + + private AccessibilityServiceInfo mUiAutomationServiceInfo; + + private int mUiAutomationFlags; + + private IBinder mUiAutomationServiceOwner; + private final DeathRecipient mUiAutomationSerivceOwnerDeathRecipient = + new DeathRecipient() { + @Override + public void binderDied() { + mUiAutomationServiceOwner.unlinkToDeath(this, 0); + mUiAutomationServiceOwner = null; + if (mUiAutomationService != null) { + destroyUiAutomationService(); + } + } + }; + + /** + * Register a UiAutomation. Only one may be registered at a time. + * + * @param owner A binder object owned by the process that owns the UiAutomation to be + * registered. + * @param serviceClient The UiAutomation's service interface. + * @param accessibilityServiceInfo The UiAutomation's service info + * @param flags The UiAutomation's flags + * @param id The id for the service connection + */ + void registerUiTestAutomationServiceLocked(IBinder owner, + IAccessibilityServiceClient serviceClient, + Context context, AccessibilityServiceInfo accessibilityServiceInfo, + int id, Handler mainHandler, Object lock, + AccessibilityManagerService.SecurityPolicy securityPolicy, + AccessibilityClientConnection.SystemSupport systemSupport, + WindowManagerInternal windowManagerInternal, + GlobalActionPerformer globalActionPerfomer, int flags) { + accessibilityServiceInfo.setComponentName(COMPONENT_NAME); + + if (mUiAutomationService != null) { + throw new IllegalStateException("UiAutomationService " + serviceClient + + "already registered!"); + } + + try { + owner.linkToDeath(mUiAutomationSerivceOwnerDeathRecipient, 0); + } catch (RemoteException re) { + Slog.e(LOG_TAG, "Couldn't register for the death of a UiTestAutomationService!", re); + return; + } + + mUiAutomationService = new UiAutomationService(context, accessibilityServiceInfo, id, + mainHandler, lock, securityPolicy, systemSupport, windowManagerInternal, + globalActionPerfomer); + mUiAutomationServiceOwner = owner; + mUiAutomationFlags = flags; + mUiAutomationServiceInfo = accessibilityServiceInfo; + mUiAutomationService.mServiceInterface = serviceClient; + mUiAutomationService.onAdded(); + try { + mUiAutomationService.mServiceInterface.asBinder().linkToDeath(mUiAutomationService, 0); + } catch (RemoteException re) { + Slog.e(LOG_TAG, "Failed registering death link: " + re); + destroyUiAutomationService(); + return; + } + + mUiAutomationService.connectServiceUnknownThread(); + } + + void unregisterUiTestAutomationServiceLocked(IAccessibilityServiceClient serviceClient) { + if ((mUiAutomationService == null) + || (serviceClient == null) + || (mUiAutomationService.mServiceInterface == null) + || (serviceClient.asBinder() + != mUiAutomationService.mServiceInterface.asBinder())) { + throw new IllegalStateException("UiAutomationService " + serviceClient + + " not registered!"); + } + + destroyUiAutomationService(); + } + + void sendAccessibilityEventLocked(AccessibilityEvent event) { + if (mUiAutomationService != null) { + mUiAutomationService.notifyAccessibilityEvent(event); + } + } + + boolean isUiAutomationRunningLocked() { + return (mUiAutomationService != null); + } + + boolean suppressingAccessibilityServicesLocked() { + return (mUiAutomationService != null) && ((mUiAutomationFlags + & UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) == 0); + } + + boolean isTouchExplorationEnabledLocked() { + return (mUiAutomationService != null) + && mUiAutomationService.mRequestTouchExplorationMode; + } + + boolean canRetrieveInteractiveWindowsLocked() { + return (mUiAutomationService != null) && mUiAutomationService.mRetrieveInteractiveWindows; + } + + int getRequestedEventMaskLocked() { + if (mUiAutomationService == null) return 0; + return mUiAutomationService.mEventTypes; + } + + void dumpUiAutomationService(FileDescriptor fd, final PrintWriter pw, String[] args) { + if (mUiAutomationService != null) { + mUiAutomationService.dump(fd, pw, args); + } + } + + private void destroyUiAutomationService() { + mUiAutomationService.mServiceInterface.asBinder().unlinkToDeath(mUiAutomationService, 0); + mUiAutomationService.onRemoved(); + mUiAutomationService.resetLocked(); + mUiAutomationService = null; + mUiAutomationFlags = 0; + if (mUiAutomationServiceOwner != null) { + mUiAutomationServiceOwner.unlinkToDeath(mUiAutomationSerivceOwnerDeathRecipient, 0); + mUiAutomationServiceOwner = null; + } + } + + private class UiAutomationService extends AccessibilityClientConnection { + UiAutomationService(Context context, AccessibilityServiceInfo accessibilityServiceInfo, + int id, Handler mainHandler, Object lock, + AccessibilityManagerService.SecurityPolicy securityPolicy, + SystemSupport systemSupport, WindowManagerInternal windowManagerInternal, + GlobalActionPerformer globalActionPerfomer) { + super(context, COMPONENT_NAME, accessibilityServiceInfo, id, mainHandler, lock, + securityPolicy, systemSupport, windowManagerInternal, globalActionPerfomer); + } + + void connectServiceUnknownThread() { + // This needs to be done on the main thread + mEventDispatchHandler.post(() -> { + try { + mService = mServiceInterface.asBinder(); + mService.linkToDeath(this, 0); + mServiceInterface.init(this, mId, mOverlayWindowToken); + } catch (RemoteException re) { + Slog.w(LOG_TAG, "Error initialized connection", re); + destroyUiAutomationService(); + } + }); + } + + @Override + public void binderDied() { + destroyUiAutomationService(); + } + + @Override + protected boolean isCalledForCurrentUserLocked() { + // Allow UiAutomation to work for any user + return true; + } + + @Override + protected boolean supportsFlagForNotImportantViews(AccessibilityServiceInfo info) { + return true; + } + + // Since this isn't really an accessibility service, several methods are just stubbed here. + @Override + public boolean setSoftKeyboardShowMode(int mode) { + return false; + } + + @Override + public boolean isAccessibilityButtonAvailable() { + return false; + } + + @Override + public void disableSelf() {} + + @Override + public void onServiceConnected(ComponentName componentName, IBinder service) {} + + @Override + public void onServiceDisconnected(ComponentName componentName) {} + + @Override + public boolean isCapturingFingerprintGestures() { + return false; + } + + @Override + public void onFingerprintGestureDetectionActiveChanged(boolean active) {} + + @Override + public void onFingerprintGesture(int gesture) {} + } +} diff --git a/services/art-profile b/services/art-profile index 140465a1c35e..28762a8932db 100644 --- a/services/art-profile +++ b/services/art-profile @@ -5445,7 +5445,7 @@ PLcom/android/server/am/ActivityManagerService;->stopAppSwitches()V PLcom/android/server/am/ActivityManagerService;->stopAssociationLocked(ILjava/lang/String;ILandroid/content/ComponentName;)V PLcom/android/server/am/ActivityManagerService;->stopService(Landroid/app/IApplicationThread;Landroid/content/Intent;Ljava/lang/String;I)I PLcom/android/server/am/ActivityManagerService;->stopServiceToken(Landroid/content/ComponentName;Landroid/os/IBinder;I)Z -PLcom/android/server/am/ActivityManagerService;->systemReady(Ljava/lang/Runnable;Landroid/util/BootTimingsTraceLog;)V +PLcom/android/server/am/ActivityManagerService;->systemReady(Ljava/lang/Runnable;Landroid/util/TimingsTraceLog;)V PLcom/android/server/am/ActivityManagerService;->trimApplications()V PLcom/android/server/am/ActivityManagerService;->uidOnBackgroundWhitelist(I)Z PLcom/android/server/am/ActivityManagerService;->unbindFinished(Landroid/os/IBinder;Landroid/content/Intent;Z)V diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java index 71f699c8da54..ddc819d39d5e 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java @@ -655,6 +655,21 @@ public final class AutofillManagerService extends SystemService { } @Override + public void onPendingSaveUi(int operation, IBinder token) { + Preconditions.checkNotNull(token, "token"); + Preconditions.checkArgument(operation == AutofillManager.PENDING_UI_OPERATION_CANCEL + || operation == AutofillManager.PENDING_UI_OPERATION_RESTORE, + "invalid operation: %d", operation); + synchronized (mLock) { + final AutofillManagerServiceImpl service = peekServiceForUserLocked( + UserHandle.getCallingUserId()); + if (service != null) { + service.onPendingSaveUi(operation, token); + } + } + } + + @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index 751c0547afd6..2b8b25ef0fb4 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -41,7 +41,6 @@ import android.os.IBinder; import android.os.Looper; import android.os.RemoteCallbackList; import android.os.RemoteException; -import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.service.autofill.AutofillService; @@ -52,10 +51,12 @@ import android.service.autofill.FillResponse; import android.service.autofill.IAutoFillService; import android.text.TextUtils; import android.util.ArraySet; +import android.util.DebugUtils; import android.util.LocalLog; import android.util.Slog; import android.util.SparseArray; import android.view.autofill.AutofillId; +import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; import android.view.autofill.IAutoFillManagerClient; @@ -233,26 +234,6 @@ final class AutofillManagerServiceImpl { } } - /** - * Used by {@link AutofillManagerServiceShellCommand} to request save for the current top app. - */ - void requestSaveForUserLocked(IBinder activityToken) { - if (!isEnabled()) { - return; - } - - final int numSessions = mSessions.size(); - for (int i = 0; i < numSessions; i++) { - final Session session = mSessions.valueAt(i); - if (session.getActivityTokenLocked().equals(activityToken)) { - session.callSaveLocked(); - return; - } - } - - Slog.w(TAG, "requestSaveForUserLocked(): no session for " + activityToken); - } - boolean addClientLocked(IAutoFillManagerClient client) { if (mClients == null) { mClients = new RemoteCallbackList<>(); @@ -290,6 +271,7 @@ final class AutofillManagerServiceImpl { if (!isEnabled()) { return 0; } + if (sVerbose) Slog.v(TAG, "startSession(): token=" + activityToken + ", flags=" + flags); // Occasionally clean up abandoned sessions pruneAbandonedSessionsLocked(); @@ -461,6 +443,25 @@ final class AutofillManagerServiceImpl { } } + void onPendingSaveUi(int operation, @NonNull IBinder token) { + if (sVerbose) Slog.v(TAG, "onPendingSaveUi(" + operation + "): " + token); + synchronized (mLock) { + final int sessionCount = mSessions.size(); + for (int i = sessionCount - 1; i >= 0; i--) { + final Session session = mSessions.valueAt(i); + if (session.isSaveUiPendingForToken(token)) { + session.onPendingSaveUi(operation, token); + return; + } + } + } + if (sDebug) { + Slog.d(TAG, "No pending Save UI for token " + token + " and operation " + + DebugUtils.flagsToString(AutofillManager.class, "PENDING_UI_OPERATION_", + operation)); + } + } + void destroyLocked() { if (sVerbose) Slog.v(TAG, "destroyLocked()"); @@ -521,10 +522,11 @@ final class AutofillManagerServiceImpl { /** * Updates the last fill selection when an authentication was selected. */ - void setAuthenticationSelected(int sessionId) { + void setAuthenticationSelected(int sessionId, @Nullable Bundle clientState) { synchronized (mLock) { if (isValidEventLocked("setAuthenticationSelected()", sessionId)) { - mEventHistory.addEvent(new Event(Event.TYPE_AUTHENTICATION_SELECTED, null)); + mEventHistory + .addEvent(new Event(Event.TYPE_AUTHENTICATION_SELECTED, null, clientState)); } } } @@ -532,11 +534,13 @@ final class AutofillManagerServiceImpl { /** * Updates the last fill selection when an dataset authentication was selected. */ - void setDatasetAuthenticationSelected(@Nullable String selectedDataset, int sessionId) { + void setDatasetAuthenticationSelected(@Nullable String selectedDataset, int sessionId, + @Nullable Bundle clientState) { synchronized (mLock) { if (isValidEventLocked("setDatasetAuthenticationSelected()", sessionId)) { mEventHistory.addEvent( - new Event(Event.TYPE_DATASET_AUTHENTICATION_SELECTED, selectedDataset)); + new Event(Event.TYPE_DATASET_AUTHENTICATION_SELECTED, selectedDataset, + clientState)); } } } @@ -544,10 +548,10 @@ final class AutofillManagerServiceImpl { /** * Updates the last fill selection when an save Ui is shown. */ - void setSaveShown(int sessionId) { + void setSaveShown(int sessionId, @Nullable Bundle clientState) { synchronized (mLock) { if (isValidEventLocked("setSaveShown()", sessionId)) { - mEventHistory.addEvent(new Event(Event.TYPE_SAVE_SHOWN, null)); + mEventHistory.addEvent(new Event(Event.TYPE_SAVE_SHOWN, null, clientState)); } } } @@ -555,10 +559,12 @@ final class AutofillManagerServiceImpl { /** * Updates the last fill response when a dataset was selected. */ - void setDatasetSelected(@Nullable String selectedDataset, int sessionId) { + void setDatasetSelected(@Nullable String selectedDataset, int sessionId, + @Nullable Bundle clientState) { synchronized (mLock) { if (isValidEventLocked("setDatasetSelected()", sessionId)) { - mEventHistory.addEvent(new Event(Event.TYPE_DATASET_SELECTED, selectedDataset)); + mEventHistory.addEvent( + new Event(Event.TYPE_DATASET_SELECTED, selectedDataset, clientState)); } } } @@ -622,8 +628,12 @@ final class AutofillManagerServiceImpl { } void destroySessionsLocked() { + if (mSessions.size() == 0) { + mUi.destroyAll(AutofillManager.NO_SESSION, null, null); + return; + } while (mSessions.size() > 0) { - mSessions.valueAt(0).removeSelfLocked(); + mSessions.valueAt(0).forceRemoveSelfLocked(); } } diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java index 5e25dfa49d70..dd980535f628 100644 --- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java +++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java @@ -290,7 +290,7 @@ final class RemoteFillService implements DeathRecipient { } private void dispatchOnFillRequestFailure(PendingRequest pendingRequest, - CharSequence message) { + @Nullable CharSequence message) { mHandler.getHandler().post(() -> { if (handleResponseCallbackCommon(pendingRequest)) { mCallbacks.onFillRequestFailure(message, mComponentName.getPackageName()); @@ -298,6 +298,16 @@ final class RemoteFillService implements DeathRecipient { }); } + private void dispatchOnFillTimeout(@NonNull ICancellationSignal cancellationSignal) { + mHandler.getHandler().post(() -> { + try { + cancellationSignal.cancel(); + } catch (RemoteException e) { + Slog.w(LOG_TAG, "Error calling cancellation signal: " + e); + } + }); + } + private void dispatchOnSaveRequestSuccess(PendingRequest pendingRequest) { mHandler.getHandler().post(() -> { if (handleResponseCallbackCommon(pendingRequest)) { @@ -307,7 +317,7 @@ final class RemoteFillService implements DeathRecipient { } private void dispatchOnSaveRequestFailure(PendingRequest pendingRequest, - CharSequence message) { + @Nullable CharSequence message) { mHandler.getHandler().post(() -> { if (handleResponseCallbackCommon(pendingRequest)) { mCallbacks.onSaveRequestFailure(message, mComponentName.getPackageName()); @@ -432,7 +442,7 @@ final class RemoteFillService implements DeathRecipient { if (remoteService != null) { Slog.w(LOG_TAG, getClass().getSimpleName() + " timed out after " + TIMEOUT_REMOTE_REQUEST_MILLIS + " ms"); - fail(remoteService); + onTimeout(remoteService); } }; mServiceHandler.postAtTime(mTimeoutTrigger, @@ -485,7 +495,7 @@ final class RemoteFillService implements DeathRecipient { * Called by the self-destructure timeout when the AutofilllService didn't reply to the * request on time. */ - abstract void fail(RemoteFillService remoteService); + abstract void onTimeout(RemoteFillService remoteService); /** * @return whether this request leads to a final state where no @@ -549,7 +559,16 @@ final class RemoteFillService implements DeathRecipient { } @Override - void fail(RemoteFillService remoteService) { + void onTimeout(RemoteFillService remoteService) { + // NOTE: Must make these 2 calls asynchronously, because the cancellation signal is + // handled by the service, which could block. + final ICancellationSignal cancellation; + synchronized (mLock) { + cancellation = mCancellation; + } + if (cancellation != null) { + remoteService.dispatchOnFillTimeout(cancellation); + } remoteService.dispatchOnFillRequestFailure(PendingFillRequest.this, null); } @@ -571,7 +590,10 @@ final class RemoteFillService implements DeathRecipient { public boolean cancel() { if (!super.cancel()) return false; - final ICancellationSignal cancellation = mCancellation; + final ICancellationSignal cancellation; + synchronized (mLock) { + cancellation = mCancellation; + } if (cancellation != null) { try { cancellation.cancel(); @@ -617,7 +639,7 @@ final class RemoteFillService implements DeathRecipient { } @Override - void fail(RemoteFillService remoteService) { + void onTimeout(RemoteFillService remoteService) { remoteService.dispatchOnSaveRequestFailure(PendingSaveRequest.this, null); } @@ -630,7 +652,7 @@ final class RemoteFillService implements DeathRecipient { } catch (RemoteException e) { Slog.e(LOG_TAG, "Error calling on save request", e); - remoteService.dispatchOnFillRequestFailure(PendingSaveRequest.this, null); + remoteService.dispatchOnSaveRequestFailure(PendingSaveRequest.this, null); } } } diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index f8fb13a54115..8d9f0aa2f49b 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -77,6 +77,7 @@ import com.android.internal.os.HandlerCaller; import com.android.internal.os.IResultReceiver; import com.android.internal.util.ArrayUtils; import com.android.server.autofill.ui.AutoFillUI; +import com.android.server.autofill.ui.PendingUi; import java.io.PrintWriter; import java.util.ArrayList; @@ -164,10 +165,16 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @GuardedBy("mLock") private boolean mDestroyed; - /** Whether the session is currently saving */ + /** Whether the session is currently saving. */ @GuardedBy("mLock") private boolean mIsSaving; + /** + * Helper used to handle state of Save UI when it must be hiding to show a custom description + * link and later recovered. + */ + @GuardedBy("mLock") + private PendingUi mPendingSaveUi; /** * Receiver of assist data from the app's {@link Activity}. @@ -590,7 +597,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState getFillContextByRequestIdLocked(requestId).getStructure(), extras); } - mService.setAuthenticationSelected(id); + mService.setAuthenticationSelected(id, mClientState); final int authenticationId = AutofillManager.makeAuthenticationId(requestId, datasetIndex); mHandlerCaller.getHandler().post(() -> startAuthentication(authenticationId, @@ -701,7 +708,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mHandlerCaller.getHandler().post(() -> { try { synchronized (mLock) { - mClient.startIntentSender(intentSender); + mClient.startIntentSender(intentSender, null); } } catch (RemoteException e) { Slog.e(TAG, "Error launching auth intent", e); @@ -963,9 +970,18 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } if (sDebug) Slog.d(TAG, "Good news, everyone! All checks passed, show save UI!"); - mService.setSaveShown(id); + mService.setSaveShown(id, mClientState); + final IAutoFillManagerClient client = getClient(); + mPendingSaveUi = new PendingUi(mActivityToken); getUiForShowing().showSaveUi(mService.getServiceLabel(), saveInfo, - valueFinder, mPackageName, this); + valueFinder, mPackageName, this, mPendingSaveUi, id, client); + if (client != null) { + try { + client.setSaveUiState(id, true); + } catch (RemoteException e) { + Slog.e(TAG, "Error notifying client to set save UI state to shown: " + e); + } + } mIsSaving = true; return false; } @@ -1246,7 +1262,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // Remove the UI if the ViewState has changed. if (mCurrentViewId != viewState.id) { - hideFillUiIfOwnedByMe(); + mUi.hideFillUi(this); mCurrentViewId = viewState.id; } @@ -1256,7 +1272,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState case ACTION_VIEW_EXITED: if (mCurrentViewId == viewState.id) { if (sVerbose) Slog.d(TAG, "Exiting view " + id); - hideFillUiIfOwnedByMe(); + mUi.hideFillUi(this); mCurrentViewId = null; } break; @@ -1396,7 +1412,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private void processResponseLocked(@NonNull FillResponse newResponse, int flags) { // Make sure we are hiding the UI which will be shown // only if handling the current response requires it. - hideAllUiIfOwnedByMe(); + mUi.hideAll(this); final int requestId = newResponse.getRequestId(); if (sVerbose) { @@ -1516,14 +1532,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } // Autofill it directly... if (dataset.getAuthentication() == null) { - mService.setDatasetSelected(dataset.getId(), id); + mService.setDatasetSelected(dataset.getId(), id, mClientState); autoFillApp(dataset); return; } // ...or handle authentication. - mService.setDatasetAuthenticationSelected(dataset.getId(), id); + mService.setDatasetAuthenticationSelected(dataset.getId(), id, mClientState); setViewStatesLocked(null, dataset, ViewState.STATE_WAITING_DATASET_AUTH, false); final Intent fillInIntent = createAuthFillInIntent( getFillContextByRequestIdLocked(requestId).getStructure(), mClientState); @@ -1583,6 +1599,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState pw.print(prefix); pw.print("mViewStates size: "); pw.println(mViewStates.size()); pw.print(prefix); pw.print("mDestroyed: "); pw.println(mDestroyed); pw.print(prefix); pw.print("mIsSaving: "); pw.println(mIsSaving); + pw.print(prefix); pw.print("mPendingSaveUi: "); pw.println(mPendingSaveUi); for (Map.Entry<AutofillId, ViewState> entry : mViewStates.entrySet()) { pw.print(prefix); pw.print("State for id "); pw.println(entry.getKey()); entry.getValue().dump(prefix2, pw); @@ -1644,7 +1661,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } if (!ids.isEmpty()) { if (waitingDatasetAuth) { - hideFillUiIfOwnedByMe(); + mUi.hideFillUi(this); } if (sDebug) Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset); @@ -1664,38 +1681,65 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } + /** + * Cleans up this session. + * + * <p>Typically called in 2 scenarios: + * + * <ul> + * <li>When the session naturally finishes (i.e., from {@link #removeSelfLocked()}. + * <li>When the service hosting the session is finished (for example, because the user + * disabled it). + * </ul> + */ RemoteFillService destroyLocked() { if (mDestroyed) { return null; } - hideAllUiIfOwnedByMe(); + mUi.destroyAll(id, getClient(), this); mUi.clearCallback(this); mDestroyed = true; mMetricsLogger.action(MetricsEvent.AUTOFILL_SESSION_FINISHED, mPackageName); return mRemoteFillService; } - private void hideAllUiIfOwnedByMe() { - mUi.hideAll(this); - } + /** + * Cleans up this session and remove it from the service always, even if it does have a pending + * Save UI. + */ + void forceRemoveSelfLocked() { + if (sVerbose) Slog.v(TAG, "forceRemoveSelfLocked(): " + mPendingSaveUi); - private void hideFillUiIfOwnedByMe() { - mUi.hideFillUi(this); + mPendingSaveUi = null; + removeSelfLocked(); + mUi.destroyAll(id, getClient(), this); } + /** + * Thread-safe version of {@link #removeSelfLocked()}. + */ private void removeSelf() { synchronized (mLock) { removeSelfLocked(); } } + /** + * Cleans up this session and remove it from the service, but but only if it does not have a + * pending Save UI. + */ void removeSelfLocked() { - if (sVerbose) Slog.v(TAG, "removeSelfLocked()"); + if (sVerbose) Slog.v(TAG, "removeSelfLocked(): " + mPendingSaveUi); if (mDestroyed) { Slog.w(TAG, "Call to Session#removeSelfLocked() rejected - session: " + id + " destroyed"); return; } + if (isSaveUiPending()) { + Slog.i(TAG, "removeSelfLocked() ignored, waiting for pending save ui"); + return; + } + final RemoteFillService remoteFillService = destroyLocked(); mService.removeSessionLocked(id); if (remoteFillService != null) { @@ -1703,6 +1747,25 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } + void onPendingSaveUi(int operation, @NonNull IBinder token) { + getUiForShowing().onPendingSaveUi(operation, token); + } + + /** + * Checks whether this session is hiding the Save UI to handle a custom description link for + * a specific {@code token} created by {@link PendingUi#PendingUi(IBinder)}. + */ + boolean isSaveUiPendingForToken(@NonNull IBinder token) { + return isSaveUiPending() && token.equals(mPendingSaveUi.getToken()); + } + + /** + * Checks whether this session is hiding the Save UI to handle a custom description link. + */ + private boolean isSaveUiPending() { + return mPendingSaveUi != null && mPendingSaveUi.getState() == PendingUi.STATE_PENDING; + } + private int getLastResponseIndexLocked() { // The response ids are monotonically increasing so // we just find the largest id which is the last. We diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java index 67ee1858f583..7febf8305d57 100644 --- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java +++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java @@ -25,6 +25,8 @@ import android.content.IntentSender; import android.metrics.LogMaker; import android.os.Bundle; import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; import android.service.autofill.Dataset; import android.service.autofill.FillResponse; import android.service.autofill.SaveInfo; @@ -33,6 +35,7 @@ import android.text.TextUtils; import android.util.Slog; import android.view.autofill.AutofillId; import android.view.autofill.AutofillManager; +import android.view.autofill.IAutoFillManagerClient; import android.view.autofill.IAutofillWindowPresenter; import android.widget.Toast; @@ -143,7 +146,6 @@ public final class AutoFillUI { if (callback != mCallback) { return; } - hideSaveUiUiThread(callback); if (mFillUi != null) { mFillUi.setFilterText(filterText); } @@ -245,7 +247,8 @@ public final class AutoFillUI { */ public void showSaveUi(@NonNull CharSequence providerLabel, @NonNull SaveInfo info, @NonNull ValueFinder valueFinder, @NonNull String packageName, - @NonNull AutoFillUiCallback callback) { + @NonNull AutoFillUiCallback callback, @NonNull PendingUi pendingUi, + int sessionId, @Nullable IAutoFillManagerClient client) { if (sVerbose) Slog.v(TAG, "showSaveUi() for " + packageName + ": " + info); int numIds = 0; numIds += info.getRequiredIds() == null ? 0 : info.getRequiredIds().length; @@ -260,21 +263,22 @@ public final class AutoFillUI { return; } hideAllUiThread(callback); - mSaveUi = new SaveUi(mContext, providerLabel, info, valueFinder, mOverlayControl, - new SaveUi.OnSaveListener() { + mSaveUi = new SaveUi(mContext, pendingUi, providerLabel, info, valueFinder, + mOverlayControl, client, new SaveUi.OnSaveListener() { @Override public void onSave() { log.setType(MetricsProto.MetricsEvent.TYPE_ACTION); - hideSaveUiUiThread(callback); + hideSaveUiUiThread(mCallback); if (mCallback != null) { mCallback.save(); } + destroySaveUiUiThread(sessionId, client); } @Override public void onCancel(IntentSender listener) { log.setType(MetricsProto.MetricsEvent.TYPE_DISMISS); - hideSaveUiUiThread(callback); + hideSaveUiUiThread(mCallback); if (listener != null) { try { listener.sendIntent(mContext, 0, null, null, null); @@ -286,6 +290,7 @@ public final class AutoFillUI { if (mCallback != null) { mCallback.cancelSave(); } + destroySaveUiUiThread(sessionId, client); } @Override @@ -304,12 +309,33 @@ public final class AutoFillUI { } /** + * Executes an operation in the pending save UI, if any. + */ + public void onPendingSaveUi(int operation, @NonNull IBinder token) { + mHandler.post(() -> { + if (mSaveUi != null) { + mSaveUi.onPendingUi(operation, token); + } else { + Slog.w(TAG, "onPendingSaveUi(" + operation + "): no save ui"); + } + }); + } + + /** * Hides all UI affordances. */ public void hideAll(@Nullable AutoFillUiCallback callback) { mHandler.post(() -> hideAllUiThread(callback)); } + /** + * Destroy all UI affordances. + */ + public void destroyAll(int sessionId, @Nullable IAutoFillManagerClient client, + @Nullable AutoFillUiCallback callback) { + mHandler.post(() -> destroyAllUiThread(sessionId, client, callback)); + } + public void dump(PrintWriter pw) { pw.println("Autofill UI"); final String prefix = " "; @@ -343,12 +369,41 @@ public final class AutoFillUI { + ", mCallback=" + mCallback); } if (mSaveUi != null && (callback == null || callback == mCallback)) { - mSaveUi.destroy(); - mSaveUi = null; + mSaveUi.hide(); } } @android.annotation.UiThread + private void destroySaveUiUiThread(int sessionId, @Nullable IAutoFillManagerClient client) { + if (mSaveUi == null) { + // Calling destroySaveUiUiThread() twice is normal - it usually happens when the + // first call is made after the SaveUI is hidden and the second when the session is + // finished. + if (sDebug) Slog.d(TAG, "destroySaveUiUiThread(): already destroyed"); + return; + } + + if (sDebug) Slog.d(TAG, "destroySaveUiUiThread(): id=" + sessionId); + mSaveUi.destroy(); + mSaveUi = null; + if (client != null) { + try { + if (sDebug) Slog.d(TAG, "destroySaveUiUiThread(): notifying client"); + client.setSaveUiState(sessionId, false); + } catch (RemoteException e) { + Slog.e(TAG, "Error notifying client to set save UI state to hidden: " + e); + } + } + } + + @android.annotation.UiThread + private void destroyAllUiThread(int sessionId, @Nullable IAutoFillManagerClient client, + @Nullable AutoFillUiCallback callback) { + hideFillUiUiThread(callback); + destroySaveUiUiThread(sessionId, client); + } + + @android.annotation.UiThread private void hideAllUiThread(@Nullable AutoFillUiCallback callback) { hideFillUiUiThread(callback); hideSaveUiUiThread(callback); diff --git a/services/autofill/java/com/android/server/autofill/ui/PendingUi.java b/services/autofill/java/com/android/server/autofill/ui/PendingUi.java new file mode 100644 index 000000000000..87263ed61ee9 --- /dev/null +++ b/services/autofill/java/com/android/server/autofill/ui/PendingUi.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.autofill.ui; + +import android.annotation.NonNull; +import android.os.IBinder; +import android.util.DebugUtils; + +/** + * Helper class used to handle a pending Autofill affordance such as the Save UI. + * + * <p>This class is not thread safe. + */ +// NOTE: this class could be an interface implemented by Session, but that would make it harder +// to move the Autofill UI logic to a different process. +public final class PendingUi { + + public static final int STATE_CREATED = 1; + public static final int STATE_PENDING = 2; + public static final int STATE_FINISHED = 4; + + private final IBinder mToken; + private int mState; + + /** + * Default constructor. + * + * @param token token used to identify this pending UI. + */ + public PendingUi(@NonNull IBinder token) { + mToken = token; + mState = STATE_CREATED; + } + + /** + * Gets the token used to identify this pending UI. + */ + @NonNull + public IBinder getToken() { + return mToken; + } + + /** + * Sets the current lifecycle state. + */ + public void setState(int state) { + mState = state; + } + + /** + * Gets the current lifecycle state. + */ + public int getState() { + return mState; + } + + /** + * Determines whether the given token matches the token used to identify this pending UI. + */ + public boolean matches(IBinder token) { + return mToken.equals(token); + } + + @Override + public String toString() { + return "PendingUi: [token=" + mToken + ", state=" + + DebugUtils.flagsToString(PendingUi.class, "STATE_", mState) + "]"; + } +} diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java index 035186525ae0..67c1b8cdf45a 100644 --- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java +++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java @@ -21,9 +21,14 @@ import static com.android.server.autofill.Helper.sVerbose; import android.annotation.NonNull; import android.app.Dialog; +import android.app.PendingIntent; +import android.app.PendingIntent.CanceledException; import android.content.Context; +import android.content.Intent; import android.content.IntentSender; import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; import android.service.autofill.CustomDescription; import android.service.autofill.SaveInfo; import android.service.autofill.ValueFinder; @@ -31,15 +36,17 @@ import android.text.Html; import android.util.ArraySet; import android.util.Slog; import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; import android.view.Window; import android.view.WindowManager; +import android.view.autofill.AutofillManager; +import android.view.autofill.IAutoFillManagerClient; import android.widget.RemoteViews; import android.widget.ScrollView; import android.widget.TextView; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewGroup.LayoutParams; import com.android.internal.R; import com.android.server.UiThread; @@ -109,12 +116,15 @@ final class SaveUi { private final CharSequence mTitle; private final CharSequence mSubTitle; + private final PendingUi mPendingUi; private boolean mDestroyed; - SaveUi(@NonNull Context context, @NonNull CharSequence providerLabel, @NonNull SaveInfo info, + SaveUi(@NonNull Context context, @NonNull PendingUi pendingUi, + @NonNull CharSequence providerLabel, @NonNull SaveInfo info, @NonNull ValueFinder valueFinder, @NonNull OverlayControl overlayControl, - @NonNull OnSaveListener listener) { + @NonNull IAutoFillManagerClient client, @NonNull OnSaveListener listener) { + mPendingUi= pendingUi; mListener = new OneTimeListener(listener); mOverlayControl = overlayControl; @@ -171,8 +181,49 @@ final class SaveUi { final RemoteViews presentation = customDescription.getPresentation(valueFinder); if (presentation != null) { + final RemoteViews.OnClickHandler handler = new RemoteViews.OnClickHandler() { + @Override + public boolean onClickHandler(View view, PendingIntent pendingIntent, + Intent intent) { + // We need to hide the Save UI before launching the pending intent, and + // restore back it once the activity is finished, and that's achieved by + // adding a custom extra in the activity intent. + if (pendingIntent != null) { + if (intent == null) { + Slog.w(TAG, + "remote view on custom description does not have intent"); + return false; + } + if (!pendingIntent.isActivity()) { + Slog.w(TAG, "ignoring custom description pending intent that's not " + + "for an activity: " + pendingIntent); + return false; + } + if (sVerbose) { + Slog.v(TAG, + "Intercepting custom description intent: " + intent); + } + final IBinder token = mPendingUi.getToken(); + intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token); + try { + client.startIntentSender(pendingIntent.getIntentSender(), + intent); + mPendingUi.setState(PendingUi.STATE_PENDING); + if (sDebug) { + Slog.d(TAG, "hiding UI until restored with token " + token); + } + hide(); + } catch (RemoteException e) { + Slog.w(TAG, "error triggering pending intent: " + intent); + return false; + } + } + return true; + } + }; + try { - final View customSubtitleView = presentation.apply(context, null); + final View customSubtitleView = presentation.apply(context, null, handler); subtitleContainer = view.findViewById(R.id.autofill_save_custom_subtitle); subtitleContainer.addView(customSubtitleView); subtitleContainer.setVisibility(View.VISIBLE); @@ -202,19 +253,19 @@ final class SaveUi { } else { noButton.setText(R.string.autofill_save_no); } - View.OnClickListener cancelListener = + final View.OnClickListener cancelListener = (v) -> mListener.onCancel(info.getNegativeActionListener()); noButton.setOnClickListener(cancelListener); final View yesButton = view.findViewById(R.id.autofill_save_yes); yesButton.setOnClickListener((v) -> mListener.onSave()); - final View closeButton = view.findViewById(R.id.autofill_save_close); - closeButton.setOnClickListener(cancelListener); - mDialog = new Dialog(context, R.style.Theme_DeviceDefault_Light_Panel); mDialog.setContentView(view); + // Dialog can be dismissed when touched outside. + mDialog.setOnDismissListener((d) -> mListener.onCancel(info.getNegativeActionListener())); + final Window window = mDialog.getWindow(); window.setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE @@ -230,9 +281,50 @@ final class SaveUi { params.accessibilityTitle = context.getString(R.string.autofill_save_accessibility_title); params.windowAnimations = R.style.AutofillSaveAnimation; + show(); + } + + /** + * Update the pending UI, if any. + * + * @param operation how to update it. + * @param token token associated with the pending UI - if it doesn't match the pending token, + * the operation will be ignored. + */ + void onPendingUi(int operation, @NonNull IBinder token) { + if (!mPendingUi.matches(token)) { + Slog.w(TAG, "restore(" + operation + "): got token " + token + " instead of " + + mPendingUi.getToken()); + return; + } + switch (operation) { + case AutofillManager.PENDING_UI_OPERATION_RESTORE: + if (sDebug) Slog.d(TAG, "Restoring save dialog for " + token); + show(); + break; + case AutofillManager.PENDING_UI_OPERATION_CANCEL: + if (sDebug) Slog.d(TAG, "Cancelling pending save dialog for " + token); + hide(); + break; + default: + Slog.w(TAG, "restore(): invalid operation " + operation); + } + mPendingUi.setState(PendingUi.STATE_FINISHED); + } + + private void show() { Slog.i(TAG, "Showing save dialog: " + mTitle); mDialog.show(); mOverlayControl.hideOverlays(); + } + + void hide() { + if (sVerbose) Slog.v(TAG, "Hiding save dialog."); + try { + mDialog.hide(); + } finally { + mOverlayControl.showOverlays(); + } } void destroy() { @@ -241,7 +333,6 @@ final class SaveUi { throwIfDestroyed(); mListener.onDestroy(); mHandler.removeCallbacksAndMessages(mListener); - if (sVerbose) Slog.v(TAG, "destroy(): dismissing dialog"); mDialog.dismiss(); mDestroyed = true; } finally { @@ -263,6 +354,7 @@ final class SaveUi { void dump(PrintWriter pw, String prefix) { pw.print(prefix); pw.print("title: "); pw.println(mTitle); pw.print(prefix); pw.print("subtitle: "); pw.println(mSubTitle); + pw.print(prefix); pw.print("pendingUi: "); pw.println(mPendingUi); final View view = mDialog.getWindow().getDecorView(); final int[] loc = view.getLocationOnScreen(); diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index cb4beccaa205..c1a7f6882d18 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -119,6 +119,7 @@ import android.util.StringBuilderPrinter; import com.android.internal.annotations.GuardedBy; import com.android.internal.backup.IBackupTransport; import com.android.internal.backup.IObbBackupService; +import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.server.AppWidgetBackupBridge; import com.android.server.EventLogTags; @@ -8416,7 +8417,19 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF // ----- Restore handling ----- - // Old style: directly match the stored vs on device signature blocks + /** + * Returns whether the signatures stored {@param storedSigs}, coming from the source apk, match + * the signatures of the apk installed on the device, the target apk. If the target resides in + * the system partition we return true. Otherwise it's considered a match if both conditions + * hold: + * + * <ul> + * <li>Source and target have at least one signature each + * <li>Target contains all signatures in source + * </ul> + * + * Note that if {@param target} is null we return false. + */ static boolean signaturesMatch(Signature[] storedSigs, PackageInfo target) { if (target == null) { return false; @@ -8428,26 +8441,24 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF // partition will be signed with the device's platform certificate, so on // different phones the same system app will have different signatures.) if ((target.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { - if (MORE_DEBUG) Slog.v(TAG, "System app " + target.packageName + " - skipping sig check"); + if (MORE_DEBUG) { + Slog.v(TAG, "System app " + target.packageName + " - skipping sig check"); + } return true; } - // Allow unsigned apps, but not signed on one device and unsigned on the other - // !!! TODO: is this the right policy? Signature[] deviceSigs = target.signatures; - if (MORE_DEBUG) Slog.v(TAG, "signaturesMatch(): stored=" + storedSigs - + " device=" + deviceSigs); - if ((storedSigs == null || storedSigs.length == 0) - && (deviceSigs == null || deviceSigs.length == 0)) { - return true; + if (MORE_DEBUG) { + Slog.v(TAG, "signaturesMatch(): stored=" + storedSigs + " device=" + deviceSigs); } - if (storedSigs == null || deviceSigs == null) { + + // Don't allow unsigned apps on either end + if (ArrayUtils.isEmpty(storedSigs) || ArrayUtils.isEmpty(deviceSigs)) { return false; } - // !!! TODO: this demands that every stored signature match one - // that is present on device, and does not demand the converse. - // Is this this right policy? + // Signatures can be added over time, so the target-device apk needs to contain all the + // source-device apk signatures, but not necessarily the other way around. int nStored = storedSigs.length; int nDevice = deviceSigs.length; @@ -10464,7 +10475,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF public ComponentName[] listAllTransportComponents() { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "listAllTransportComponents"); - return mTransportManager.getAllTransportCompenents(); + return mTransportManager.getAllTransportComponents(); } @Override diff --git a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java index b01cfc572432..83b6693e7a70 100644 --- a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java +++ b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java @@ -2762,7 +2762,7 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter public ComponentName[] listAllTransportComponents() { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "listAllTransportComponents"); - return mTransportManager.getAllTransportCompenents(); + return mTransportManager.getAllTransportComponents(); } @Override diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java index fb2982eb0baa..321ef2652514 100644 --- a/services/backup/java/com/android/server/backup/TransportManager.java +++ b/services/backup/java/com/android/server/backup/TransportManager.java @@ -41,10 +41,12 @@ import android.util.Log; import android.util.Slog; import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.backup.IBackupTransport; import com.android.server.EventLogTags; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -57,7 +59,9 @@ public class TransportManager { private static final String TAG = "BackupTransportManager"; - private static final String SERVICE_ACTION_TRANSPORT_HOST = "android.backup.TRANSPORT_HOST"; + @VisibleForTesting + /* package */ static final String SERVICE_ACTION_TRANSPORT_HOST = + "android.backup.TRANSPORT_HOST"; private static final long REBINDING_TIMEOUT_UNPROVISIONED_MS = 30 * 1000; // 30 sec private static final long REBINDING_TIMEOUT_PROVISIONED_MS = 5 * 60 * 1000; // 5 mins @@ -95,7 +99,11 @@ public class TransportManager { TransportBoundListener listener, Looper looper) { mContext = context; mPackageManager = context.getPackageManager(); - mTransportWhitelist = (whitelist != null) ? whitelist : new ArraySet<>(); + if (whitelist != null) { + mTransportWhitelist = whitelist; + } else { + mTransportWhitelist = new ArraySet<>(); + } mCurrentTransportName = defaultTransport; mTransportBoundListener = listener; mHandler = new RebindOnTimeoutHandler(looper); @@ -186,7 +194,7 @@ public class TransportManager { } } - ComponentName[] getAllTransportCompenents() { + ComponentName[] getAllTransportComponents() { synchronized (mTransportLock) { return mValidTransports.keySet().toArray(new ComponentName[mValidTransports.size()]); } @@ -208,7 +216,8 @@ public class TransportManager { } } - void ensureTransportReady(ComponentName transportComponent, SelectBackupTransportCallback listener) { + void ensureTransportReady(ComponentName transportComponent, + SelectBackupTransportCallback listener) { synchronized (mTransportLock) { TransportConnection conn = mValidTransports.get(transportComponent); if (conn == null) { @@ -252,7 +261,7 @@ public class TransportManager { intent, 0, UserHandle.USER_SYSTEM); if (hosts != null) { for (ResolveInfo host : hosts) { - final ComponentName infoComponentName = host.serviceInfo.getComponentName(); + final ComponentName infoComponentName = getComponentName(host.serviceInfo); boolean shouldBind = false; if (components != null && packageName != null) { for (String component : components) { @@ -310,7 +319,7 @@ public class TransportManager { Intent intent = new Intent(mTransportServiceIntent) .setComponent(componentName); return mContext.bindServiceAsUser(intent, connection, Context.BIND_AUTO_CREATE, - UserHandle.SYSTEM); + createSystemUserHandle()); } private class TransportConnection implements ServiceConnection { @@ -333,7 +342,7 @@ public class TransportManager { boolean success = false; EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, - component.flattenToShortString(), 1); + component.flattenToShortString(), 1); try { mTransportName = mBinder.name(); @@ -437,7 +446,8 @@ public class TransportManager { } private long getRebindTimeout() { - final boolean isDeviceProvisioned = Settings.Global.getInt(mContext.getContentResolver(), + final boolean isDeviceProvisioned = Settings.Global.getInt( + mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0; return isDeviceProvisioned ? REBINDING_TIMEOUT_PROVISIONED_MS @@ -465,7 +475,7 @@ public class TransportManager { synchronized (mTransportLock) { if (mBoundTransports.containsValue(transportComponent)) { Slog.d(TAG, "Explicit rebinding timeout passed, but already bound to " - + componentShortString + " so not attempting to rebind"); + + componentShortString + " so not attempting to rebind"); return; } Slog.d(TAG, "Explicit rebinding timeout passed, attempting rebinding to: " @@ -492,4 +502,18 @@ public class TransportManager { Slog.v(TAG, message); } } + + // These only exists to make it testable with Robolectric, which is not updated to API level 24 + // yet. + // TODO: Get rid of this once Robolectric is updated. + private static ComponentName getComponentName(ServiceInfo serviceInfo) { + return new ComponentName(serviceInfo.packageName, serviceInfo.name); + } + + // These only exists to make it testable with Robolectric, which is not updated to API level 24 + // yet. + // TODO: Get rid of this once Robolectric is updated. + private static UserHandle createSystemUserHandle() { + return new UserHandle(UserHandle.USER_SYSTEM); + } } diff --git a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java index c033d98e3896..4abf18add469 100644 --- a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java +++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java @@ -26,6 +26,8 @@ import android.content.pm.Signature; import android.os.Process; import android.util.Slog; +import com.android.internal.util.ArrayUtils; + /** * Utility methods wrapping operations on ApplicationInfo and PackageInfo. */ @@ -91,9 +93,18 @@ public class AppBackupUtils { } /** - * Old style: directly match the stored vs on device signature blocks. + * Returns whether the signatures stored {@param storedSigs}, coming from the source apk, match + * the signatures of the apk installed on the device, the target apk. If the target resides in + * the system partition we return true. Otherwise it's considered a match if both conditions + * hold: + * + * <ul> + * <li>Source and target have at least one signature each + * <li>Target contains all signatures in source + * </ul> + * + * Note that if {@param target} is null we return false. */ - // TODO(b/37977154): Resolve questionable policies. public static boolean signaturesMatch(Signature[] storedSigs, PackageInfo target) { if (target == null) { return false; @@ -111,24 +122,18 @@ public class AppBackupUtils { return true; } - // Allow unsigned apps, but not signed on one device and unsigned on the other - // TODO(b/37977154): is this the right policy? Signature[] deviceSigs = target.signatures; if (MORE_DEBUG) { Slog.v(TAG, "signaturesMatch(): stored=" + storedSigs + " device=" + deviceSigs); } - if ((storedSigs == null || storedSigs.length == 0) - && (deviceSigs == null || deviceSigs.length == 0)) { - return true; - } - // TODO(b/37977154): This allows empty stored signature, is this right? - if (storedSigs == null || deviceSigs == null) { + + // Don't allow unsigned apps on either end + if (ArrayUtils.isEmpty(storedSigs) || ArrayUtils.isEmpty(deviceSigs)) { return false; } - // TODO(b/37977154): this demands that every stored signature match one - // that is present on device, and does not demand the converse. - // Is this this right policy? + // Signatures can be added over time, so the target-device apk needs to contain all the + // source-device apk signatures, but not necessarily the other way around. int nStored = storedSigs.length; int nDevice = deviceSigs.length; diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index be4d1064ec9c..d1cf0255b18c 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -850,6 +850,7 @@ class AlarmManagerService extends SystemService { static final class InFlight { final PendingIntent mPendingIntent; + final long mWhenElapsed; final IBinder mListener; final WorkSource mWorkSource; final int mUid; @@ -862,6 +863,7 @@ class AlarmManagerService extends SystemService { WorkSource workSource, int uid, String alarmPkg, int alarmType, String tag, long nowELAPSED) { mPendingIntent = pendingIntent; + mWhenElapsed = nowELAPSED; mListener = listener != null ? listener.asBinder() : null; mWorkSource = workSource; mUid = uid; @@ -883,6 +885,7 @@ class AlarmManagerService extends SystemService { public String toString() { return "InFlight{" + "pendingIntent=" + mPendingIntent + + ", when=" + mWhenElapsed + ", workSource=" + mWorkSource + ", uid=" + mUid + ", tag=" + mTag @@ -1567,8 +1570,10 @@ class AlarmManagerService extends SystemService { pw.println(); pw.print(" Broadcast ref count: "); pw.println(mBroadcastRefCount); - pw.print(" PendingIntent send/finish count: "); pw.println(mSendCount); - pw.print(" Listener send/complete count: "); pw.println(mListenerCount); + pw.print(" PendingIntent send count: "); pw.println(mSendCount); + pw.print(" PendingIntent finish count: "); pw.println(mSendFinishCount); + pw.print(" Listener send count: "); pw.println(mListenerCount); + pw.print(" Listener finish count: "); pw.println(mListenerFinishCount); pw.println(); if (mInFlight.size() > 0) { @@ -2949,7 +2954,11 @@ class AlarmManagerService extends SystemService { @GuardedBy("mLock") private int mSendCount = 0; @GuardedBy("mLock") + private int mSendFinishCount = 0; + @GuardedBy("mLock") private int mListenerCount = 0; + @GuardedBy("mLock") + private int mListenerFinishCount = 0; class DeliveryTracker extends IAlarmCompleteListener.Stub implements PendingIntent.OnFinished { @@ -3054,7 +3063,7 @@ class AlarmManagerService extends SystemService { Slog.i(TAG, "alarmComplete() from " + who); } updateTrackingLocked(inflight); - mListenerCount--; + mListenerFinishCount++; } else { // Delivery timed out, and the timeout handling already took care of // updating our tracking here, so we needn't do anything further. @@ -3075,7 +3084,7 @@ class AlarmManagerService extends SystemService { public void onSendFinished(PendingIntent pi, Intent intent, int resultCode, String resultData, Bundle resultExtras) { synchronized (mLock) { - mSendCount--; + mSendFinishCount++; updateTrackingLocked(removeLocked(pi, intent)); } } @@ -3092,7 +3101,7 @@ class AlarmManagerService extends SystemService { Slog.i(TAG, "Alarm listener " + who + " timed out in delivery"); } updateTrackingLocked(inflight); - mListenerCount--; + mListenerFinishCount++; } else { if (DEBUG_LISTENER_CALLBACK) { Slog.i(TAG, "Spurious timeout of listener " + who); @@ -3125,7 +3134,7 @@ class AlarmManagerService extends SystemService { // 'finished' callback won't be invoked. We also don't need // to do any wakelock or stats tracking, so we have nothing // left to do here but go on to the next thing. - mSendCount--; + mSendFinishCount++; return; } } else { @@ -3150,6 +3159,7 @@ class AlarmManagerService extends SystemService { // alarm was not possible, so we have no wakelock or timeout or // stats management to do. It threw before we posted the delayed // timeout message, so we're done here. + mListenerFinishCount++; return; } } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index ac41079e5237..adf536bbf487 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2269,7 +2269,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED); mNetworkAgentInfos.remove(msg.replyTo); - updateClat(null, nai.linkProperties, nai); + maybeStopClat(nai); synchronized (mNetworkForNetId) { // Remove the NetworkAgent, but don't mark the netId as // available until we've told netd to delete it below. @@ -4382,7 +4382,8 @@ public class ConnectivityService extends IConnectivityManager.Stub updateRoutes(newLp, oldLp, netId); updateDnses(newLp, oldLp, netId); - updateClat(newLp, oldLp, networkAgent); + // Start or stop clat accordingly to network state. + updateClat(networkAgent); if (isDefaultNetwork(networkAgent)) { handleApplyDefaultProxy(newLp.getHttpProxy()); } else { @@ -4397,16 +4398,30 @@ public class ConnectivityService extends IConnectivityManager.Stub mKeepaliveTracker.handleCheckKeepalivesStillValid(networkAgent); } - private void updateClat(LinkProperties newLp, LinkProperties oldLp, NetworkAgentInfo nai) { - final boolean wasRunningClat = nai.clatd != null && nai.clatd.isStarted(); - final boolean shouldRunClat = Nat464Xlat.requiresClat(nai); + private void updateClat(NetworkAgentInfo nai) { + if (Nat464Xlat.requiresClat(nai)) { + maybeStartClat(nai); + } else { + maybeStopClat(nai); + } + } + + /** Ensure clat has started for this network. */ + private void maybeStartClat(NetworkAgentInfo nai) { + if (nai.clatd != null && nai.clatd.isStarted()) { + return; + } + nai.clatd = new Nat464Xlat(mNetd, mTrackerHandler, nai); + nai.clatd.start(); + } - if (!wasRunningClat && shouldRunClat) { - nai.clatd = new Nat464Xlat(mContext, mNetd, mTrackerHandler, nai); - nai.clatd.start(); - } else if (wasRunningClat && !shouldRunClat) { - nai.clatd.stop(); + /** Ensure clat has stopped for this network. */ + private void maybeStopClat(NetworkAgentInfo nai) { + if (nai.clatd == null) { + return; } + nai.clatd.stop(); + nai.clatd = null; } private void wakeupModifyInterface(String iface, NetworkCapabilities caps, boolean add) { @@ -4582,11 +4597,15 @@ public class ConnectivityService extends IConnectivityManager.Stub */ private void updateCapabilities( int oldScore, NetworkAgentInfo nai, NetworkCapabilities networkCapabilities) { - // Sanity check: a NetworkAgent should not change its static capabilities or parameters. - if (nai.everConnected) { + // Once a NetworkAgent is connected, complain if some immutable capabilities are removed. + if (nai.everConnected && !nai.networkCapabilities.satisfiedByImmutableNetworkCapabilities( + networkCapabilities)) { + // TODO: consider not complaining when a network agent degrade its capabilities if this + // does not cause any request (that is not a listen) currently matching that agent to + // stop being matched by the updated agent. String diff = nai.networkCapabilities.describeImmutableDifferences(networkCapabilities); if (!TextUtils.isEmpty(diff)) { - Slog.wtf(TAG, "BUG: " + nai + " changed immutable capabilities:" + diff); + Slog.wtf(TAG, "BUG: " + nai + " lost immutable capabilities:" + diff); } } diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java index 1bf12c4f86f0..887de74f1cf9 100644 --- a/services/core/java/com/android/server/DropBoxManagerService.java +++ b/services/core/java/com/android/server/DropBoxManagerService.java @@ -16,6 +16,7 @@ package com.android.server; +import android.app.ActivityManager; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; @@ -70,6 +71,7 @@ public final class DropBoxManagerService extends SystemService { private static final String TAG = "DropBoxManagerService"; private static final int DEFAULT_AGE_SECONDS = 3 * 86400; private static final int DEFAULT_MAX_FILES = 1000; + private static final int DEFAULT_MAX_FILES_LOWRAM = 300; private static final int DEFAULT_QUOTA_KB = 5 * 1024; private static final int DEFAULT_QUOTA_PERCENT = 10; private static final int DEFAULT_RESERVE_PERCENT = 10; @@ -106,6 +108,8 @@ public final class DropBoxManagerService extends SystemService { // Provide a way to perform sendBroadcast asynchronously to avoid deadlocks. private final Handler mHandler; + private int mMaxFiles = -1; // -1 means uninitialized. + /** Receives events that might indicate a need to clean up files. */ private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override @@ -394,6 +398,7 @@ public final class DropBoxManagerService extends SystemService { } out.append("Drop box contents: ").append(mAllFiles.contents.size()).append(" entries\n"); + out.append("Max entries: ").append(mMaxFiles).append("\n"); if (!searchArgs.isEmpty()) { out.append("Searching for:"); @@ -819,12 +824,16 @@ public final class DropBoxManagerService extends SystemService { int ageSeconds = Settings.Global.getInt(mContentResolver, Settings.Global.DROPBOX_AGE_SECONDS, DEFAULT_AGE_SECONDS); - int maxFiles = Settings.Global.getInt(mContentResolver, - Settings.Global.DROPBOX_MAX_FILES, DEFAULT_MAX_FILES); + mMaxFiles = Settings.Global.getInt(mContentResolver, + Settings.Global.DROPBOX_MAX_FILES, + (ActivityManager.isLowRamDeviceStatic() + ? DEFAULT_MAX_FILES_LOWRAM : DEFAULT_MAX_FILES)); long cutoffMillis = System.currentTimeMillis() - ageSeconds * 1000; while (!mAllFiles.contents.isEmpty()) { EntryFile entry = mAllFiles.contents.first(); - if (entry.timestampMillis > cutoffMillis && mAllFiles.contents.size() < maxFiles) break; + if (entry.timestampMillis > cutoffMillis && mAllFiles.contents.size() < mMaxFiles) { + break; + } FileList tag = mFilesByTag.get(entry.tag); if (tag != null && tag.contents.remove(entry)) tag.blocks -= entry.blocks; diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index ab7daccb0691..305683139ffd 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -142,6 +142,17 @@ public class IpSecService extends IIpSecService.Stub { } mCurrent--; } + + @Override + public String toString() { + return new StringBuilder() + .append("{mCurrent=") + .append(mCurrent) + .append(", mMax=") + .append(mMax) + .append("}") + .toString(); + } } private static final class UserQuotaTracker { @@ -159,6 +170,19 @@ public class IpSecService extends IIpSecService.Stub { public final ResourceTracker socket = new ResourceTracker(MAX_NUM_ENCAP_SOCKETS); public final ResourceTracker transform = new ResourceTracker(MAX_NUM_TRANSFORMS); public final ResourceTracker spi = new ResourceTracker(MAX_NUM_SPIS); + + @Override + public String toString() { + return new StringBuilder() + .append("{socket=") + .append(socket) + .append(", transform=") + .append(transform) + .append(", spi=") + .append(spi) + .append("}") + .toString(); + } } private final SparseArray<UserRecord> mUserRecords = new SparseArray<>(); @@ -172,6 +196,11 @@ public class IpSecService extends IIpSecService.Stub { } return r; } + + @Override + public String toString() { + return mUserRecords.toString(); + } } private final UserQuotaTracker mUserQuotaTracker = new UserQuotaTracker(); @@ -909,6 +938,8 @@ public class IpSecService extends IIpSecService.Stub { pw.println("NetdNativeService Connection: " + (isNetdAlive() ? "alive" : "dead")); pw.println(); + pw.println("mUserQuotaTracker:"); + pw.println(mUserQuotaTracker); pw.println("mTransformRecords:"); pw.println(mTransformRecords); pw.println("mUdpSocketRecords:"); diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 13aca877096b..f17c770becde 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -34,6 +34,7 @@ import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY; import static android.net.NetworkPolicyManager.FIREWALL_TYPE_BLACKLIST; import static android.net.NetworkPolicyManager.FIREWALL_TYPE_WHITELIST; import static android.net.NetworkStats.SET_DEFAULT; +import static android.net.NetworkStats.STATS_PER_UID; import static android.net.NetworkStats.TAG_ALL; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; @@ -72,6 +73,7 @@ import android.net.wifi.WifiConfiguration.KeyMgmt; import android.os.BatteryStats; import android.os.Binder; import android.os.Handler; +import android.os.IBinder; import android.os.INetworkActivityListener; import android.os.INetworkManagementService; import android.os.PowerManager; @@ -131,10 +133,27 @@ import java.util.concurrent.CountDownLatch; */ public class NetworkManagementService extends INetworkManagementService.Stub implements Watchdog.Monitor { + + /** + * Helper class that encapsulates NetworkManagementService dependencies and makes them + * easier to mock in unit tests. + */ + static class SystemServices { + public IBinder getService(String name) { + return ServiceManager.getService(name); + } + public void registerLocalService(NetworkManagementInternal nmi) { + LocalServices.addService(NetworkManagementInternal.class, nmi); + } + public INetd getNetd() { + return NetdService.get(); + } + } + private static final String TAG = "NetworkManagement"; private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); private static final String NETD_TAG = "NetdConnector"; - private static final String NETD_SERVICE_NAME = "netd"; + static final String NETD_SERVICE_NAME = "netd"; private static final int MAX_UID_RANGES_PER_COMMAND = 10; @@ -216,6 +235,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub private final Handler mFgHandler; private final Handler mDaemonHandler; + private final SystemServices mServices; + private INetd mNetdService; private IBatteryStats mBatteryStats; @@ -314,8 +335,10 @@ public class NetworkManagementService extends INetworkManagementService.Stub * * @param context Binder context for this service */ - private NetworkManagementService(Context context, String socket) { + private NetworkManagementService( + Context context, String socket, SystemServices services) { mContext = context; + mServices = services; // make sure this is on the same looper as our NativeDaemonConnector for sync purposes mFgHandler = new Handler(FgThread.get().getLooper()); @@ -337,7 +360,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub // Add ourself to the Watchdog monitors. Watchdog.getInstance().addMonitor(this); - LocalServices.addService(NetworkManagementInternal.class, new LocalService()); + mServices.registerLocalService(new LocalService()); synchronized (mTetheringStatsProviders) { mTetheringStatsProviders.put(new NetdTetheringStatsProvider(), "netd"); @@ -351,11 +374,13 @@ public class NetworkManagementService extends INetworkManagementService.Stub mDaemonHandler = null; mFgHandler = null; mThread = null; + mServices = null; } - static NetworkManagementService create(Context context, String socket) + static NetworkManagementService create(Context context, String socket, SystemServices services) throws InterruptedException { - final NetworkManagementService service = new NetworkManagementService(context, socket); + final NetworkManagementService service = + new NetworkManagementService(context, socket, services); final CountDownLatch connectedSignal = service.mConnectedSignal; if (DBG) Slog.d(TAG, "Creating NetworkManagementService"); service.mThread.start(); @@ -369,7 +394,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub } public static NetworkManagementService create(Context context) throws InterruptedException { - return create(context, NETD_SERVICE_NAME); + return create(context, NETD_SERVICE_NAME, new SystemServices()); } public void systemReady() { @@ -389,8 +414,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub if (mBatteryStats != null) { return mBatteryStats; } - mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService( - BatteryStats.SERVICE_NAME)); + mBatteryStats = + IBatteryStats.Stub.asInterface(mServices.getService(BatteryStats.SERVICE_NAME)); return mBatteryStats; } } @@ -550,6 +575,18 @@ public class NetworkManagementService extends INetworkManagementService.Stub } } + @Override + public void tetherLimitReached(ITetheringStatsProvider provider) { + mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG); + synchronized(mTetheringStatsProviders) { + if (!mTetheringStatsProviders.containsKey(provider)) { + return; + } + // No current code examines the interface parameter in a global alert. Just pass null. + notifyLimitReached(LIMIT_GLOBAL_ALERT, null); + } + } + // Sync the state of the given chain with the native daemon. private void syncFirewallChainLocked(int chain, String name) { SparseIntArray rules; @@ -576,7 +613,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub } private void connectNativeNetdService() { - mNetdService = NetdService.get(); + mNetdService = mServices.getNetd(); } /** @@ -1567,6 +1604,17 @@ public class NetworkManagementService extends INetworkManagementService.Stub } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); } + + synchronized (mTetheringStatsProviders) { + for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) { + try { + provider.setInterfaceQuota(iface, quotaBytes); + } catch (RemoteException e) { + Log.e(TAG, "Problem setting tethering data limit on provider " + + mTetheringStatsProviders.get(provider) + ": " + e); + } + } + } } } @@ -1593,6 +1641,17 @@ public class NetworkManagementService extends INetworkManagementService.Stub } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); } + + synchronized (mTetheringStatsProviders) { + for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) { + try { + provider.setInterfaceQuota(iface, ITetheringStatsProvider.QUOTA_UNLIMITED); + } catch (RemoteException e) { + Log.e(TAG, "Problem removing tethering data limit on provider " + + mTetheringStatsProviders.get(provider) + ": " + e); + } + } + } } } @@ -1803,12 +1862,14 @@ public class NetworkManagementService extends INetworkManagementService.Stub // netd does not keep state on strict mode policies, and cannot replace a non-accept // policy without deleting it first. Rather than add state to netd, just always send // it an accept policy when switching between two non-accept policies. + // TODO: consider keeping state in netd so we can simplify this code. if (oldPolicy != StrictMode.NETWORK_POLICY_ACCEPT && policy != StrictMode.NETWORK_POLICY_ACCEPT) { - applyUidCleartextNetworkPolicy(uid, policy); + applyUidCleartextNetworkPolicy(uid, StrictMode.NETWORK_POLICY_ACCEPT); } + + applyUidCleartextNetworkPolicy(uid, policy); } - applyUidCleartextNetworkPolicy(uid, policy); } @Override @@ -1829,7 +1890,13 @@ public class NetworkManagementService extends INetworkManagementService.Stub private class NetdTetheringStatsProvider extends ITetheringStatsProvider.Stub { @Override - public NetworkStats getTetherStats() { + public NetworkStats getTetherStats(int how) { + // We only need to return per-UID stats. Per-device stats are already counted by + // interface counters. + if (how != STATS_PER_UID) { + return new NetworkStats(SystemClock.elapsedRealtime(), 0); + } + final NativeDaemonEvent[] events; try { events = mConnector.executeForList("bandwidth", "gettetherstats"); @@ -1864,17 +1931,22 @@ public class NetworkManagementService extends INetworkManagementService.Stub } return stats; } + + @Override + public void setInterfaceQuota(String iface, long quotaBytes) { + // Do nothing. netd is already informed of quota changes in setInterfaceQuota. + } } @Override - public NetworkStats getNetworkStatsTethering() { + public NetworkStats getNetworkStatsTethering(int how) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1); synchronized (mTetheringStatsProviders) { for (ITetheringStatsProvider provider: mTetheringStatsProviders.keySet()) { try { - stats.combineAllValues(provider.getTetherStats()); + stats.combineAllValues(provider.getTetherStats(how)); } catch (RemoteException e) { Log.e(TAG, "Problem reading tethering stats from " + mTetheringStatsProviders.get(provider) + ": " + e); diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java index d60df83da68e..44c02270fe6c 100644 --- a/services/core/java/com/android/server/NetworkScoreService.java +++ b/services/core/java/com/android/server/NetworkScoreService.java @@ -46,7 +46,6 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; -import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.UserHandle; @@ -640,42 +639,22 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } } - private boolean callerCanRequestScores() { - // REQUEST_NETWORK_SCORES is a signature only permission. - return mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES) == - PackageManager.PERMISSION_GRANTED; - } - - private boolean callerCanScoreNetworks() { - return mContext.checkCallingOrSelfPermission(permission.SCORE_NETWORKS) == - PackageManager.PERMISSION_GRANTED; - } - @Override public boolean clearScores() { // Only the active scorer or the system should be allowed to flush all scores. - if (isCallerActiveScorer(getCallingUid()) || callerCanRequestScores()) { - final long token = Binder.clearCallingIdentity(); - try { - clearInternal(); - return true; - } finally { - Binder.restoreCallingIdentity(token); - } - } else { - throw new SecurityException( - "Caller is neither the active scorer nor the scorer manager."); + enforceSystemOrIsActiveScorer(getCallingUid()); + final long token = Binder.clearCallingIdentity(); + try { + clearInternal(); + return true; + } finally { + Binder.restoreCallingIdentity(token); } } @Override public boolean setActiveScorer(String packageName) { - // Only the system can set the active scorer - if (!isCallerSystemProcess(getCallingUid()) && !callerCanScoreNetworks()) { - throw new SecurityException( - "Caller is neither the system process or a network scorer."); - } - + enforceSystemOrHasScoreNetworks(); return mNetworkScorerAppManager.setActiveScorer(packageName); } @@ -693,8 +672,29 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } } - private boolean isCallerSystemProcess(int callingUid) { - return callingUid == Process.SYSTEM_UID; + private void enforceSystemOnly() throws SecurityException { + // REQUEST_NETWORK_SCORES is a signature only permission. + mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, + "Caller must be granted REQUEST_NETWORK_SCORES."); + } + + private void enforceSystemOrHasScoreNetworks() throws SecurityException { + if (mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES) + != PackageManager.PERMISSION_GRANTED + && mContext.checkCallingOrSelfPermission(permission.SCORE_NETWORKS) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException( + "Caller is neither the system process or a network scorer."); + } + } + + private void enforceSystemOrIsActiveScorer(int callingUid) throws SecurityException { + if (mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES) + != PackageManager.PERMISSION_GRANTED + && !isCallerActiveScorer(callingUid)) { + throw new SecurityException( + "Caller is neither the system process or the active network scorer."); + } } /** @@ -705,6 +705,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub { */ @Override public String getActiveScorerPackage() { + enforceSystemOrHasScoreNetworks(); synchronized (mServiceConnectionLock) { if (mServiceConnection != null) { return mServiceConnection.getPackageName(); @@ -719,15 +720,11 @@ public class NetworkScoreService extends INetworkScoreService.Stub { @Override public NetworkScorerAppData getActiveScorer() { // Only the system can access this data. - if (isCallerSystemProcess(getCallingUid()) || callerCanRequestScores()) { - synchronized (mServiceConnectionLock) { - if (mServiceConnection != null) { - return mServiceConnection.getAppData(); - } + enforceSystemOnly(); + synchronized (mServiceConnectionLock) { + if (mServiceConnection != null) { + return mServiceConnection.getAppData(); } - } else { - throw new SecurityException( - "Caller is neither the system process nor a score requester."); } return null; @@ -740,22 +737,14 @@ public class NetworkScoreService extends INetworkScoreService.Stub { @Override public List<NetworkScorerAppData> getAllValidScorers() { // Only the system can access this data. - if (!isCallerSystemProcess(getCallingUid()) && !callerCanRequestScores()) { - throw new SecurityException( - "Caller is neither the system process nor a score requester."); - } - + enforceSystemOnly(); return mNetworkScorerAppManager.getAllValidScorers(); } @Override public void disableScoring() { // Only the active scorer or the system should be allowed to disable scoring. - if (!isCallerActiveScorer(getCallingUid()) && !callerCanRequestScores()) { - throw new SecurityException( - "Caller is neither the active scorer nor the scorer manager."); - } - + enforceSystemOrIsActiveScorer(getCallingUid()); // no-op for now but we could write to the setting if needed. } @@ -779,7 +768,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub { public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache, int filterType) { - mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG); + enforceSystemOnly(); final long token = Binder.clearCallingIdentity(); try { synchronized (mScoreCaches) { @@ -804,7 +793,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub { @Override public void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) { - mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG); + enforceSystemOnly(); final long token = Binder.clearCallingIdentity(); try { synchronized (mScoreCaches) { @@ -825,7 +814,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub { @Override public boolean requestScores(NetworkKey[] networks) { - mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG); + enforceSystemOnly(); final long token = Binder.clearCallingIdentity(); try { final INetworkRecommendationProvider provider = getRecommendationProvider(); diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java index c8dc5fcfa4a0..7cd34065c427 100644 --- a/services/core/java/com/android/server/TextServicesManagerService.java +++ b/services/core/java/com/android/server/TextServicesManagerService.java @@ -16,7 +16,6 @@ package com.android.server; -import com.android.internal.annotations.GuardedBy; import com.android.internal.content.PackageMonitor; import com.android.internal.inputmethod.InputMethodUtils; import com.android.internal.textservice.ISpellCheckerService; @@ -32,23 +31,19 @@ import org.xmlpull.v1.XmlPullParserException; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; -import android.app.ActivityManager; -import android.app.AppGlobals; -import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.content.pm.UserInfo; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; -import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.UserHandle; @@ -57,6 +52,7 @@ import android.provider.Settings; import android.service.textservice.SpellCheckerService; import android.text.TextUtils; import android.util.Slog; +import android.util.SparseArray; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; import android.view.textservice.SpellCheckerInfo; @@ -77,20 +73,192 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { private static final boolean DBG = false; private final Context mContext; - private boolean mIsCurrentUserUnlockingOrUnlocked; private final TextServicesMonitor mMonitor; - private final HashMap<String, SpellCheckerInfo> mSpellCheckerMap = new HashMap<>(); - private final ArrayList<SpellCheckerInfo> mSpellCheckerList = new ArrayList<>(); - private final HashMap<String, SpellCheckerBindGroup> mSpellCheckerBindGroups = new HashMap<>(); - @UserIdInt - private int mCurrentUserId; - private int[] mCurrentProfileIds = new int[0]; - private final TextServicesSettings mSettings; + private final SparseArray<TextServicesData> mUserData = new SparseArray<>(); @NonNull private final UserManager mUserManager; private final Object mLock = new Object(); - @GuardedBy("mLock") - private int mSpellCheckerMapUpdateCount = 0; + + private static class TextServicesData { + @UserIdInt + private final int mUserId; + private final HashMap<String, SpellCheckerInfo> mSpellCheckerMap; + private final ArrayList<SpellCheckerInfo> mSpellCheckerList; + private final HashMap<String, SpellCheckerBindGroup> mSpellCheckerBindGroups; + private final Context mContext; + private final ContentResolver mResolver; + public int mUpdateCount = 0; + + public TextServicesData(@UserIdInt int userId, @NonNull Context context) { + mUserId = userId; + mSpellCheckerMap = new HashMap<>(); + mSpellCheckerList = new ArrayList<>(); + mSpellCheckerBindGroups = new HashMap<>(); + mContext = context; + mResolver = context.getContentResolver(); + } + + private void putString(final String key, final String str) { + Settings.Secure.putStringForUser(mResolver, key, str, mUserId); + } + + @Nullable + private String getString(@NonNull final String key, @Nullable final String defaultValue) { + final String result; + result = Settings.Secure.getStringForUser(mResolver, key, mUserId); + return result != null ? result : defaultValue; + } + + private void putInt(final String key, final int value) { + Settings.Secure.putIntForUser(mResolver, key, value, mUserId); + } + + private int getInt(final String key, final int defaultValue) { + return Settings.Secure.getIntForUser(mResolver, key, defaultValue, mUserId); + } + + private boolean getBoolean(final String key, final boolean defaultValue) { + return getInt(key, defaultValue ? 1 : 0) == 1; + } + + private void putSelectedSpellChecker(@Nullable String sciId) { + putString(Settings.Secure.SELECTED_SPELL_CHECKER, sciId); + } + + private void putSelectedSpellCheckerSubtype(int hashCode) { + putInt(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, hashCode); + } + + @NonNull + private String getSelectedSpellChecker() { + return getString(Settings.Secure.SELECTED_SPELL_CHECKER, ""); + } + + public int getSelectedSpellCheckerSubtype(final int defaultValue) { + return getInt(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, defaultValue); + } + + public boolean isSpellCheckerEnabled() { + return getBoolean(Settings.Secure.SPELL_CHECKER_ENABLED, true); + } + + @Nullable + public SpellCheckerInfo getCurrentSpellChecker() { + final String curSpellCheckerId = getSelectedSpellChecker(); + if (TextUtils.isEmpty(curSpellCheckerId)) { + return null; + } + return mSpellCheckerMap.get(curSpellCheckerId); + } + + public void setCurrentSpellChecker(@Nullable SpellCheckerInfo sci) { + if (sci != null) { + putSelectedSpellChecker(sci.getId()); + } else { + putSelectedSpellChecker(""); + } + putSelectedSpellCheckerSubtype(SpellCheckerSubtype.SUBTYPE_ID_NONE); + } + + private void initializeTextServicesData() { + if (DBG) { + Slog.d(TAG, "initializeTextServicesData for user: " + mUserId); + } + mSpellCheckerList.clear(); + mSpellCheckerMap.clear(); + mUpdateCount++; + final PackageManager pm = mContext.getPackageManager(); + // Note: We do not specify PackageManager.MATCH_ENCRYPTION_* flags here because the + // default behavior of PackageManager is exactly what we want. It by default picks up + // appropriate services depending on the unlock state for the specified user. + final List<ResolveInfo> services = pm.queryIntentServicesAsUser( + new Intent(SpellCheckerService.SERVICE_INTERFACE), PackageManager.GET_META_DATA, + mUserId); + final int N = services.size(); + for (int i = 0; i < N; ++i) { + final ResolveInfo ri = services.get(i); + final ServiceInfo si = ri.serviceInfo; + final ComponentName compName = new ComponentName(si.packageName, si.name); + if (!android.Manifest.permission.BIND_TEXT_SERVICE.equals(si.permission)) { + Slog.w(TAG, "Skipping text service " + compName + + ": it does not require the permission " + + android.Manifest.permission.BIND_TEXT_SERVICE); + continue; + } + if (DBG) Slog.d(TAG, "Add: " + compName + " for user: " + mUserId); + try { + final SpellCheckerInfo sci = new SpellCheckerInfo(mContext, ri); + if (sci.getSubtypeCount() <= 0) { + Slog.w(TAG, "Skipping text service " + compName + + ": it does not contain subtypes."); + continue; + } + mSpellCheckerList.add(sci); + mSpellCheckerMap.put(sci.getId(), sci); + } catch (XmlPullParserException e) { + Slog.w(TAG, "Unable to load the spell checker " + compName, e); + } catch (IOException e) { + Slog.w(TAG, "Unable to load the spell checker " + compName, e); + } + } + if (DBG) { + Slog.d(TAG, "initializeSpellCheckerMap: " + mSpellCheckerList.size() + "," + + mSpellCheckerMap.size()); + } + } + + private void dump(PrintWriter pw) { + int spellCheckerIndex = 0; + pw.println(" User #" + mUserId); + pw.println(" Spell Checkers:"); + pw.println(" Spell Checkers: " + "mUpdateCount=" + mUpdateCount); + for (final SpellCheckerInfo info : mSpellCheckerMap.values()) { + pw.println(" Spell Checker #" + spellCheckerIndex); + info.dump(pw, " "); + ++spellCheckerIndex; + } + + pw.println(""); + pw.println(" Spell Checker Bind Groups:"); + HashMap<String, SpellCheckerBindGroup> spellCheckerBindGroups = mSpellCheckerBindGroups; + for (final Map.Entry<String, SpellCheckerBindGroup> ent + : spellCheckerBindGroups.entrySet()) { + final SpellCheckerBindGroup grp = ent.getValue(); + pw.println(" " + ent.getKey() + " " + grp + ":"); + pw.println(" " + "mInternalConnection=" + grp.mInternalConnection); + pw.println(" " + "mSpellChecker=" + grp.mSpellChecker); + pw.println(" " + "mUnbindCalled=" + grp.mUnbindCalled); + pw.println(" " + "mConnected=" + grp.mConnected); + final int numPendingSessionRequests = grp.mPendingSessionRequests.size(); + for (int j = 0; j < numPendingSessionRequests; j++) { + final SessionRequest req = grp.mPendingSessionRequests.get(j); + pw.println(" " + "Pending Request #" + j + ":"); + pw.println(" " + "mTsListener=" + req.mTsListener); + pw.println(" " + "mScListener=" + req.mScListener); + pw.println( + " " + "mScLocale=" + req.mLocale + " mUid=" + req.mUserId); + } + final int numOnGoingSessionRequests = grp.mOnGoingSessionRequests.size(); + for (int j = 0; j < numOnGoingSessionRequests; j++) { + final SessionRequest req = grp.mOnGoingSessionRequests.get(j); + pw.println(" " + "On going Request #" + j + ":"); + ++j; + pw.println(" " + "mTsListener=" + req.mTsListener); + pw.println(" " + "mScListener=" + req.mScListener); + pw.println( + " " + "mScLocale=" + req.mLocale + " mUid=" + req.mUserId); + } + final int N = grp.mListeners.getRegisteredCallbackCount(); + for (int j = 0; j < N; j++) { + final ISpellCheckerSessionListener mScListener = + grp.mListeners.getRegisteredCallbackItem(j); + pw.println(" " + "Listener #" + j + ":"); + pw.println(" " + "mScListener=" + mScListener); + pw.println(" " + "mGroup=" + grp); + } + } + } + } public static final class Lifecycle extends SystemService { private TextServicesManagerService mService; @@ -106,285 +274,153 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } @Override - public void onSwitchUser(@UserIdInt int userHandle) { - // Called on the system server's main looper thread. - // TODO: Dispatch this to a worker thread as needed. - mService.onSwitchUser(userHandle); + public void onStopUser(@UserIdInt int userHandle) { + if (DBG) { + Slog.d(TAG, "onStopUser userId: " + userHandle); + } + mService.onStopUser(userHandle); } @Override public void onUnlockUser(@UserIdInt int userHandle) { + if(DBG) { + Slog.d(TAG, "onUnlockUser userId: " + userHandle); + } // Called on the system server's main looper thread. // TODO: Dispatch this to a worker thread as needed. mService.onUnlockUser(userHandle); } } - void onSwitchUser(@UserIdInt int userId) { + void onStopUser(@UserIdInt int userId) { synchronized (mLock) { - mIsCurrentUserUnlockingOrUnlocked = mUserManager.isUserUnlockingOrUnlocked(userId); - resetInternalStateLocked(userId); - if (mIsCurrentUserUnlockingOrUnlocked) { - initializeInternalStateLocked(mCurrentUserId); - } + // Clean per-user data + TextServicesData tsd = mUserData.get(userId); + if (tsd == null) return; + + unbindServiceLocked(tsd); // Remove bind groups first + mUserData.remove(userId); // This needs to be done after bind groups are all removed } } void onUnlockUser(@UserIdInt int userId) { synchronized (mLock) { - final int currentUserId = mCurrentUserId; - if (userId != currentUserId) { - return; - } - if (!mIsCurrentUserUnlockingOrUnlocked) { - mIsCurrentUserUnlockingOrUnlocked = true; - resetInternalStateLocked(mCurrentUserId); - initializeInternalStateLocked(mCurrentUserId); - } + // Initialize internal state for the given user + initializeInternalStateLocked(userId); } } public TextServicesManagerService(Context context) { - mIsCurrentUserUnlockingOrUnlocked = false; mContext = context; - mUserManager = mContext.getSystemService(UserManager.class); - final IntentFilter broadcastFilter = new IntentFilter(); - broadcastFilter.addAction(Intent.ACTION_USER_ADDED); - broadcastFilter.addAction(Intent.ACTION_USER_REMOVED); - mContext.registerReceiver(new TextServicesBroadcastReceiver(), broadcastFilter); - - int userId = UserHandle.USER_SYSTEM; - try { - userId = ActivityManager.getService().getCurrentUser().id; - } catch (RemoteException e) { - Slog.w(TAG, "Couldn't get current user ID; guessing it's 0", e); - } mMonitor = new TextServicesMonitor(); - mMonitor.register(context, null, true); - mCurrentUserId = userId; - mCurrentProfileIds = mUserManager.getProfileIdsWithDisabled(userId); - mSettings = new TextServicesSettings(context.getContentResolver()); - } - - private void resetInternalStateLocked(@UserIdInt int userId) { - mCurrentUserId = userId; - mCurrentProfileIds = mUserManager.getProfileIdsWithDisabled(userId); - unbindServiceLocked(); - mSpellCheckerList.clear(); - mSpellCheckerMap.clear(); + mMonitor.register(context, null, UserHandle.ALL, true); } private void initializeInternalStateLocked(@UserIdInt int userId) { - buildSpellCheckerMapLocked(mContext, mSpellCheckerList, mSpellCheckerMap, mCurrentUserId); - SpellCheckerInfo sci = getCurrentSpellChecker(null); + TextServicesData tsd = mUserData.get(userId); + if (tsd == null) { + tsd = new TextServicesData(userId, mContext); + mUserData.put(userId, tsd); + } + + tsd.initializeTextServicesData(); + SpellCheckerInfo sci = tsd.getCurrentSpellChecker(); if (sci == null) { - sci = findAvailSpellCheckerLocked(null); - if (sci != null) { - // Set the current spell checker if there is one or more spell checkers - // available. In this case, "sci" is the first one in the available spell - // checkers. - setCurrentSpellCheckerLocked(sci); - } + sci = findAvailSystemSpellCheckerLocked(null, tsd); + // Set the current spell checker if there is one or more system spell checkers + // available. In this case, "sci" is the first one in the available spell + // checkers. + setCurrentSpellCheckerLocked(sci, tsd); } } private final class TextServicesMonitor extends PackageMonitor { - private boolean isChangingPackagesOfCurrentUser() { - final int userId = getChangingUserId(); - final boolean retval = userId == mCurrentUserId; - if (DBG) { - Slog.d(TAG, "--- ignore this call back from a background user: " + userId); - } - return retval; - } - @Override public void onSomePackagesChanged() { - if (!isChangingPackagesOfCurrentUser()) { - return; + int userId = getChangingUserId(); + if(DBG) { + Slog.d(TAG, "onSomePackagesChanged: " + userId); } + synchronized (mLock) { + TextServicesData tsd = mUserData.get(userId); + if (tsd == null) return; + // TODO: Update for each locale - SpellCheckerInfo sci = getCurrentSpellChecker(null); - buildSpellCheckerMapLocked( - mContext, mSpellCheckerList, mSpellCheckerMap, mCurrentUserId); - // If no spell checker is enabled, just return. The user should explicitly + SpellCheckerInfo sci = tsd.getCurrentSpellChecker(); + tsd.initializeTextServicesData(); + // If spell checker is disabled, just return. The user should explicitly // enable the spell checker. - if (sci == null) return; - final String packageName = sci.getPackageName(); - final int change = isPackageDisappearing(packageName); - if (// Package disappearing - change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE - // Package modified - || isPackageModified(packageName)) { - SpellCheckerInfo availSci = findAvailSpellCheckerLocked(packageName); - // Set the spell checker settings if different than before - if (availSci != null && !availSci.getId().equals(sci.getId())) { - setCurrentSpellCheckerLocked(availSci); + if (!tsd.isSpellCheckerEnabled()) return; + + if (sci == null) { + sci = findAvailSystemSpellCheckerLocked(null, tsd); + // Set the current spell checker if there is one or more system spell checkers + // available. In this case, "sci" is the first one in the available spell + // checkers. + setCurrentSpellCheckerLocked(sci, tsd); + } else { + final String packageName = sci.getPackageName(); + final int change = isPackageDisappearing(packageName); + if (DBG) Slog.d(TAG, "Changing package name: " + packageName); + if (// Package disappearing + change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE + // Package modified + || isPackageModified(packageName)) { + SpellCheckerInfo availSci = + findAvailSystemSpellCheckerLocked(packageName, tsd); + // Set the spell checker settings if different than before + if (availSci == null + || (availSci != null && !availSci.getId().equals(sci.getId()))) { + setCurrentSpellCheckerLocked(availSci, tsd); + } } } } } } - private final class TextServicesBroadcastReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (Intent.ACTION_USER_ADDED.equals(action) - || Intent.ACTION_USER_REMOVED.equals(action)) { - synchronized (mLock) { - mCurrentProfileIds = mUserManager.getProfileIdsWithDisabled(mCurrentUserId); - } - return; - } - Slog.w(TAG, "Unexpected intent " + intent); - } - } - - private void buildSpellCheckerMapLocked(Context context, - ArrayList<SpellCheckerInfo> list, HashMap<String, SpellCheckerInfo> map, - @UserIdInt int userId) { - list.clear(); - map.clear(); - mSpellCheckerMapUpdateCount++; - final PackageManager pm = context.getPackageManager(); - // Note: We do not specify PackageManager.MATCH_ENCRYPTION_* flags here because the default - // behavior of PackageManager is exactly what we want. It by default picks up appropriate - // services depending on the unlock state for the specified user. - final List<ResolveInfo> services = pm.queryIntentServicesAsUser( - new Intent(SpellCheckerService.SERVICE_INTERFACE), PackageManager.GET_META_DATA, - userId); - final int N = services.size(); - for (int i = 0; i < N; ++i) { - final ResolveInfo ri = services.get(i); - final ServiceInfo si = ri.serviceInfo; - final ComponentName compName = new ComponentName(si.packageName, si.name); - if (!android.Manifest.permission.BIND_TEXT_SERVICE.equals(si.permission)) { - Slog.w(TAG, "Skipping text service " + compName - + ": it does not require the permission " - + android.Manifest.permission.BIND_TEXT_SERVICE); - continue; - } - if (DBG) Slog.d(TAG, "Add: " + compName); - try { - final SpellCheckerInfo sci = new SpellCheckerInfo(context, ri); - if (sci.getSubtypeCount() <= 0) { - Slog.w(TAG, "Skipping text service " + compName - + ": it does not contain subtypes."); - continue; - } - list.add(sci); - map.put(sci.getId(), sci); - } catch (XmlPullParserException e) { - Slog.w(TAG, "Unable to load the spell checker " + compName, e); - } catch (IOException e) { - Slog.w(TAG, "Unable to load the spell checker " + compName, e); - } - } - if (DBG) { - Slog.d(TAG, "buildSpellCheckerMapLocked: " + list.size() + "," + map.size()); - } - } - - // --------------------------------------------------------------------------------------- - // Check whether or not this is a valid IPC. Assumes an IPC is valid when either - // 1) it comes from the system process - // 2) the calling process' user id is identical to the current user id TSMS thinks. - // We ignore requests for when the current user has not unlocked or been unlocking. - private boolean calledFromValidUser() { - final int uid = Binder.getCallingUid(); - final int userId = UserHandle.getUserId(uid); - final boolean isCurrentProfile; - synchronized (mLock) { - if (!mIsCurrentUserUnlockingOrUnlocked) { - return false; - } - isCurrentProfile = isCurrentProfileLocked(userId); - } - if (DBG) { - Slog.d(TAG, "--- calledFromForegroundUserOrSystemProcess ? " - + "calling uid = " + uid + " system uid = " + Process.SYSTEM_UID - + " calling userId = " + userId + ", foreground user id = " - + mCurrentUserId + ", calling pid = " + Binder.getCallingPid()); - try { - final String[] packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid); - for (int i = 0; i < packageNames.length; ++i) { - if (DBG) { - Slog.d(TAG, "--- process name for "+ uid + " = " + packageNames[i]); - } - } - } catch (RemoteException e) { - } - } - - if (uid == Process.SYSTEM_UID || userId == mCurrentUserId) { - return true; - } - - // Permits current profile to use TSFM as long as the current text service is the system's - // one. This is a tentative solution and should be replaced with fully functional multiuser - // support. - // TODO: Implement multiuser support in TSMS. - if (DBG) { - Slog.d(TAG, "--- userId = "+ userId + " isCurrentProfile = " + isCurrentProfile); - } - if (isCurrentProfile) { - final SpellCheckerInfo spellCheckerInfo = getCurrentSpellCheckerWithoutVerification(); - if (spellCheckerInfo != null) { - final ServiceInfo serviceInfo = spellCheckerInfo.getServiceInfo(); - final boolean isSystemSpellChecker = - (serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; - if (DBG) { - Slog.d(TAG, "--- current spell checker = "+ spellCheckerInfo.getPackageName() - + " isSystem = " + isSystemSpellChecker); - } - if (isSystemSpellChecker) { - return true; - } - } - } - - // Unlike InputMethodManagerService#calledFromValidUser, INTERACT_ACROSS_USERS_FULL isn't - // taken into account here. Anyway this method is supposed to be removed once multiuser - // support is implemented. - if (DBG) { - Slog.d(TAG, "--- IPC from userId:" + userId + " is being ignored. \n" - + getStackTrace()); - } - return false; - } - private boolean bindCurrentSpellCheckerService( - Intent service, ServiceConnection conn, int flags) { + Intent service, ServiceConnection conn, int flags, @UserIdInt int userId) { if (service == null || conn == null) { - Slog.e(TAG, "--- bind failed: service = " + service + ", conn = " + conn); + Slog.e(TAG, "--- bind failed: service = " + service + ", conn = " + conn + + ", userId =" + userId); return false; } - return mContext.bindServiceAsUser(service, conn, flags, UserHandle.of(mCurrentUserId)); + return mContext.bindServiceAsUser(service, conn, flags, UserHandle.of(userId)); } - private void unbindServiceLocked() { - for (SpellCheckerBindGroup scbg : mSpellCheckerBindGroups.values()) { + private void unbindServiceLocked(TextServicesData tsd) { + HashMap<String, SpellCheckerBindGroup> spellCheckerBindGroups = tsd.mSpellCheckerBindGroups; + for (SpellCheckerBindGroup scbg : spellCheckerBindGroups.values()) { scbg.removeAllLocked(); } - mSpellCheckerBindGroups.clear(); + spellCheckerBindGroups.clear(); } - private SpellCheckerInfo findAvailSpellCheckerLocked(String prefPackage) { - final int spellCheckersCount = mSpellCheckerList.size(); + private SpellCheckerInfo findAvailSystemSpellCheckerLocked(String prefPackage, + TextServicesData tsd) { + // Filter the spell checker list to remove spell checker services that are not pre-installed + ArrayList<SpellCheckerInfo> spellCheckerList = new ArrayList<>(); + for (SpellCheckerInfo sci : tsd.mSpellCheckerList) { + if ((sci.getServiceInfo().applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { + spellCheckerList.add(sci); + } + } + + final int spellCheckersCount = spellCheckerList.size(); if (spellCheckersCount == 0) { Slog.w(TAG, "no available spell checker services found"); return null; } if (prefPackage != null) { for (int i = 0; i < spellCheckersCount; ++i) { - final SpellCheckerInfo sci = mSpellCheckerList.get(i); + final SpellCheckerInfo sci = spellCheckerList.get(i); if (prefPackage.equals(sci.getPackageName())) { if (DBG) { - Slog.d(TAG, "findAvailSpellCheckerLocked: " + sci.getPackageName()); + Slog.d(TAG, "findAvailSystemSpellCheckerLocked: " + sci.getPackageName()); } return sci; } @@ -398,7 +434,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { final ArrayList<Locale> suitableLocales = InputMethodUtils.getSuitableLocalesForSpellChecker(systemLocal); if (DBG) { - Slog.w(TAG, "findAvailSpellCheckerLocked suitableLocales=" + Slog.w(TAG, "findAvailSystemSpellCheckerLocked suitableLocales=" + Arrays.toString(suitableLocales.toArray(new Locale[suitableLocales.size()]))); } final int localeCount = suitableLocales.size(); @@ -406,7 +442,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { final Locale locale = suitableLocales.get(localeIndex); for (int spellCheckersIndex = 0; spellCheckersIndex < spellCheckersCount; ++spellCheckersIndex) { - final SpellCheckerInfo info = mSpellCheckerList.get(spellCheckersIndex); + final SpellCheckerInfo info = spellCheckerList.get(spellCheckersIndex); final int subtypeCount = info.getSubtypeCount(); for (int subtypeIndex = 0; subtypeIndex < subtypeCount; ++subtypeIndex) { final SpellCheckerSubtype subtype = info.getSubtypeAt(subtypeIndex); @@ -425,30 +461,19 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { if (spellCheckersCount > 1) { Slog.w(TAG, "more than one spell checker service found, picking first"); } - return mSpellCheckerList.get(0); + return spellCheckerList.get(0); } // TODO: Save SpellCheckerService by supported languages. Currently only one spell // checker is saved. @Override public SpellCheckerInfo getCurrentSpellChecker(String locale) { - // TODO: Make this work even for non-current users? - if (!calledFromValidUser()) { - return null; - } - return getCurrentSpellCheckerWithoutVerification(); - } - - private SpellCheckerInfo getCurrentSpellCheckerWithoutVerification() { + int userId = UserHandle.getCallingUserId(); synchronized (mLock) { - final String curSpellCheckerId = mSettings.getSelectedSpellChecker(mCurrentUserId); - if (DBG) { - Slog.w(TAG, "getCurrentSpellChecker: " + curSpellCheckerId); - } - if (TextUtils.isEmpty(curSpellCheckerId)) { - return null; - } - return mSpellCheckerMap.get(curSpellCheckerId); + TextServicesData tsd = mUserData.get(userId); + if (tsd == null) return null; + + return tsd.getCurrentSpellChecker(); } } @@ -457,21 +482,21 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { @Override public SpellCheckerSubtype getCurrentSpellCheckerSubtype( String locale, boolean allowImplicitlySelectedSubtype) { - // TODO: Make this work even for non-current users? - if (!calledFromValidUser()) { - return null; - } final int subtypeHashCode; final SpellCheckerInfo sci; final Locale systemLocale; + final int userId = UserHandle.getCallingUserId(); + synchronized (mLock) { + TextServicesData tsd = mUserData.get(userId); + if (tsd == null) return null; + subtypeHashCode = - mSettings.getSelectedSpellCheckerSubtype(SpellCheckerSubtype.SUBTYPE_ID_NONE, - mCurrentUserId); + tsd.getSelectedSpellCheckerSubtype(SpellCheckerSubtype.SUBTYPE_ID_NONE); if (DBG) { Slog.w(TAG, "getCurrentSpellCheckerSubtype: " + subtypeHashCode); } - sci = getCurrentSpellChecker(null); + sci = tsd.getCurrentSpellChecker(); systemLocale = mContext.getResources().getConfiguration().locale; } if (sci == null || sci.getSubtypeCount() == 0) { @@ -537,24 +562,29 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { public void getSpellCheckerService(String sciId, String locale, ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener, Bundle bundle) { - if (!calledFromValidUser()) { - return; - } if (TextUtils.isEmpty(sciId) || tsListener == null || scListener == null) { Slog.e(TAG, "getSpellCheckerService: Invalid input."); return; } + int callingUserId = UserHandle.getCallingUserId(); + synchronized (mLock) { - if (!mSpellCheckerMap.containsKey(sciId)) { + TextServicesData tsd = mUserData.get(callingUserId); + if (tsd == null) return; + + HashMap<String, SpellCheckerInfo> spellCheckerMap = tsd.mSpellCheckerMap; + if (!spellCheckerMap.containsKey(sciId)) { return; } - final SpellCheckerInfo sci = mSpellCheckerMap.get(sciId); - SpellCheckerBindGroup bindGroup = mSpellCheckerBindGroups.get(sciId); + final SpellCheckerInfo sci = spellCheckerMap.get(sciId); + HashMap<String, SpellCheckerBindGroup> spellCheckerBindGroups = + tsd.mSpellCheckerBindGroups; + SpellCheckerBindGroup bindGroup = spellCheckerBindGroups.get(sciId); final int uid = Binder.getCallingUid(); if (bindGroup == null) { final long ident = Binder.clearCallingIdentity(); try { - bindGroup = startSpellCheckerServiceInnerLocked(sci); + bindGroup = startSpellCheckerServiceInnerLocked(sci, tsd); } finally { Binder.restoreCallingIdentity(ident); } @@ -573,62 +603,76 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { @Override public boolean isSpellCheckerEnabled() { - if (!calledFromValidUser()) { - return false; - } + int userId = UserHandle.getCallingUserId(); + synchronized (mLock) { - return isSpellCheckerEnabledLocked(); + TextServicesData tsd = mUserData.get(userId); + if (tsd == null) return false; + + return tsd.isSpellCheckerEnabled(); } } @Nullable - private SpellCheckerBindGroup startSpellCheckerServiceInnerLocked(SpellCheckerInfo info) { + private SpellCheckerBindGroup startSpellCheckerServiceInnerLocked(SpellCheckerInfo info, + TextServicesData tsd) { if (DBG) { Slog.w(TAG, "Start spell checker session inner locked."); } final String sciId = info.getId(); - final InternalServiceConnection connection = new InternalServiceConnection(sciId); + final InternalServiceConnection connection = new InternalServiceConnection(sciId, + tsd.mSpellCheckerBindGroups); final Intent serviceIntent = new Intent(SpellCheckerService.SERVICE_INTERFACE); serviceIntent.setComponent(info.getComponent()); if (DBG) { Slog.w(TAG, "bind service: " + info.getId()); } if (!bindCurrentSpellCheckerService(serviceIntent, connection, - Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT_BACKGROUND)) { + Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT_BACKGROUND, tsd.mUserId)) { Slog.e(TAG, "Failed to get a spell checker service."); return null; } final SpellCheckerBindGroup group = new SpellCheckerBindGroup(connection); - mSpellCheckerBindGroups.put(sciId, group); + + tsd.mSpellCheckerBindGroups.put(sciId, group); return group; } @Override public SpellCheckerInfo[] getEnabledSpellCheckers() { - // TODO: Make this work even for non-current users? - if (!calledFromValidUser()) { - return null; - } - if (DBG) { - Slog.d(TAG, "getEnabledSpellCheckers: " + mSpellCheckerList.size()); - for (int i = 0; i < mSpellCheckerList.size(); ++i) { - Slog.d(TAG, "EnabledSpellCheckers: " + mSpellCheckerList.get(i).getPackageName()); + int callingUserId = UserHandle.getCallingUserId(); + + synchronized (mLock) { + TextServicesData tsd = mUserData.get(callingUserId); + if (tsd == null) return null; + + ArrayList<SpellCheckerInfo> spellCheckerList = tsd.mSpellCheckerList; + if (DBG) { + Slog.d(TAG, "getEnabledSpellCheckers: " + spellCheckerList.size()); + for (int i = 0; i < spellCheckerList.size(); ++i) { + Slog.d(TAG, + "EnabledSpellCheckers: " + spellCheckerList.get(i).getPackageName()); + } } + return spellCheckerList.toArray(new SpellCheckerInfo[spellCheckerList.size()]); } - return mSpellCheckerList.toArray(new SpellCheckerInfo[mSpellCheckerList.size()]); } @Override public void finishSpellCheckerService(ISpellCheckerSessionListener listener) { - if (!calledFromValidUser()) { - return; - } if (DBG) { Slog.d(TAG, "FinishSpellCheckerService"); } + int userId = UserHandle.getCallingUserId(); + synchronized (mLock) { + TextServicesData tsd = mUserData.get(userId); + if (tsd == null) return; + final ArrayList<SpellCheckerBindGroup> removeList = new ArrayList<>(); - for (SpellCheckerBindGroup group : mSpellCheckerBindGroups.values()) { + HashMap<String, SpellCheckerBindGroup> spellCheckerBindGroups = + tsd.mSpellCheckerBindGroups; + for (SpellCheckerBindGroup group : spellCheckerBindGroups.values()) { if (group == null) continue; // Use removeList to avoid modifying mSpellCheckerBindGroups in this loop. removeList.add(group); @@ -640,48 +684,14 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } } - private void setCurrentSpellCheckerLocked(SpellCheckerInfo sci) { - final String sciId = sci.getId(); + private void setCurrentSpellCheckerLocked(@Nullable SpellCheckerInfo sci, TextServicesData tsd) { + final String sciId = (sci != null) ? sci.getId() : ""; if (DBG) { Slog.w(TAG, "setCurrentSpellChecker: " + sciId); } final long ident = Binder.clearCallingIdentity(); try { - mSettings.putSelectedSpellChecker(sciId, mCurrentUserId); - setCurrentSpellCheckerSubtypeLocked(0); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - private void setCurrentSpellCheckerSubtypeLocked(int hashCode) { - if (DBG) { - Slog.w(TAG, "setCurrentSpellCheckerSubtype: " + hashCode); - } - final SpellCheckerInfo sci = getCurrentSpellChecker(null); - int tempHashCode = 0; - for (int i = 0; sci != null && i < sci.getSubtypeCount(); ++i) { - if(sci.getSubtypeAt(i).hashCode() == hashCode) { - tempHashCode = hashCode; - break; - } - } - final long ident = Binder.clearCallingIdentity(); - try { - mSettings.putSelectedSpellCheckerSubtype(tempHashCode, mCurrentUserId); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - private boolean isSpellCheckerEnabledLocked() { - final long ident = Binder.clearCallingIdentity(); - try { - final boolean retval = mSettings.isSpellCheckerEnabled(mCurrentUserId); - if (DBG) { - Slog.w(TAG, "getSpellCheckerEnabled: " + retval); - } - return retval; + tsd.setCurrentSpellChecker(sci); } finally { Binder.restoreCallingIdentity(ident); } @@ -691,59 +701,38 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; - synchronized (mLock) { - pw.println("Current Text Services Manager state:"); - pw.println(" Spell Checkers: mSpellCheckerMapUpdateCount=" - + mSpellCheckerMapUpdateCount); - pw.println(" Spell Checkers:"); - int spellCheckerIndex = 0; - for (final SpellCheckerInfo info : mSpellCheckerMap.values()) { - pw.println(" Spell Checker #" + spellCheckerIndex); - info.dump(pw, " "); - ++spellCheckerIndex; + if (args.length == 0) { // Dump all users' data + synchronized (mLock) { + pw.println("Current Text Services Manager state:"); + pw.println(" Users:"); + final int numOfUsers = mUserData.size(); + for (int i = 0; i < numOfUsers; i++) { + TextServicesData tsd = mUserData.valueAt(i); + tsd.dump(pw); + } } - pw.println(""); - pw.println(" Spell Checker Bind Groups:"); - for (final Map.Entry<String, SpellCheckerBindGroup> ent - : mSpellCheckerBindGroups.entrySet()) { - final SpellCheckerBindGroup grp = ent.getValue(); - pw.println(" " + ent.getKey() + " " + grp + ":"); - pw.println(" " + "mInternalConnection=" + grp.mInternalConnection); - pw.println(" " + "mSpellChecker=" + grp.mSpellChecker); - pw.println(" " + "mUnbindCalled=" + grp.mUnbindCalled); - pw.println(" " + "mConnected=" + grp.mConnected); - final int numPendingSessionRequests = grp.mPendingSessionRequests.size(); - for (int i = 0; i < numPendingSessionRequests; i++) { - final SessionRequest req = grp.mPendingSessionRequests.get(i); - pw.println(" " + "Pending Request #" + i + ":"); - pw.println(" " + "mTsListener=" + req.mTsListener); - pw.println(" " + "mScListener=" + req.mScListener); - pw.println(" " + "mScLocale=" + req.mLocale + " mUid=" + req.mUserId); + } else { // Dump a given user's data + if (args.length != 2 || !args[0].equals("--user")) { + pw.println("Invalid arguments to text services." ); + return; + } else { + int userId = Integer.parseInt(args[1]); + UserInfo userInfo = mUserManager.getUserInfo(userId); + if (userInfo == null) { + pw.println("Non-existent user."); + return; } - final int numOnGoingSessionRequests = grp.mOnGoingSessionRequests.size(); - for (int i = 0; i < numOnGoingSessionRequests; i++) { - final SessionRequest req = grp.mOnGoingSessionRequests.get(i); - pw.println(" " + "On going Request #" + i + ":"); - ++i; - pw.println(" " + "mTsListener=" + req.mTsListener); - pw.println(" " + "mScListener=" + req.mScListener); - pw.println( - " " + "mScLocale=" + req.mLocale + " mUid=" + req.mUserId); + TextServicesData tsd = mUserData.get(userId); + if (tsd == null) { + pw.println("User needs to unlock first." ); + return; } - final int N = grp.mListeners.getRegisteredCallbackCount(); - for (int i = 0; i < N; i++) { - final ISpellCheckerSessionListener mScListener = - grp.mListeners.getRegisteredCallbackItem(i); - pw.println(" " + "Listener #" + i + ":"); - pw.println(" " + "mScListener=" + mScListener); - pw.println(" " + "mGroup=" + grp); + synchronized (mLock) { + pw.println("Current Text Services Manager state:"); + pw.println(" User " + userId + ":"); + tsd.dump(pw); } } - pw.println(""); - pw.println(" " + "mCurrentUserId=" + mCurrentUserId); - pw.println(" " + "mCurrentProfileIds=" + Arrays.toString(mCurrentProfileIds)); - pw.println(" " + "mIsCurrentUserUnlockingOrUnlocked=" - + mIsCurrentUserUnlockingOrUnlocked); } } @@ -782,10 +771,14 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { private boolean mConnected; private final ArrayList<SessionRequest> mPendingSessionRequests = new ArrayList<>(); private final ArrayList<SessionRequest> mOnGoingSessionRequests = new ArrayList<>(); + @NonNull + HashMap<String, SpellCheckerBindGroup> mSpellCheckerBindGroups; + public SpellCheckerBindGroup(InternalServiceConnection connection) { mInternalConnection = connection; mListeners = new InternalDeathRecipients(this); + mSpellCheckerBindGroups = connection.mSpellCheckerBindGroups; } public void onServiceConnectedLocked(ISpellCheckerService spellChecker) { @@ -920,8 +913,12 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { private final class InternalServiceConnection implements ServiceConnection { private final String mSciId; - public InternalServiceConnection(String id) { + @NonNull + private final HashMap<String, SpellCheckerBindGroup> mSpellCheckerBindGroups; + public InternalServiceConnection(String id, + @NonNull HashMap<String, SpellCheckerBindGroup> spellCheckerBindGroups) { mSciId = id; + mSpellCheckerBindGroups = spellCheckerBindGroups; } @Override @@ -937,6 +934,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } final ISpellCheckerService spellChecker = ISpellCheckerService.Stub.asInterface(service); + final SpellCheckerBindGroup group = mSpellCheckerBindGroups.get(mSciId); if (group != null && this == group.mInternalConnection) { group.onServiceConnectedLocked(spellChecker); @@ -993,88 +991,4 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { mBindGroup.onSessionCreated(newSession, mRequest); } } - - private boolean isCurrentProfileLocked(@UserIdInt int userId) { - if (userId == mCurrentUserId) return true; - for (int i = 0; i < mCurrentProfileIds.length; i++) { - if (userId == mCurrentProfileIds[i]) return true; - } - return false; - } - - private static final class TextServicesSettings { - private final ContentResolver mResolver; - - public TextServicesSettings(ContentResolver resolver) { - mResolver = resolver; - } - - private void putString(final String key, final String str, @UserIdInt int userId) { - Settings.Secure.putStringForUser(mResolver, key, str, userId); - } - - @Nullable - private String getString(@NonNull final String key, @Nullable final String defaultValue, - @UserIdInt int userId) { - final String result; - result = Settings.Secure.getStringForUser(mResolver, key, userId); - return result != null ? result : defaultValue; - } - - private void putInt(final String key, final int value, @UserIdInt int userId) { - Settings.Secure.putIntForUser(mResolver, key, value, userId); - } - - private int getInt(final String key, final int defaultValue, @UserIdInt int userId) { - return Settings.Secure.getIntForUser(mResolver, key, defaultValue, userId); - } - - private boolean getBoolean(final String key, final boolean defaultValue, - @UserIdInt int userId) { - return getInt(key, defaultValue ? 1 : 0, userId) == 1; - } - - public void putSelectedSpellChecker(@Nullable String sciId, @UserIdInt int userId) { - if (TextUtils.isEmpty(sciId)) { - // OK to coalesce to null, since getSelectedSpellChecker() can take care of the - // empty data scenario. - putString(Settings.Secure.SELECTED_SPELL_CHECKER, null, userId); - } else { - putString(Settings.Secure.SELECTED_SPELL_CHECKER, sciId, userId); - } - } - - public void putSelectedSpellCheckerSubtype(int hashCode, @UserIdInt int userId) { - putInt(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, hashCode, userId); - } - - @NonNull - public String getSelectedSpellChecker(@UserIdInt int userId) { - return getString(Settings.Secure.SELECTED_SPELL_CHECKER, "", userId); - } - - public int getSelectedSpellCheckerSubtype(final int defaultValue, @UserIdInt int userId) { - return getInt(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, defaultValue, userId); - } - - public boolean isSpellCheckerEnabled(@UserIdInt int userId) { - return getBoolean(Settings.Secure.SPELL_CHECKER_ENABLED, true, userId); - } - } - - // ---------------------------------------------------------------------- - // Utilities for debug - private static String getStackTrace() { - final StringBuilder sb = new StringBuilder(); - try { - throw new RuntimeException(); - } catch (RuntimeException e) { - final StackTraceElement[] frames = e.getStackTrace(); - // Start at 1 because the first frame is here and we don't care about it - for (int j = 1; j < frames.length; ++j) { - sb.append(frames[j].toString() + "\n"); - } - } - return sb.toString(); - } } diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java index 473384081656..046eb761d1c0 100644 --- a/services/core/java/com/android/server/VibratorService.java +++ b/services/core/java/com/android/server/VibratorService.java @@ -728,6 +728,9 @@ public class VibratorService extends IVibratorService.Stub return timeout; } } + if (!prebaked.shouldFallback()) { + return 0; + } final int id = prebaked.getId(); if (id < 0 || id >= mFallbackEffects.length || mFallbackEffects[id] == null) { Slog.w(TAG, "Failed to play prebaked effect, no fallback"); diff --git a/services/core/java/com/android/server/accounts/AccountManagerBackupHelper.java b/services/core/java/com/android/server/accounts/AccountManagerBackupHelper.java index 6380da5e2af8..1c77a7f451b4 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerBackupHelper.java +++ b/services/core/java/com/android/server/accounts/AccountManagerBackupHelper.java @@ -23,6 +23,7 @@ import android.annotation.IntRange; import android.annotation.NonNull; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.Signature; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.os.UserHandle; @@ -30,6 +31,7 @@ import android.text.TextUtils; import android.util.Log; import android.util.PackageUtils; import android.util.Pair; +import android.util.Slog; import android.util.Xml; import com.android.internal.annotations.GuardedBy; import com.android.internal.content.PackageMonitor; @@ -126,9 +128,18 @@ public final class AccountManagerBackupHelper { } catch (PackageManager.NameNotFoundException e) { return false; } - String currentCertDigest = PackageUtils.computeCertSha256Digest( - packageInfo.signatures[0]); - if (!certDigest.equals(currentCertDigest)) { + + // Before we used only the first signature to compute the SHA 256 but some + // apps could be singed by multiple certs and the cert order is undefined. + // We prefer the modern computation procedure where all certs are taken + // into account but also allow the value from the old computation to allow + // restoring backed up grants on an older platform version. + final String[] signaturesSha256Digests = PackageUtils.computeSignaturesSha256Digests( + packageInfo.signatures); + final String signaturesSha256Digest = PackageUtils.computeSignaturesSha256Digest( + signaturesSha256Digests); + if (!certDigest.equals(signaturesSha256Digest) && (packageInfo.signatures.length <= 1 + || !certDigest.equals(signaturesSha256Digests[0]))) { return false; } final int uid = packageInfo.applicationInfo.uid; @@ -169,8 +180,17 @@ public final class AccountManagerBackupHelper { } for (String packageName : packageNames) { - String digest = PackageUtils.computePackageCertSha256Digest( - packageManager, packageName, userId); + final PackageInfo packageInfo; + try { + packageInfo = packageManager.getPackageInfoAsUser(packageName, + PackageManager.GET_SIGNATURES, userId); + } catch (PackageManager.NameNotFoundException e) { + Slog.i(TAG, "Skipping backup of account access grant for" + + " non-existing package: " + packageName); + continue; + } + final String digest = PackageUtils.computeSignaturesSha256Digest( + packageInfo.signatures); if (digest != null) { serializer.startTag(null, TAG_PERMISSION); serializer.attribute(null, ATTR_ACCOUNT_SHA_256, diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index c6f2fc082bac..8ae592f7978a 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -2191,7 +2191,7 @@ public class AccountManagerService return false; } else if (!isAccountManagedByCaller(account.type, callingUid, userId)) { String msg = String.format( - "uid %s cannot explicitly add accounts of type: %s", + "uid %s cannot explicitly remove accounts of type: %s", callingUid, account.type); throw new SecurityException(msg); @@ -5330,25 +5330,25 @@ public class AccountManagerService long identityToken = Binder.clearCallingIdentity(); try { packages = mPackageManager.getPackagesForUid(callingUid); - } finally { - Binder.restoreCallingIdentity(identityToken); - } - if (packages == null) { - Log.d(TAG, "No packages for callingUid " + callingUid); - return false; - } - for (String name : packages) { - try { - PackageInfo packageInfo = mPackageManager.getPackageInfo(name, 0 /* flags */); - if (packageInfo != null + if (packages == null) { + Log.d(TAG, "No packages for callingUid " + callingUid); + return false; + } + for (String name : packages) { + try { + PackageInfo packageInfo = + mPackageManager.getPackageInfo(name, 0 /* flags */); + if (packageInfo != null && (packageInfo.applicationInfo.privateFlags - & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) { - return true; + & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) { + return true; + } + } catch (PackageManager.NameNotFoundException e) { + Log.d(TAG, "Package not found " + e.getMessage()); } - } catch (PackageManager.NameNotFoundException e) { - Log.d(TAG, "Package not found " + e.getMessage()); - return false; } + } finally { + Binder.restoreCallingIdentity(identityToken); } return false; } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 47f3ec69fd03..8f68bd6c2781 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -25,9 +25,11 @@ import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS; import static android.Manifest.permission.READ_FRAME_BUFFER; import static android.Manifest.permission.START_TASKS_FROM_RECENTS; import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; +import static android.app.ActivityManager.LOCK_TASK_MODE_NONE; import static android.app.ActivityManager.RESIZE_MODE_PRESERVE_WINDOW; import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; +import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID; import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; import static android.app.ActivityManager.StackId.INVALID_STACK_ID; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; @@ -173,8 +175,6 @@ import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS; import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS; import static com.android.server.am.TaskRecord.INVALID_TASK_ID; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK; -import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV; -import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE; import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT; import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE; import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN; @@ -197,7 +197,6 @@ import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityManager.StackId; import android.app.ActivityManager.StackInfo; import android.app.ActivityManager.TaskSnapshot; -import android.app.ActivityManager.TaskThumbnailInfo; import android.app.ActivityManagerInternal; import android.app.ActivityManagerInternal.SleepToken; import android.app.ActivityOptions; @@ -338,7 +337,7 @@ import android.text.style.SuggestionSpan; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; -import android.util.BootTimingsTraceLog; +import android.util.TimingsTraceLog; import android.util.DebugUtils; import android.util.DisplayMetrics; import android.util.EventLog; @@ -355,10 +354,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; -import com.android.server.job.JobSchedulerInternal; -import com.google.android.collect.Lists; -import com.google.android.collect.Maps; - import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -404,14 +399,15 @@ import com.android.server.ThreadPriorityBooster; import com.android.server.Watchdog; import com.android.server.am.ActivityStack.ActivityState; import com.android.server.firewall.IntentFirewall; +import com.android.server.job.JobSchedulerInternal; import com.android.server.pm.Installer; import com.android.server.pm.Installer.InstallerException; -import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.vr.VrManagerInternal; import com.android.server.wm.PinnedStackWindowController; import com.android.server.wm.WindowManagerService; +import com.google.android.collect.Lists; +import com.google.android.collect.Maps; -import java.text.SimpleDateFormat; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; @@ -429,6 +425,7 @@ import java.io.UnsupportedEncodingException; import java.lang.ref.WeakReference; import java.nio.charset.StandardCharsets; import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -696,6 +693,11 @@ public class ActivityManagerService extends IActivityManager.Stub */ String mDeviceOwnerName; + /** + * The controller for all operations related to locktask. + */ + final LockTaskController mLockTaskController; + final UserController mUserController; final AppErrors mAppErrors; @@ -1346,7 +1348,7 @@ public class ActivityManagerService extends IActivityManager.Stub * Set while we are running a voice interaction. This overrides * sleeping while it is active. */ - private IVoiceInteractionSession mRunningVoice; + IVoiceInteractionSession mRunningVoice; /** * For some direct access we need to power manager. @@ -1366,13 +1368,6 @@ public class ActivityManagerService extends IActivityManager.Stub private int mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE; /** - * A list of tokens that cause the top activity to be put to sleep. - * They are used by components that may hide and block interaction with underlying - * activities. - */ - final ArrayList<SleepToken> mSleepTokens = new ArrayList<SleepToken>(); - - /** * Set if we are shutting down the system, similar to sleeping. */ boolean mShuttingDown = false; @@ -1689,6 +1684,7 @@ public class ActivityManagerService extends IActivityManager.Stub static final int DISPATCH_PENDING_INTENT_CANCEL_MSG = 67; static final int PUSH_TEMP_WHITELIST_UI_MSG = 68; static final int SERVICE_FOREGROUND_CRASH_MSG = 69; + static final int USER_SWITCH_CALLBACKS_TIMEOUT_MSG = 70; static final int START_USER_SWITCH_FG_MSG = 712; static final int FIRST_ACTIVITY_STACK_MSG = 100; @@ -2147,6 +2143,10 @@ public class ActivityManagerService extends IActivityManager.Stub mUserController.timeoutUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2); break; } + case USER_SWITCH_CALLBACKS_TIMEOUT_MSG: { + mUserController.timeoutUserSwitchCallbacks(msg.arg1, msg.arg2); + break; + } case IMMERSIVE_MODE_LOCK_MSG: { final boolean nextState = (msg.arg1 != 0); if (mUpdateLock.isHeld() != nextState) { @@ -2562,6 +2562,7 @@ public class ActivityManagerService extends IActivityManager.Stub mWindowManager = wm; mStackSupervisor.setWindowManager(wm); mActivityStarter.setWindowManager(wm); + mLockTaskController.setWindowManager(wm); } public void setUsageStatsManager(UsageStatsManagerInternal usageStatsManager) { @@ -2689,6 +2690,7 @@ public class ActivityManagerService extends IActivityManager.Stub mUiHandler = injector.getUiHandler(null); mUserController = null; mVrController = null; + mLockTaskController = null; } // Note: This method is invoked on the main thread but may need to attach various @@ -2786,6 +2788,7 @@ public class ActivityManagerService extends IActivityManager.Stub new TaskChangeNotificationController(this, mStackSupervisor, mHandler); mActivityStarter = new ActivityStarter(this, mStackSupervisor); mRecentTasks = new RecentTasks(this, mStackSupervisor); + mLockTaskController = new LockTaskController(mContext, mStackSupervisor, mHandler); mProcessCpuThread = new Thread("CpuTracker") { @Override @@ -3090,7 +3093,7 @@ public class ActivityManagerService extends IActivityManager.Stub */ void setResumedActivityUncheckLocked(ActivityRecord r, String reason) { final TaskRecord task = r.getTask(); - if (task.isApplicationTask()) { + if (task.isActivityTypeStandard()) { if (mCurAppTimeTracker != r.appTimeTracker) { // We are switching app tracking. Complete the current one. if (mCurAppTimeTracker != null) { @@ -3237,6 +3240,18 @@ public class ActivityManagerService extends IActivityManager.Stub } final void applyUpdateVrModeLocked(ActivityRecord r) { + // VR apps are expected to run in a main display. If an app is turning on VR for + // itself, but lives in a dynamic stack, then make sure that it is moved to the main + // fullscreen stack before enabling VR Mode. + // TODO: The goal of this code is to keep the VR app on the main display. When the + // stack implementation changes in the future, keep in mind that the use of the fullscreen + // stack is a means to move the activity to the main display and a moveActivityToDisplay() + // option would be a better choice here. + if (r.requestedVrComponent != null && r.getStackId() >= FIRST_DYNAMIC_STACK_ID) { + Slog.i(TAG, "Moving " + r.shortComponentName + " from stack " + r.getStackId() + + " to main stack for VR"); + moveTaskToStack(r.getTask().taskId, FULLSCREEN_WORKSPACE_STACK_ID, true /* toTop */); + } mHandler.sendMessage( mHandler.obtainMessage(VR_MODE_CHANGE_MSG, 0, 0, r)); } @@ -4893,13 +4908,13 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public void reportActivityFullyDrawn(IBinder token) { + public void reportActivityFullyDrawn(IBinder token, boolean restoredFromBundle) { synchronized (this) { ActivityRecord r = ActivityRecord.isInStackLocked(token); if (r == null) { return; } - r.reportFullyDrawnLocked(); + r.reportFullyDrawnLocked(restoredFromBundle); } } @@ -4979,12 +4994,10 @@ public class ActivityManagerService extends IActivityManager.Stub } // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps can // finish. - if (tr.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV && rootR == r && - mStackSupervisor.isLastLockedTask(tr)) { - Slog.i(TAG, "Not finishing task in lock task mode"); - mStackSupervisor.showLockTaskToast(); + if (mLockTaskController.activityBlockedFromFinish(r)) { return false; } + if (mController != null) { // Find the first activity that is not finishing. ActivityRecord next = r.getStack().topRunningActivityLocked(token, 0); @@ -5110,9 +5123,7 @@ public class ActivityManagerService extends IActivityManager.Stub // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps // can finish. final TaskRecord task = r.getTask(); - if (task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV && - mStackSupervisor.isLastLockedTask(task) && task.getRootActivity() == r) { - mStackSupervisor.showLockTaskToast(); + if (mLockTaskController.activityBlockedFromFinish(r)) { return false; } return task.getStack().finishActivityAffinityLocked(r); @@ -5839,26 +5850,53 @@ public class ActivityManagerService extends IActivityManager.Stub enforceNotIsolatedCaller("clearApplicationUserData"); int uid = Binder.getCallingUid(); int pid = Binder.getCallingPid(); - userId = mUserController.handleIncomingUser(pid, uid, userId, false, + final int resolvedUserId = mUserController.handleIncomingUser(pid, uid, userId, false, ALLOW_FULL_ONLY, "clearApplicationUserData", null); + final ApplicationInfo appInfo; + final boolean isInstantApp; long callingId = Binder.clearCallingIdentity(); try { IPackageManager pm = AppGlobals.getPackageManager(); - int pkgUid = -1; synchronized(this) { + // Instant packages are not protected if (getPackageManagerInternalLocked().isPackageDataProtected( - userId, packageName)) { + resolvedUserId, packageName)) { throw new SecurityException( "Cannot clear data for a protected package: " + packageName); } + ApplicationInfo applicationInfo = null; try { - pkgUid = pm.getPackageUid(packageName, MATCH_UNINSTALLED_PACKAGES, userId); + applicationInfo = pm.getApplicationInfo(packageName, + MATCH_UNINSTALLED_PACKAGES, resolvedUserId); } catch (RemoteException e) { + /* ignore */ } - if (pkgUid == -1) { + appInfo = applicationInfo; + + final boolean clearingOwnUidData = appInfo != null && appInfo.uid == uid; + + if (!clearingOwnUidData && checkComponentPermission(permission.CLEAR_APP_USER_DATA, + pid, uid, -1, true) != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("PID " + pid + " does not have permission " + + android.Manifest.permission.CLEAR_APP_USER_DATA + " to clear data" + + " of package " + packageName); + } + + final boolean hasInstantMetadata = getPackageManagerInternalLocked() + .hasInstantApplicationMetadata(packageName, resolvedUserId); + final boolean isUninstalledAppWithoutInstantMetadata = + (appInfo == null && !hasInstantMetadata); + isInstantApp = (appInfo != null && appInfo.isInstantApp()) + || hasInstantMetadata; + final boolean canAccessInstantApps = checkComponentPermission( + permission.ACCESS_INSTANT_APPS, pid, uid, -1, true) + == PackageManager.PERMISSION_GRANTED; + + if (isUninstalledAppWithoutInstantMetadata || (isInstantApp + && !canAccessInstantApps)) { Slog.w(TAG, "Invalid packageName: " + packageName); if (observer != null) { try { @@ -5869,45 +5907,45 @@ public class ActivityManagerService extends IActivityManager.Stub } return false; } - if (uid == pkgUid || checkComponentPermission( - android.Manifest.permission.CLEAR_APP_USER_DATA, - pid, uid, -1, true) - == PackageManager.PERMISSION_GRANTED) { - forceStopPackageLocked(packageName, pkgUid, "clear data"); - } else { - throw new SecurityException("PID " + pid + " does not have permission " - + android.Manifest.permission.CLEAR_APP_USER_DATA + " to clear data" - + " of package " + packageName); - } - // Remove all tasks match the cleared application package and user - for (int i = mRecentTasks.size() - 1; i >= 0; i--) { - final TaskRecord tr = mRecentTasks.get(i); - final String taskPackageName = - tr.getBaseIntent().getComponent().getPackageName(); - if (tr.userId != userId) continue; - if (!taskPackageName.equals(packageName)) continue; - mStackSupervisor.removeTaskByIdLocked(tr.taskId, false, REMOVE_FROM_RECENTS); + if (appInfo != null) { + forceStopPackageLocked(packageName, appInfo.uid, "clear data"); + // Remove all tasks match the cleared application package and user + for (int i = mRecentTasks.size() - 1; i >= 0; i--) { + final TaskRecord tr = mRecentTasks.get(i); + final String taskPackageName = + tr.getBaseIntent().getComponent().getPackageName(); + if (tr.userId != resolvedUserId) continue; + if (!taskPackageName.equals(packageName)) continue; + mStackSupervisor.removeTaskByIdLocked(tr.taskId, false, + REMOVE_FROM_RECENTS); + } } } - final int pkgUidF = pkgUid; - final int userIdF = userId; final IPackageDataObserver localObserver = new IPackageDataObserver.Stub() { @Override public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException { - synchronized (ActivityManagerService.this) { - finishForceStopPackageLocked(packageName, pkgUidF); + if (appInfo != null) { + synchronized (ActivityManagerService.this) { + finishForceStopPackageLocked(packageName, appInfo.uid); + } } - final Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED, Uri.fromParts("package", packageName, null)); intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - intent.putExtra(Intent.EXTRA_UID, pkgUidF); - intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(pkgUidF)); - broadcastIntentInPackage("android", SYSTEM_UID, intent, - null, null, 0, null, null, null, null, false, false, userIdF); + intent.putExtra(Intent.EXTRA_UID, (appInfo != null) ? appInfo.uid : -1); + intent.putExtra(Intent.EXTRA_USER_HANDLE, resolvedUserId); + if (isInstantApp) { + intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); + broadcastIntentInPackage("android", SYSTEM_UID, intent, null, null, 0, + null, null, permission.ACCESS_INSTANT_APPS, null, false, false, + resolvedUserId); + } else { + broadcastIntentInPackage("android", SYSTEM_UID, intent, null, null, 0, + null, null, null, null, false, false, resolvedUserId); + } if (observer != null) { observer.onRemoveCompleted(packageName, succeeded); @@ -5917,16 +5955,18 @@ public class ActivityManagerService extends IActivityManager.Stub try { // Clear application user data - pm.clearApplicationUserData(packageName, localObserver, userId); + pm.clearApplicationUserData(packageName, localObserver, resolvedUserId); - synchronized(this) { - // Remove all permissions granted from/to this package - removeUriPermissionsForPackageLocked(packageName, userId, true); - } + if (appInfo != null) { + synchronized (this) { + // Remove all permissions granted from/to this package + removeUriPermissionsForPackageLocked(packageName, resolvedUserId, true); + } - // Reset notification settings. - INotificationManager inm = NotificationManager.getService(); - inm.clearData(packageName, pkgUidF, uid == pkgUidF); + // Reset notification settings. + INotificationManager inm = NotificationManager.getService(); + inm.clearData(packageName, appInfo.uid, uid == appInfo.uid); + } } catch (RemoteException e) { } } finally { @@ -8011,7 +8051,7 @@ public class ActivityManagerService extends IActivityManager.Stub // Activity supports picture-in-picture, now check that we can enter PiP at this // point, if it is if (!r.checkEnterPictureInPictureState("enterPictureInPictureMode", - false /* noThrow */, false /* beforeStopping */)) { + false /* beforeStopping */)) { return false; } @@ -8029,7 +8069,7 @@ public class ActivityManagerService extends IActivityManager.Stub stack.setPictureInPictureActions(actions); MetricsLogger.action(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_ENTERED, - r.supportsPictureInPictureWhilePausing); + r.supportsEnterPipOnTaskSwitch); logPictureInPictureArgs(params); }; @@ -9894,7 +9934,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (!allowed) { // If the caller doesn't have the GET_TASKS permission, then only // allow them to see a small subset of tasks -- their own and home. - if (!tr.isHomeTask() && tr.effectiveUid != callingUid) { + if (!tr.isActivityTypeHome() && tr.effectiveUid != callingUid) { if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, not allowed: " + tr); continue; } @@ -9955,20 +9995,6 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public ActivityManager.TaskThumbnail getTaskThumbnail(int id) { - synchronized (this) { - enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER, - "getTaskThumbnail()"); - final TaskRecord tr = mStackSupervisor.anyTaskForIdLocked( - id, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, INVALID_STACK_ID); - if (tr != null) { - return tr.getTaskThumbnailLocked(); - } - } - return null; - } - - @Override public ActivityManager.TaskDescription getTaskDescription(int id) { synchronized (this) { enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS, @@ -10035,7 +10061,7 @@ public class ActivityManagerService extends IActivityManager.Stub TaskRecord task = new TaskRecord(this, mStackSupervisor.getNextTaskIdForUserLocked(r.userId), - ainfo, intent, description, new TaskThumbnailInfo()); + ainfo, intent, description); int trimIdx = mRecentTasks.trimForTaskLocked(task, false); if (trimIdx >= 0) { @@ -10054,8 +10080,8 @@ public class ActivityManagerService extends IActivityManager.Stub mRecentTasks.add(task); r.getStack().addTask(task, false, "addAppTask"); - task.setLastThumbnailLocked(thumbnail); - task.freeLastThumbnail(); + // TODO: Send the thumbnail to WM to store it. + return task.taskId; } } finally { @@ -10115,7 +10141,7 @@ public class ActivityManagerService extends IActivityManager.Stub // that task to freeform // - otherwise the task is not moved int stackId = task.getStackId(); - if (!StackId.isTaskResizeAllowed(stackId)) { + if (!task.getWindowConfiguration().canResizeTask()) { throw new IllegalArgumentException("resizeTask not allowed on task=" + task); } if (bounds == null && stackId == FREEFORM_WORKSPACE_STACK_ID) { @@ -10372,8 +10398,7 @@ public class ActivityManagerService extends IActivityManager.Stub Slog.d(TAG, "Could not find task for id: "+ taskId); return; } - if (mStackSupervisor.isLockTaskModeViolation(task)) { - mStackSupervisor.showLockTaskToast(); + if (mLockTaskController.isLockTaskModeViolation(task)) { Slog.e(TAG, "moveTaskToFront: Attempt to violate Lock Task Mode"); return; } @@ -10481,17 +10506,6 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public int getActivityStackId(IBinder token) throws RemoteException { - synchronized (this) { - ActivityStack stack = ActivityRecord.getStackLocked(token); - if (stack == null) { - return INVALID_STACK_ID; - } - return stack.mStackId; - } - } - - @Override public void exitFreeformMode(IBinder token) throws RemoteException { synchronized (this) { long ident = Binder.clearCallingIdentity(); @@ -10820,6 +10834,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public void updateLockTaskPackages(int userId, String[] packages) { + // TODO: move this into LockTaskController final int callingUid = Binder.getCallingUid(); if (callingUid != 0 && callingUid != SYSTEM_UID) { enforceCallingPermission(android.Manifest.permission.UPDATE_LOCK_TASK_PACKAGES, @@ -10829,17 +10844,21 @@ public class ActivityManagerService extends IActivityManager.Stub if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Whitelisting " + userId + ":" + Arrays.toString(packages)); mLockTaskPackages.put(userId, packages); - mStackSupervisor.onLockTaskPackagesUpdatedLocked(); + mLockTaskController.onLockTaskPackagesUpdated(); } } - - void startLockTaskModeLocked(TaskRecord task) { + private void startLockTaskModeLocked(@Nullable TaskRecord task, boolean isAppPinning) { if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "startLockTaskModeLocked: " + task); - if (task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) { + if (task == null || task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) { return; } + final ActivityStack stack = mStackSupervisor.getFocusedStack(); + if (stack == null || task != stack.topTask()) { + throw new IllegalArgumentException("Invalid task, not in foreground"); + } + // When a task is locked, dismiss the pinned stack if it exists final PinnedActivityStack pinnedStack = mStackSupervisor.getStack( PINNED_STACK_ID); @@ -10847,63 +10866,26 @@ public class ActivityManagerService extends IActivityManager.Stub mStackSupervisor.removeStackLocked(PINNED_STACK_ID); } - // isSystemInitiated is used to distinguish between locked and pinned mode, as pinned mode + // isAppPinning is used to distinguish between locked and pinned mode, as pinned mode // is initiated by system after the pinning request was shown and locked mode is initiated // by an authorized app directly final int callingUid = Binder.getCallingUid(); - boolean isSystemInitiated = callingUid == SYSTEM_UID; long ident = Binder.clearCallingIdentity(); try { - if (!isSystemInitiated) { - task.mLockTaskUid = callingUid; - if (task.mLockTaskAuth == LOCK_TASK_AUTH_PINNABLE) { - // startLockTask() called by app and task mode is lockTaskModeDefault. - if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Mode default, asking user"); - StatusBarManagerInternal statusBarManager = - LocalServices.getService(StatusBarManagerInternal.class); - if (statusBarManager != null) { - statusBarManager.showScreenPinningRequest(task.taskId); - } - return; - } - - final ActivityStack stack = mStackSupervisor.getFocusedStack(); - if (stack == null || task != stack.topTask()) { - throw new IllegalArgumentException("Invalid task, not in foreground"); - } - } - if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, isSystemInitiated ? "Locking pinned" : - "Locking fully"); - mStackSupervisor.setLockTaskModeLocked(task, isSystemInitiated ? - ActivityManager.LOCK_TASK_MODE_PINNED : - ActivityManager.LOCK_TASK_MODE_LOCKED, - "startLockTask", true); + mLockTaskController.startLockTaskMode(task, isAppPinning, callingUid); } finally { Binder.restoreCallingIdentity(ident); } } @Override - public void startLockTaskModeById(int taskId) { - synchronized (this) { - final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId); - if (task != null) { - startLockTaskModeLocked(task); - } - } - } - - @Override public void startLockTaskModeByToken(IBinder token) { synchronized (this) { final ActivityRecord r = ActivityRecord.forTokenLocked(token); if (r == null) { return; } - final TaskRecord task = r.getTask(); - if (task != null) { - startLockTaskModeLocked(task); - } + startLockTaskModeLocked(r.getTask(), false /* not system initiated */); } } @@ -10914,7 +10896,8 @@ public class ActivityManagerService extends IActivityManager.Stub long ident = Binder.clearCallingIdentity(); try { synchronized (this) { - startLockTaskModeById(taskId); + startLockTaskModeLocked(mStackSupervisor.anyTaskForIdLocked(taskId), + true /* system initiated */); } } finally { Binder.restoreCallingIdentity(ident); @@ -10923,41 +10906,28 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public void stopLockTaskMode() { - final TaskRecord lockTask = mStackSupervisor.getLockedTaskLocked(); - if (lockTask == null) { - // Our work here is done. - return; - } + stopLockTaskModeInternal(false /* not system initiated */); + } + /** + * This API should be called by SystemUI only when user perform certain action to dismiss + * lock task mode. We should only dismiss pinned lock task mode in this case. + */ + @Override + public void stopSystemLockTaskMode() throws RemoteException { + enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "stopSystemLockTaskMode"); + stopLockTaskModeInternal(true /* system initiated */); + } + + private void stopLockTaskModeInternal(boolean isSystemRequest) { final int callingUid = Binder.getCallingUid(); - final int lockTaskUid = lockTask.mLockTaskUid; - final int lockTaskModeState = mStackSupervisor.getLockTaskModeState(); - if (lockTaskModeState == ActivityManager.LOCK_TASK_MODE_NONE) { - // Done. - return; - } else { - // Ensure the same caller for startLockTaskMode and stopLockTaskMode. - // It is possible lockTaskMode was started by the system process because - // android:lockTaskMode is set to a locking value in the application manifest - // instead of the app calling startLockTaskMode. In this case - // {@link TaskRecord.mLockTaskUid} will be 0, so we compare the callingUid to the - // {@link TaskRecord.effectiveUid} instead. Also caller with - // {@link MANAGE_ACTIVITY_STACKS} can stop any lock task. - if (checkCallingPermission(MANAGE_ACTIVITY_STACKS) != PERMISSION_GRANTED - && callingUid != lockTaskUid - && (lockTaskUid != 0 || callingUid != lockTask.effectiveUid)) { - throw new SecurityException("Invalid uid, expected " + lockTaskUid - + " callingUid=" + callingUid + " effectiveUid=" + lockTask.effectiveUid); - } - } long ident = Binder.clearCallingIdentity(); try { - Log.d(TAG, "stopLockTaskMode"); - // Stop lock task synchronized (this) { - mStackSupervisor.setLockTaskModeLocked(null, ActivityManager.LOCK_TASK_MODE_NONE, - "stopLockTask", true); + mLockTaskController.stopLockTaskMode(isSystemRequest, callingUid); } + // Launch in-call UI if a call is ongoing. This is necessary to allow stopping the lock + // task and jumping straight into a call in the case of emergency call back. TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); if (tm != null) { tm.showInCallScreen(false); @@ -10967,28 +10937,15 @@ public class ActivityManagerService extends IActivityManager.Stub } } - /** - * This API should be called by SystemUI only when user perform certain action to dismiss - * lock task mode. We should only dismiss pinned lock task mode in this case. - */ - @Override - public void stopSystemLockTaskMode() throws RemoteException { - if (mStackSupervisor.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_PINNED) { - stopLockTaskMode(); - } else { - mStackSupervisor.showLockTaskToast(); - } - } - @Override public boolean isInLockTaskMode() { - return getLockTaskModeState() != ActivityManager.LOCK_TASK_MODE_NONE; + return getLockTaskModeState() != LOCK_TASK_MODE_NONE; } @Override public int getLockTaskModeState() { synchronized (this) { - return mStackSupervisor.getLockTaskModeState(); + return mLockTaskController.getLockTaskModeState(); } } @@ -10999,7 +10956,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (r == null) { return; } - mStackSupervisor.showLockTaskEscapeMessageLocked(r.getTask()); + mLockTaskController.showLockTaskToast(); } } @@ -12395,7 +12352,19 @@ public class ActivityManagerService extends IActivityManager.Stub void onWakefulnessChanged(int wakefulness) { synchronized(this) { mWakefulness = wakefulness; - updateSleepIfNeededLocked(); + + // Also update state in a special way for running foreground services UI. + switch (mWakefulness) { + case PowerManagerInternal.WAKEFULNESS_ASLEEP: + case PowerManagerInternal.WAKEFULNESS_DREAMING: + case PowerManagerInternal.WAKEFULNESS_DOZING: + mServices.updateScreenStateLocked(false /* screenOn */); + break; + case PowerManagerInternal.WAKEFULNESS_AWAKE: + default: + mServices.updateScreenStateLocked(true /* screenOn */); + break; + } } } @@ -12415,14 +12384,24 @@ public class ActivityManagerService extends IActivityManager.Stub } void updateSleepIfNeededLocked() { - final boolean shouldSleep = shouldSleepLocked(); - if (mSleeping && !shouldSleep) { - mSleeping = false; - startTimeTrackingFocusedActivityLocked(); - mTopProcessState = ActivityManager.PROCESS_STATE_TOP; - mStackSupervisor.comeOutOfSleepIfNeededLocked(); - sendNotifyVrManagerOfSleepState(false); - updateOomAdjLocked(); + final boolean shouldSleep = !mStackSupervisor.hasAwakeDisplay(); + final boolean wasSleeping = mSleeping; + + if (!shouldSleep) { + // If wasSleeping is true, we need to wake up activity manager state from when + // we started sleeping. In either case, we need to apply the sleep tokens, which + // will wake up stacks or put them to sleep as appropriate. + if (wasSleeping) { + mSleeping = false; + startTimeTrackingFocusedActivityLocked(); + mTopProcessState = ActivityManager.PROCESS_STATE_TOP; + mStackSupervisor.comeOutOfSleepIfNeededLocked(); + } + mStackSupervisor.applySleepTokensLocked(true /* applyToStacks */); + if (wasSleeping) { + sendNotifyVrManagerOfSleepState(false); + updateOomAdjLocked(); + } } else if (!mSleeping && shouldSleep) { mSleeping = true; if (mCurAppTimeTracker != null) { @@ -12433,40 +12412,6 @@ public class ActivityManagerService extends IActivityManager.Stub sendNotifyVrManagerOfSleepState(true); updateOomAdjLocked(); } - - // Also update state in a special way for running foreground services UI. - switch (mWakefulness) { - case PowerManagerInternal.WAKEFULNESS_ASLEEP: - case PowerManagerInternal.WAKEFULNESS_DREAMING: - case PowerManagerInternal.WAKEFULNESS_DOZING: - mServices.updateScreenStateLocked(false); - break; - case PowerManagerInternal.WAKEFULNESS_AWAKE: - default: - mServices.updateScreenStateLocked(true); - break; - } - } - - private boolean shouldSleepLocked() { - // Resume applications while running a voice interactor. - if (mRunningVoice != null) { - return false; - } - - // TODO: Transform the lock screen state into a sleep token instead. - switch (mWakefulness) { - case PowerManagerInternal.WAKEFULNESS_AWAKE: - case PowerManagerInternal.WAKEFULNESS_DREAMING: - // Pause applications whenever the lock screen is shown or any sleep - // tokens have been acquired. - return mKeyguardController.isKeyguardShowing() || !mSleepTokens.isEmpty(); - case PowerManagerInternal.WAKEFULNESS_DOZING: - case PowerManagerInternal.WAKEFULNESS_ASLEEP: - default: - // If we're asleep then pause applications unconditionally. - return true; - } } /** Pokes the task persister. */ @@ -12507,6 +12452,7 @@ public class ActivityManagerService extends IActivityManager.Stub synchronized(this) { mShuttingDown = true; + mStackSupervisor.prepareForShutdownLocked(); updateEventDispatchingLocked(); timedout = mStackSupervisor.shutdownLocked(timeout); } @@ -12999,7 +12945,7 @@ public class ActivityManagerService extends IActivityManager.Stub int userId; synchronized (this) { final ActivityStack focusedStack = getFocusedStack(); - if (focusedStack == null || focusedStack.isAssistantStack()) { + if (focusedStack == null || focusedStack.isActivityTypeAssistant()) { return false; } @@ -13088,6 +13034,10 @@ public class ActivityManagerService extends IActivityManager.Stub + " couldn't be found"); return null; } + if (activity.app == null || activity.app.thread == null) { + Slog.w(TAG, "enqueueAssistContext failed: no process for " + activity); + return null; + } } PendingAssistExtras pae; @@ -13100,7 +13050,7 @@ public class ActivityManagerService extends IActivityManager.Stub pae = new PendingAssistExtras(activity, extras, intent, hint, receiver, receiverExtras, userHandle); - pae.isHome = activity.isHomeActivity(); + pae.isHome = activity.isActivityTypeHome(); // Increment the sessionId if necessary if (newSessionId) { @@ -13327,7 +13277,7 @@ public class ActivityManagerService extends IActivityManager.Stub synchronized (this) { final ActivityRecord r = ActivityRecord.isInStackLocked(token); if (r != null) { - final ActivityOptions activityOptions = r.pendingOptions; + final ActivityOptions activityOptions = r.takeOptionsLocked(); return activityOptions == null ? null : activityOptions.toBundle(); } return null; @@ -14054,7 +14004,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } - public void systemReady(final Runnable goingCallback, BootTimingsTraceLog traceLog) { + public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) { traceLog.traceBegin("PhaseActivityManagerReady"); synchronized(this) { if (mSystemReady) { @@ -14921,6 +14871,14 @@ public class ActivityManagerService extends IActivityManager.Stub this, in, out, err, args, callback, resultReceiver); } + SleepToken acquireSleepToken(String tag, int displayId) { + synchronized (this) { + final SleepToken token = mStackSupervisor.createSleepTokenLocked(tag, displayId); + updateSleepIfNeededLocked(); + return token; + } + } + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return; @@ -15817,7 +15775,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (dumpPackage == null) { pw.println(" mWakefulness=" + PowerManagerInternal.wakefulnessToString(mWakefulness)); - pw.println(" mSleepTokens=" + mSleepTokens); + pw.println(" mSleepTokens=" + mStackSupervisor.mSleepTokens); pw.println(" mSleeping=" + mSleeping); pw.println(" mShuttingDown=" + mShuttingDown + " mTestPssMode=" + mTestPssMode); if (mRunningVoice != null) { @@ -21906,7 +21864,7 @@ public class ActivityManagerService extends IActivityManager.Stub int changes = 0; if (app.curAdj != app.setAdj) { - ProcessList.setOomAdj(app.pid, app.info.uid, app.curAdj); + ProcessList.setOomAdj(app.pid, app.uid, app.curAdj); if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ, "Set " + app.pid + " " + app.processName + " adj " + app.curAdj + ": " + app.adjType); @@ -23778,15 +23736,9 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public SleepToken acquireSleepToken(String tag) { + public SleepToken acquireSleepToken(String tag, int displayId) { Preconditions.checkNotNull(tag); - - synchronized (ActivityManagerService.this) { - SleepTokenImpl token = new SleepTokenImpl(tag); - mSleepTokens.add(token); - updateSleepIfNeededLocked(); - return token; - } + return ActivityManagerService.this.acquireSleepToken(tag, displayId); } @Override @@ -24110,6 +24062,21 @@ public class ActivityManagerService extends IActivityManager.Stub mLastANRState = null; } } + + @Override + public void setFocusedActivity(IBinder token) { + synchronized (ActivityManagerService.this) { + final ActivityRecord r = ActivityRecord.forTokenLocked(token); + if (r == null) { + throw new IllegalArgumentException( + "setFocusedActivity: No activity record matching token=" + token); + } + if (mStackSupervisor.moveFocusableActivityStackToFrontLocked( + r, "setFocusedActivity")) { + mStackSupervisor.resumeFocusedStackTopActivityLocked(); + } + } + } } /** @@ -24223,30 +24190,6 @@ public class ActivityManagerService extends IActivityManager.Stub } } - private final class SleepTokenImpl extends SleepToken { - private final String mTag; - private final long mAcquireTime; - - public SleepTokenImpl(String tag) { - mTag = tag; - mAcquireTime = SystemClock.uptimeMillis(); - } - - @Override - public void release() { - synchronized (ActivityManagerService.this) { - if (mSleepTokens.remove(this)) { - updateSleepIfNeededLocked(); - } - } - } - - @Override - public String toString() { - return "{\"" + mTag + "\", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}"; - } - } - /** * An implementation of IAppTask, that allows an app to manage its own tasks via * {@link android.app.ActivityManager.AppTask}. We keep track of the callingUid to ensure that diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 45357cb67fd1..403e01d5ae44 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -2224,7 +2224,7 @@ final class ActivityManagerShellCommand extends ShellCommand { int runTaskLock(PrintWriter pw) throws RemoteException { String taskIdStr = getNextArgRequired(); if (taskIdStr.equals("stop")) { - mInterface.stopLockTaskMode(); + mInterface.stopSystemLockTaskMode(); } else { int taskId = Integer.parseInt(taskIdStr); mInterface.startSystemLockTaskMode(taskId); diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java index 98815d7e18c7..aae98a6e5013 100644 --- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java @@ -4,23 +4,29 @@ import static android.app.ActivityManager.START_SUCCESS; import static android.app.ActivityManager.START_TASK_TO_FRONT; import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID; import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; -import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; -import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; import static android.app.ActivityManager.StackId.INVALID_STACK_ID; -import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT; +import static android.app.WindowConfiguration.WINDOWING_MODE_DOCKED; +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_BIND_APPLICATION_DELAY_MS; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_CALLING_PACKAGE_NAME; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DELAY_MS; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DEVICE_UPTIME_SECONDS; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_IS_EPHEMERAL; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_PROCESS_RUNNING; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_REPORTED_DRAWN; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_REPORTED_DRAWN_MS; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_STARTING_WINDOW_DELAY_MS; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CLASS_NAME; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_LAUNCH_TOKEN; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_COLD_LAUNCH; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_HOT_LAUNCH; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_WARM_LAUNCH; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -67,12 +73,14 @@ class ActivityMetricsLogger { private final MetricsLogger mMetricsLogger = new MetricsLogger(); private long mCurrentTransitionStartTime = INVALID_START_TIME; + private long mLastTransitionStartTime = INVALID_START_TIME; private int mCurrentTransitionDeviceUptime; private int mCurrentTransitionDelayMs; private boolean mLoggedTransitionStarting; private final SparseArray<StackTransitionInfo> mStackTransitionInfo = new SparseArray<>(); + private final SparseArray<StackTransitionInfo> mLastStackTransitionInfo = new SparseArray<>(); private final class StackTransitionInfo { private ActivityRecord launchedActivity; @@ -110,17 +118,19 @@ class ActivityMetricsLogger { } mWindowState = WINDOW_STATE_INVALID; stack = mSupervisor.getFocusedStack(); - if (stack.mStackId == PINNED_STACK_ID) { + int windowingMode = stack.getWindowingMode(); + if (windowingMode == WINDOWING_MODE_PINNED) { stack = mSupervisor.findStackBehind(stack); + windowingMode = stack.getWindowingMode(); } if (StackId.isHomeOrRecentsStack(stack.mStackId) - || stack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) { + || windowingMode == WINDOWING_MODE_FULLSCREEN) { mWindowState = WINDOW_STATE_STANDARD; - } else if (stack.mStackId == DOCKED_STACK_ID) { + } else if (windowingMode == WINDOWING_MODE_DOCKED) { Slog.wtf(TAG, "Docked stack shouldn't be the focused stack, because it reported not" + " being visible."); mWindowState = WINDOW_STATE_INVALID; - } else if (stack.mStackId == FREEFORM_WORKSPACE_STACK_ID) { + } else if (windowingMode == WINDOWING_MODE_FREEFORM) { mWindowState = WINDOW_STATE_FREEFORM; } else if (stack.mStackId == ASSISTANT_STACK_ID) { mWindowState = WINDOW_STATE_ASSISTANT; @@ -136,6 +146,7 @@ class ActivityMetricsLogger { void notifyActivityLaunching() { if (!isAnyTransitionActive()) { mCurrentTransitionStartTime = SystemClock.uptimeMillis(); + mLastTransitionStartTime = mCurrentTransitionStartTime; } } @@ -223,7 +234,8 @@ class ActivityMetricsLogger { newInfo.launchedActivity = launchedActivity; newInfo.currentTransitionProcessRunning = processRunning; newInfo.startResult = resultCode; - mStackTransitionInfo.append(stackId, newInfo); + mStackTransitionInfo.put(stackId, newInfo); + mLastStackTransitionInfo.put(stackId, newInfo); mCurrentTransitionDeviceUptime = (int) (SystemClock.uptimeMillis() / 1000); } @@ -361,7 +373,7 @@ class ActivityMetricsLogger { builder.setType(type); builder.addTaggedData(FIELD_CLASS_NAME, info.launchedActivity.info.name); final boolean isInstantApp = info.launchedActivity.info.applicationInfo.isInstantApp(); - if (isInstantApp && info.launchedActivity.launchedFromPackage != null) { + if (info.launchedActivity.launchedFromPackage != null) { builder.addTaggedData(APP_TRANSITION_CALLING_PACKAGE_NAME, info.launchedActivity.launchedFromPackage); } @@ -388,6 +400,24 @@ class ActivityMetricsLogger { } } + void logAppTransitionReportedDrawn(ActivityRecord r, boolean restoredFromBundle) { + final StackTransitionInfo info = mLastStackTransitionInfo.get(r.getStackId()); + if (info == null) { + return; + } + final LogMaker builder = new LogMaker(APP_TRANSITION_REPORTED_DRAWN); + builder.setPackageName(r.packageName); + builder.addTaggedData(FIELD_CLASS_NAME, r.info.name); + builder.addTaggedData(APP_TRANSITION_REPORTED_DRAWN_MS, + SystemClock.uptimeMillis() - mLastTransitionStartTime); + builder.setType(restoredFromBundle + ? TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE + : TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE); + builder.addTaggedData(APP_TRANSITION_PROCESS_RUNNING, + info.currentTransitionProcessRunning ? 1 : 0); + mMetricsLogger.write(builder); + } + private int getTransitionType(StackTransitionInfo info) { if (info.currentTransitionProcessRunning) { if (info.startResult == START_SUCCESS) { diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 4a9b98d7be00..651d3a6a044e 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -16,13 +16,10 @@ package com.android.server.am; -import static android.app.ActivityManager.ENABLE_TASK_SNAPSHOTS; import static android.app.ActivityManager.LOCK_TASK_MODE_NONE; -import static android.app.ActivityManager.StackId; import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID; import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; -import static android.app.ActivityManager.StackId.HOME_STACK_ID; import static android.app.ActivityManager.StackId.INVALID_STACK_ID; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static android.app.ActivityManager.TaskDescription.ATTR_TASKDESCRIPTION_PREFIX; @@ -36,6 +33,12 @@ import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN; import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP; import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import static android.app.WindowConfiguration.activityTypeToString; import static android.content.Intent.ACTION_MAIN; import static android.content.Intent.CATEGORY_HOME; import static android.content.Intent.CATEGORY_LAUNCHER; @@ -46,12 +49,14 @@ import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT; import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE; import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE; import static android.content.pm.ActivityInfo.CONFIG_UI_MODE; +import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION; import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE; -import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED; import static android.content.pm.ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS; import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE; import static android.content.pm.ActivityInfo.FLAG_MULTIPROCESS; +import static android.content.pm.ActivityInfo.FLAG_NO_HISTORY; import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS; +import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED; import static android.content.pm.ActivityInfo.FLAG_STATE_NOT_NEEDED; import static android.content.pm.ActivityInfo.FLAG_TURN_SCREEN_ON; import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE; @@ -64,7 +69,6 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE; import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE; import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION; import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; -import static android.content.pm.ActivityInfo.FLAG_NO_HISTORY; import static android.content.pm.ActivityInfo.isFixedOrientationLandscape; import static android.content.pm.ActivityInfo.isFixedOrientationPortrait; import static android.content.res.Configuration.EMPTY; @@ -74,16 +78,14 @@ import static android.content.res.Configuration.UI_MODE_TYPE_MASK; import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET; import static android.os.Build.VERSION_CODES.HONEYCOMB; import static android.os.Build.VERSION_CODES.O; +import static android.os.Build.VERSION_CODES.O_MR1; import static android.os.Process.SYSTEM_UID; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import static android.view.WindowManagerPolicy.NAV_BAR_LEFT; - import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SCREENSHOTS; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_THUMBNAILS; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBILITY; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SAVED_STATE; @@ -94,7 +96,6 @@ import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_THUMBNAIL import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; -import static com.android.server.am.ActivityManagerService.TAKE_FULLSCREEN_SCREENSHOTS; import static com.android.server.am.ActivityStack.ActivityState.DESTROYED; import static com.android.server.am.ActivityStack.ActivityState.DESTROYING; import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING; @@ -145,6 +146,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; +import android.os.storage.StorageManager; import android.service.voice.IVoiceInteractionSession; import android.util.EventLog; import android.util.Log; @@ -165,6 +167,7 @@ import com.android.server.AttributeCache.Entry; import com.android.server.am.ActivityStack.ActivityState; import com.android.server.wm.AppWindowContainerController; import com.android.server.wm.AppWindowContainerListener; +import com.android.server.wm.ConfigurationContainer; import com.android.server.wm.TaskWindowContainerController; import org.xmlpull.v1.XmlPullParser; @@ -229,12 +232,6 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo private final boolean componentSpecified; // did caller specify an explicit component? final boolean rootVoiceInteraction; // was this the root activity of a voice interaction? - static final int APPLICATION_ACTIVITY_TYPE = 0; - static final int HOME_ACTIVITY_TYPE = 1; - static final int RECENTS_ACTIVITY_TYPE = 2; - static final int ASSISTANT_ACTIVITY_TYPE = 3; - int mActivityType; - private CharSequence nonLocalizedLabel; // the label information from the package mgr. private int labelRes; // the label information from the package mgr. private int icon; // resource identifier of activity's icon. @@ -296,9 +293,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo boolean frozenBeforeDestroy;// has been frozen but not yet destroyed. boolean immersive; // immersive mode (don't interrupt if possible) boolean forceNewConfig; // force re-create with new config next time - boolean supportsPictureInPictureWhilePausing; // This flag is set by the system to indicate - // that the activity can enter picture in picture while pausing (ie. only when another - // task is brought to front or started) + boolean supportsEnterPipOnTaskSwitch; // This flag is set by the system to indicate that the + // activity can enter picture in picture while pausing (only when switching to another task) PictureInPictureParams pictureInPictureArgs = new PictureInPictureParams.Builder().build(); // The PiP params used when deferring the entering of picture-in-picture. int launchCount; // count of launches since last state @@ -316,8 +312,6 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo int mStartingWindowState = STARTING_WINDOW_NOT_SHOWN; boolean mTaskOverlay = false; // Task is always on-top of other activities in the task. - boolean mUpdateTaskThumbnailWhenHidden; - TaskDescription taskDescription; // the recents information for this activity boolean mLaunchTaskBehind; // this activity is actively being launched with // ActivityOptions.setLaunchTaskBehind, will be cleared once launch is completed. @@ -394,7 +388,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded); pw.print(" componentSpecified="); pw.print(componentSpecified); - pw.print(" mActivityType="); pw.println(mActivityType); + pw.print(" mActivityType="); pw.println( + activityTypeToString(getActivityType())); if (rootVoiceInteraction) { pw.print(prefix); pw.print("rootVoiceInteraction="); pw.println(rootVoiceInteraction); } @@ -427,11 +422,11 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo pw.print("\""); pw.print(" primaryColor="); pw.println(Integer.toHexString(taskDescription.getPrimaryColor())); - pw.print(prefix); pw.print(" backgroundColor="); + pw.print(prefix + " backgroundColor="); pw.println(Integer.toHexString(taskDescription.getBackgroundColor())); - pw.print(prefix); pw.print(" statusBarColor="); + pw.print(prefix + " statusBarColor="); pw.println(Integer.toHexString(taskDescription.getStatusBarColor())); - pw.print(prefix); pw.print(" navigationBarColor="); + pw.print(prefix + " navigationBarColor="); pw.println(Integer.toHexString(taskDescription.getNavigationBarColor())); } if (iconFilename == null && taskDescription.getIcon() != null) { @@ -501,7 +496,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy); pw.print(" forceNewConfig="); pw.println(forceNewConfig); pw.print(prefix); pw.print("mActivityType="); - pw.println(activityTypeToString(mActivityType)); + pw.println(activityTypeToString(getActivityType())); if (requestedVrComponent != null) { pw.print(prefix); pw.print("requestedVrComponent="); @@ -543,8 +538,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo + " mLastReportedPictureInPictureMode=" + mLastReportedPictureInPictureMode); if (info.supportsPictureInPicture()) { pw.println(prefix + "supportsPictureInPicture=" + info.supportsPictureInPicture()); - pw.println(prefix + "supportsPictureInPictureWhilePausing: " - + supportsPictureInPictureWhilePausing); + pw.println(prefix + "supportsEnterPipOnTaskSwitch: " + + supportsEnterPipOnTaskSwitch); } if (info.maxAspectRatio != 0) { pw.println(prefix + "maxAspectRatio=" + info.maxAspectRatio); @@ -658,14 +653,14 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } } - void updatePictureInPictureMode(Rect targetStackBounds) { + void updatePictureInPictureMode(Rect targetStackBounds, boolean forceUpdate) { if (task == null || task.getStack() == null || app == null || app.thread == null) { return; } final boolean inPictureInPictureMode = (task.getStackId() == PINNED_STACK_ID) && (targetStackBounds != null); - if (inPictureInPictureMode != mLastReportedPictureInPictureMode) { + if (inPictureInPictureMode != mLastReportedPictureInPictureMode || forceUpdate) { // Picture-in-picture mode changes also trigger a multi-window mode change as well, so // update that here in order mLastReportedPictureInPictureMode = inPictureInPictureMode; @@ -680,8 +675,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo private void schedulePictureInPictureModeChanged(Configuration overrideConfig) { try { app.thread.schedulePictureInPictureModeChanged(appToken, - mLastReportedPictureInPictureMode, - overrideConfig); + mLastReportedPictureInPictureMode, overrideConfig); } catch (Exception e) { // If process died, no one cares. } @@ -748,9 +742,11 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo static class Token extends IApplicationToken.Stub { private final WeakReference<ActivityRecord> weakActivity; + private final String name; - Token(ActivityRecord activity) { + Token(ActivityRecord activity, Intent intent) { weakActivity = new WeakReference<>(activity); + name = intent.getComponent().flattenToShortString(); } private static ActivityRecord tokenToActivityRecordLocked(Token token) { @@ -774,6 +770,11 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo sb.append('}'); return sb.toString(); } + + @Override + public String getName() { + return name; + } } static ActivityRecord forTokenLocked(IBinder token) { @@ -797,7 +798,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo ActivityStackSupervisor supervisor, ActivityOptions options, ActivityRecord sourceRecord) { service = _service; - appToken = new Token(this); + appToken = new Token(this, _intent); info = aInfo; launchedFromPid = _launchedFromPid; launchedFromUid = _launchedFromUid; @@ -937,7 +938,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo task.voiceSession != null, mLaunchTaskBehind, isAlwaysFocusable(), appInfo.targetSdkVersion, mRotationAnimationHint, ActivityManagerService.getInputDispatchingTimeoutLocked(this) * 1000000L, - getOverrideConfiguration(), mBounds); + new Configuration(getOverrideConfiguration()), mBounds); task.addActivityToTop(this); @@ -946,8 +947,6 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo // the user leaves that mode. mLastReportedMultiWindowMode = !task.mFullscreen; mLastReportedPictureInPictureMode = (task.getStackId() == PINNED_STACK_ID); - - onOverrideConfigurationSent(); } void removeWindowContainer() { @@ -1029,10 +1028,11 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo private void setActivityType(boolean componentSpecified, int launchedFromUid, Intent intent, ActivityOptions options, ActivityRecord sourceRecord) { + int activityType = ACTIVITY_TYPE_UNDEFINED; if ((!componentSpecified || canLaunchHomeActivity(launchedFromUid, sourceRecord)) && isHomeIntent(intent) && !isResolverActivity()) { // This sure looks like a home activity! - mActivityType = HOME_ACTIVITY_TYPE; + activityType = ACTIVITY_TYPE_HOME; if (info.resizeMode == RESIZE_MODE_FORCE_RESIZEABLE || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) { @@ -1040,13 +1040,12 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo info.resizeMode = RESIZE_MODE_UNRESIZEABLE; } } else if (realActivity.getClassName().contains(RECENTS_PACKAGE_NAME)) { - mActivityType = RECENTS_ACTIVITY_TYPE; + activityType = ACTIVITY_TYPE_RECENTS; } else if (options != null && options.getLaunchStackId() == ASSISTANT_STACK_ID && canLaunchAssistActivity(launchedFromPackage)) { - mActivityType = ASSISTANT_ACTIVITY_TYPE; - } else { - mActivityType = APPLICATION_ACTIVITY_TYPE; + activityType = ACTIVITY_TYPE_ASSISTANT; } + setActivityType(activityType); } void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) { @@ -1097,31 +1096,14 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo return stack != null && stack.isInStackLocked(this) != null; } - boolean isHomeActivity() { - return mActivityType == HOME_ACTIVITY_TYPE; - } - - boolean isRecentsActivity() { - return mActivityType == RECENTS_ACTIVITY_TYPE; - } - - boolean isAssistantActivity() { - return mActivityType == ASSISTANT_ACTIVITY_TYPE; - } - - boolean isApplicationActivity() { - return mActivityType == APPLICATION_ACTIVITY_TYPE; - } - boolean isPersistable() { return (info.persistableMode == PERSIST_ROOT_ONLY || info.persistableMode == PERSIST_ACROSS_REBOOTS) && - (intent == null || - (intent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0); + (intent == null || (intent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0); } boolean isFocusable() { - return StackId.canReceiveKeys(task.getStackId()) || isAlwaysFocusable(); + return getWindowConfiguration().canReceiveKeys() || isAlwaysFocusable(); } boolean isResizeable() { @@ -1140,7 +1122,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo * @return whether this activity supports PiP multi-window and can be put in the pinned stack. */ boolean supportsPictureInPicture() { - return service.mSupportsPictureInPicture && !isHomeActivity() + return service.mSupportsPictureInPicture && isActivityTypeStandard() && info.supportsPictureInPicture(); } @@ -1166,7 +1148,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo * @return whether this activity supports non-PiP multi-window. */ private boolean supportsResizeableMultiWindow() { - return service.mSupportsMultiWindow && !isHomeActivity() + return service.mSupportsMultiWindow && !isActivityTypeHome() && (ActivityInfo.isResizeableMode(info.resizeMode) || service.mForceResizableActivities); } @@ -1186,10 +1168,9 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo * @param beforeStopping Whether this check is for an auto-enter-pip operation, that is to say * the activity has requested to enter PiP when it would otherwise be stopped. * - * @return whether this activity is currently allowed to enter PIP, throwing an exception if - * the activity is not currently visible and {@param noThrow} is not set. + * @return whether this activity is currently allowed to enter PIP. */ - boolean checkEnterPictureInPictureState(String caller, boolean noThrow, boolean beforeStopping) { + boolean checkEnterPictureInPictureState(String caller, boolean beforeStopping) { if (!supportsPictureInPicture()) { return false; } @@ -1205,7 +1186,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } boolean isKeyguardLocked = service.isKeyguardLocked(); - boolean isCurrentAppLocked = mStackSupervisor.getLockTaskModeState() != LOCK_TASK_MODE_NONE; + boolean isCurrentAppLocked = service.getLockTaskModeState() != LOCK_TASK_MODE_NONE; boolean hasPinnedStack = mStackSupervisor.getStack(PINNED_STACK_ID) != null; // Don't return early if !isNotLocked, since we want to throw an exception if the activity // is in an incorrect state @@ -1221,29 +1202,23 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo // When visible, allow entering PiP if the app is not locked. If it is over the // keyguard, then we will prompt to unlock in the caller before entering PiP. return !isCurrentAppLocked && - (supportsPictureInPictureWhilePausing || !beforeStopping); + (supportsEnterPipOnTaskSwitch || !beforeStopping); case PAUSING: case PAUSED: // When pausing, then only allow enter PiP as in the resume state, and in addition, // require that there is not an existing PiP activity and that the current system // state supports entering PiP return isNotLockedOrOnKeyguard && !hasPinnedStack - && supportsPictureInPictureWhilePausing; + && supportsEnterPipOnTaskSwitch; case STOPPING: // When stopping in a valid state, then only allow enter PiP as in the pause state. // Otherwise, fall through to throw an exception if the caller is trying to enter // PiP in an invalid stopping state. - if (supportsPictureInPictureWhilePausing) { + if (supportsEnterPipOnTaskSwitch) { return isNotLockedOrOnKeyguard && !hasPinnedStack; } default: - if (noThrow) { - return false; - } else { - throw new IllegalStateException(caller - + ": Current activity is not visible (state=" + state.name() + ") " - + "r=" + this); - } + return false; } } @@ -1340,7 +1315,9 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo intent, getUriPermissionsLocked(), userId); final ReferrerIntent rintent = new ReferrerIntent(intent, referrer); boolean unsent = true; - final boolean isTopActivityWhileSleeping = service.isSleepingLocked() && isTopRunningActivity(); + final ActivityStack stack = getStack(); + final boolean isTopActivityWhileSleeping = isTopRunningActivity() + && (stack != null ? stack.shouldSleepActivities() : service.isSleepingLocked()); // We want to immediately deliver the intent to the activity if: // - It is currently resumed or paused. i.e. it is currently visible to the user and we want @@ -1498,72 +1475,10 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } } - void updateThumbnailLocked(Bitmap newThumbnail, CharSequence description) { - if (newThumbnail != null) { - if (DEBUG_THUMBNAILS) Slog.i(TAG_THUMBNAILS, - "Setting thumbnail of " + this + " to " + newThumbnail); - boolean thumbnailUpdated = task.setLastThumbnailLocked(newThumbnail); - if (thumbnailUpdated && isPersistable()) { - service.notifyTaskPersisterLocked(task, false); - } - } + private void updateTaskDescription(CharSequence description) { task.lastDescription = description; } - final Bitmap screenshotActivityLocked() { - if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "screenshotActivityLocked: " + this); - - if (ENABLE_TASK_SNAPSHOTS) { - // No need to screenshot if snapshots are enabled. - if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, - "\tSnapshots are enabled, abort taking screenshot"); - return null; - } - - if (noDisplay) { - if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "\tNo display"); - return null; - } - - final ActivityStack stack = getStack(); - if (stack.isHomeOrRecentsStack()) { - // This is an optimization -- since we never show Home or Recents within Recents itself, - // we can just go ahead and skip taking the screenshot if this is the home stack. - if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, stack.getStackId() == HOME_STACK_ID ? - "\tHome stack" : "\tRecents stack"); - return null; - } - - int w = service.mThumbnailWidth; - int h = service.mThumbnailHeight; - - if (w <= 0) { - Slog.e(TAG, "\tInvalid thumbnail dimensions: " + w + "x" + h); - return null; - } - - if (stack.mStackId == DOCKED_STACK_ID && mStackSupervisor.mIsDockMinimized) { - // When the docked stack is minimized its app windows are cropped significantly so any - // screenshot taken will not display the apps contain. So, we avoid taking a screenshot - // in that case. - if (DEBUG_SCREENSHOTS) Slog.e(TAG, "\tIn minimized docked stack"); - return null; - } - - float scale = 0; - if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "\tTaking screenshot"); - - // When this flag is set, we currently take the fullscreen screenshot of the activity but - // scaled to half the size. This gives us a "good-enough" fullscreen thumbnail to use within - // SystemUI while keeping memory usage low. - if (TAKE_FULLSCREEN_SCREENSHOTS) { - w = h = -1; - scale = service.mFullscreenThumbnailScale; - } - - return mWindowContainerController.screenshotApplications(getDisplayId(), w, h, scale); - } - void setDeferHidingClient(boolean deferHidingClient) { if (mDeferHidingClient == deferHidingClient) { return; @@ -1585,10 +1500,6 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo void setVisible(boolean newVisible) { visible = newVisible; mDeferHidingClient = !visible && mDeferHidingClient; - if (!visible && mUpdateTaskThumbnailWhenHidden) { - updateThumbnailLocked(screenshotActivityLocked(), null /* description */); - mUpdateTaskThumbnailWhenHidden = false; - } setVisibility(visible); mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true; } @@ -1598,7 +1509,12 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } void notifyUnknownVisibilityLaunched() { - mWindowContainerController.notifyUnknownVisibilityLaunched(); + + // No display activities never add a window, so there is no point in waiting them for + // relayout. + if (!noDisplay) { + mWindowContainerController.notifyUnknownVisibilityLaunched(); + } } /** @@ -1614,7 +1530,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo boolean isVisible = !behindFullscreenActivity || mLaunchTaskBehind; - if (service.mSupportsLeanbackOnly && isVisible && isRecentsActivity()) { + if (service.mSupportsLeanbackOnly && isVisible && isActivityTypeRecents()) { // On devices that support leanback only (Android TV), Recents activity can only be // visible if the home stack is the focused stack or we are in split-screen mode. isVisible = mStackSupervisor.getStack(DOCKED_STACK_ID) != null @@ -1682,7 +1598,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo */ void completeResumeLocked() { final boolean wasVisible = visible; - visible = true; + setVisible(true); if (!wasVisible) { // Visibility has changed, so take a note of it so we call the TaskStackChangedListener mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true; @@ -1692,7 +1608,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo newIntents = null; stopped = false; - if (isHomeActivity()) { + if (isActivityTypeHome()) { ProcessRecord app = task.mActivities.get(0).app; if (app != null && app != service.mHomeProcess) { service.mHomeProcess = app; @@ -1730,7 +1646,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo // If the screen is going to turn on because the caller explicitly requested it and // the keyguard is not showing don't attempt to sleep. Otherwise the Activity will // pause and then resume again later, which will result in a double life-cycle event. - mStackSupervisor.checkReadyForSleepLocked(); + stack.checkReadyForSleep(); } } @@ -1754,7 +1670,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo icicle = newIcicle; haveState = true; launchCount = 0; - updateThumbnailLocked(null /* newThumbnail */, description); + updateTaskDescription(description); } if (!stopped) { if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPED: " + this + " (stop complete)"); @@ -1834,7 +1750,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } } - public void reportFullyDrawnLocked() { + public void reportFullyDrawnLocked(boolean restoredFromBundle) { final long curTime = SystemClock.uptimeMillis(); if (displayStartTime != 0) { reportLaunchTimeLocked(curTime); @@ -1867,6 +1783,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } stack.mFullyDrawnStartTime = 0; } + mStackSupervisor.mActivityMetricsLogger.logAppTransitionReportedDrawn(this, + restoredFromBundle); fullyDrawnStartTime = 0; } @@ -2010,6 +1928,13 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo /** Checks whether the activity should be shown for current user. */ public boolean okToShowLocked() { + // We cannot show activities when the device is locked and the application is not + // encryption aware. + if (!StorageManager.isUserKeyUnlocked(userId) + && !info.applicationInfo.isEncryptionAware()) { + return false; + } + return (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0 || (mStackSupervisor.isCurrentProfileLocked(userId) && service.mUserController.isUserRunningLocked(userId, 0 /* flags */)); @@ -2171,7 +2096,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo void setRequestedOrientation(int requestedOrientation) { if (ActivityInfo.isFixedOrientation(requestedOrientation) && !fullscreen - && appInfo.targetSdkVersion > O) { + && appInfo.targetSdkVersion >= O_MR1) { throw new IllegalStateException("Only fullscreen activities can request orientation"); } @@ -2209,19 +2134,16 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo * a new merged configuration is sent to the client for this activity. */ void setLastReportedConfiguration(@NonNull MergedConfiguration config) { - mLastReportedConfiguration.setTo(config); + setLastReportedConfiguration(config.getGlobalConfiguration(), + config.getOverrideConfiguration()); } - /** Call when override config was sent to the Window Manager to update internal records. */ - // TODO(b/36505427): Why do we set last reported based on sending the config to WM? Seems like - // we should only set this when we actually report to the activity which is what the method - // setLastReportedMergedOverrideConfiguration() does. Investigate if this is really needed. - void onOverrideConfigurationSent() { - mLastReportedConfiguration.setOverrideConfiguration(getMergedOverrideConfiguration()); + private void setLastReportedConfiguration(Configuration global, Configuration override) { + mLastReportedConfiguration.setConfiguration(global, override); } @Override - void onOverrideConfigurationChanged(Configuration newConfig) { + public void onOverrideConfigurationChanged(Configuration newConfig) { final Configuration currentConfig = getOverrideConfiguration(); if (currentConfig.equals(newConfig)) { return; @@ -2231,9 +2153,6 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo return; } mWindowContainerController.onOverrideConfigurationChanged(newConfig, mBounds); - // TODO(b/36505427): Can we consolidate the call points of onOverrideConfigurationSent() - // to just use this method instead? - onOverrideConfigurationSent(); } // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer. @@ -2308,9 +2227,9 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo // We must base this on the parent configuration, because we set our override // configuration's appBounds based on the result of this method. If we used our own // configuration, it would be influenced by past invocations. - final Configuration configuration = getParent().getConfiguration(); - final int containingAppWidth = configuration.appBounds.width(); - final int containingAppHeight = configuration.appBounds.height(); + final Rect appBounds = getParent().getWindowConfiguration().getAppBounds(); + final int containingAppWidth = appBounds.width(); + final int containingAppHeight = appBounds.height(); int maxActivityWidth = containingAppWidth; int maxActivityHeight = containingAppHeight; @@ -2339,8 +2258,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo outBounds.set(0, 0, maxActivityWidth, maxActivityHeight); // Position the activity frame on the opposite side of the nav bar. final int navBarPosition = service.mWindowManager.getNavBarPosition(); - final int left = navBarPosition == NAV_BAR_LEFT - ? configuration.appBounds.right - outBounds.width() : 0; + final int left = navBarPosition == NAV_BAR_LEFT ? appBounds.right - outBounds.width() : 0; outBounds.offsetTo(left, 0 /* top */); } @@ -2420,8 +2338,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo // Update last reported values. final Configuration newMergedOverrideConfig = getMergedOverrideConfiguration(); - mLastReportedConfiguration.setConfiguration(service.getGlobalConfiguration(), - newMergedOverrideConfig); + + setLastReportedConfiguration(service.getGlobalConfiguration(), newMergedOverrideConfig); if (changes == 0 && !forceNewConfig) { if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, @@ -2571,6 +2489,10 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo changes &= ~CONFIG_SMALLEST_SCREEN_SIZE; } } + // We don't want window configuration to cause relaunches. + if ((changes & CONFIG_WINDOW_CONFIGURATION) != 0) { + changes &= ~CONFIG_WINDOW_CONFIGURATION; + } return changes; } @@ -2789,16 +2711,6 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo return r; } - private static String activityTypeToString(int type) { - switch (type) { - case APPLICATION_ACTIVITY_TYPE: return "APPLICATION_ACTIVITY_TYPE"; - case HOME_ACTIVITY_TYPE: return "HOME_ACTIVITY_TYPE"; - case RECENTS_ACTIVITY_TYPE: return "RECENTS_ACTIVITY_TYPE"; - case ASSISTANT_ACTIVITY_TYPE: return "ASSISTANT_ACTIVITY_TYPE"; - default: return Integer.toString(type); - } - } - private static boolean isInVrUiMode(Configuration config) { return (config.uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET; } diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 896f846feec0..4560d3a6e4f7 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -23,7 +23,13 @@ import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; import static android.app.ActivityManager.StackId.HOME_STACK_ID; import static android.app.ActivityManager.StackId.INVALID_STACK_ID; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; -import static android.app.ActivityManager.StackId.RECENTS_STACK_ID; +import static android.app.ActivityManager.StackId.getActivityTypeForStackId; +import static android.app.ActivityManager.StackId.getWindowingModeForStackId; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT; import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING; import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS; @@ -64,9 +70,6 @@ import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAV import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; -import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE; -import static com.android.server.am.ActivityRecord.ASSISTANT_ACTIVITY_TYPE; -import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE; import static com.android.server.am.ActivityStack.ActivityState.STOPPED; import static com.android.server.am.ActivityStack.ActivityState.STOPPING; import static com.android.server.am.ActivityStackSupervisor.FindTaskResult; @@ -125,6 +128,7 @@ import com.android.internal.app.IVoiceInteractor; import com.android.internal.os.BatteryStatsImpl; import com.android.server.Watchdog; import com.android.server.am.ActivityManagerService.ItemMatcher; +import com.android.server.wm.ConfigurationContainer; import com.android.server.wm.StackWindowController; import com.android.server.wm.StackWindowListener; import com.android.server.wm.WindowManagerService; @@ -209,7 +213,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } @Override - void onParentChanged() { + protected void onParentChanged() { super.onParentChanged(); mStackSupervisor.updateUIDsPresentOnDisplay(); } @@ -459,20 +463,36 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mTaskPositioner = mStackId == FREEFORM_WORKSPACE_STACK_ID ? new LaunchingTaskPositioner() : null; mTmpRect2.setEmpty(); + updateOverrideConfiguration(); mWindowContainerController = createStackWindowController(display.mDisplayId, onTop, - mTmpRect2); + mTmpRect2, getOverrideConfiguration()); mStackSupervisor.mStacks.put(mStackId, this); postAddToDisplay(display, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop); } - T createStackWindowController(int displayId, boolean onTop, Rect outBounds) { - return (T) new StackWindowController(mStackId, this, displayId, onTop, outBounds); + T createStackWindowController(int displayId, boolean onTop, Rect outBounds, + Configuration overrideConfig) { + return (T) new StackWindowController(mStackId, this, displayId, onTop, outBounds, + overrideConfig); } T getWindowContainerController() { return mWindowContainerController; } + // TODO: Not needed once we are no longer using stack ids as the override config. can be passed + // in. + private void updateOverrideConfiguration() { + final int windowingMode = getWindowingModeForStackId(mStackId); + if (windowingMode != WINDOWING_MODE_UNDEFINED) { + setWindowingMode(windowingMode); + } + final int activityType = getActivityTypeForStackId(mStackId); + if (activityType != ACTIVITY_TYPE_UNDEFINED) { + setActivityType(activityType); + } + } + /** Adds the stack to specified display and calls WindowManager to do the same. */ void reparent(ActivityStackSupervisor.ActivityDisplay activityDisplay, boolean onTop) { removeFromDisplay(); @@ -816,14 +836,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai return hadit; } - final boolean isHomeStack() { - return mStackId == HOME_STACK_ID; - } - - final boolean isRecentsStack() { - return mStackId == RECENTS_STACK_ID; - } - final boolean isHomeOrRecentsStack() { return StackId.isHomeOrRecentsStack(mStackId); } @@ -836,10 +848,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai return mStackId == PINNED_STACK_ID; } - final boolean isAssistantStack() { - return mStackId == ASSISTANT_STACK_ID; - } - final boolean isOnHomeDisplay() { return isAttached() && mDisplayId == DEFAULT_DISPLAY; } @@ -899,7 +907,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai int addIndex = mStacks.size(); if (addIndex > 0) { final ActivityStack topStack = mStacks.get(addIndex - 1); - if (StackId.isAlwaysOnTop(topStack.mStackId) && topStack != this) { + if (topStack.getWindowConfiguration().isAlwaysOnTop() + && topStack != this) { // If the top stack is always on top, we move this stack just below it. addIndex--; } @@ -911,7 +920,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } boolean isFocusable() { - if (StackId.canReceiveKeys(mStackId)) { + if (getWindowConfiguration().canReceiveKeys()) { return true; } // The stack isn't focusable. See if its top activity is focusable to force focus on the @@ -959,7 +968,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r); continue; } - if (r.mActivityType != target.mActivityType) { + if (!r.hasCompatibleActivityType(target)) { if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch activity type"); continue; } @@ -1170,10 +1179,26 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } } + void checkReadyForSleep() { + if (shouldSleepActivities() && goToSleepIfPossible(false /* shuttingDown */)) { + mStackSupervisor.checkReadyForSleepLocked(true /* allowDelay */); + } + } + /** - * @return true if something must be done before going to sleep. + * Tries to put the activities in the stack to sleep. + * + * If the stack is not in a state where its activities can be put to sleep, this function will + * start any necessary actions to move the stack into such a state. It is expected that this + * function get called again when those actions complete. + * + * @param shuttingDown true when the called because the device is shutting down. + * @return true if the stack finished going to sleep, false if the stack only started the + * process of going to sleep (checkReadyForSleep will be called when that process finishes). */ - boolean checkReadyForSleepLocked() { + boolean goToSleepIfPossible(boolean shuttingDown) { + boolean shouldSleep = true; + if (mResumedActivity != null) { // Still have something resumed; can't sleep until it is paused. if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep needs to pause " + mResumedActivity); @@ -1183,23 +1208,44 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // If we are in the middle of resuming the top activity in // {@link #resumeTopActivityUncheckedLocked}, mResumedActivity will be set but not // resumed yet. We must not proceed pausing the activity here. This method will be - // called again if necessary as part of + // called again if necessary as part of {@link #checkReadyForSleep} or // {@link ActivityStackSupervisor#checkReadyForSleepLocked}. if (mStackSupervisor.inResumeTopActivity) { if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "In the middle of resuming top activity " + mResumedActivity); - return true; + } else { + startPausingLocked(false, true, null, false); } - - startPausingLocked(false, true, null, false); - return true; - } - if (mPausingActivity != null) { + shouldSleep = false ; + } else if (mPausingActivity != null) { // Still waiting for something to pause; can't sleep yet. if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still waiting to pause " + mPausingActivity); - return true; + shouldSleep = false; } - return false; + + if (!shuttingDown) { + if (containsActivityFromStack(mStackSupervisor.mStoppingActivities)) { + // Still need to tell some activities to stop; can't sleep yet. + if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to stop " + + mStackSupervisor.mStoppingActivities.size() + " activities"); + + mStackSupervisor.scheduleIdleLocked(); + shouldSleep = false; + } + + if (containsActivityFromStack(mStackSupervisor.mGoingToSleepActivities)) { + // Still need to tell some activities to sleep; can't sleep yet. + if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to sleep " + + mStackSupervisor.mGoingToSleepActivities.size() + " activities"); + shouldSleep = false; + } + } + + if (shouldSleep) { + goToSleep(); + } + + return shouldSleep; } void goToSleep() { @@ -1219,6 +1265,15 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } } + private boolean containsActivityFromStack(List<ActivityRecord> rs) { + for (ActivityRecord r : rs) { + if (r.getStack() == this) { + return true; + } + } + return false; + } + /** * Schedule a pause timeout in case the app doesn't respond. We don't give it much time because * this directly impacts the responsiveness seen by the user. @@ -1251,7 +1306,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (mPausingActivity != null) { Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity + " state=" + mPausingActivity.state); - if (!mService.isSleepingLocked()) { + if (!shouldSleepActivities()) { // Avoid recursion among check for sleep and complete pause during sleeping. // Because activity will be paused immediately after resume, just let pause // be completed by the order of activity paused from clients. @@ -1279,11 +1334,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai prev.getTask().touchActiveTime(); clearLaunchTime(prev); final ActivityRecord next = mStackSupervisor.topRunningActivityLocked(); - if (mService.mHasRecents - && (next == null || next.noDisplay || next.getTask() != prev.getTask() - || uiSleeping)) { - prev.mUpdateTaskThumbnailWhenHidden = true; - } + stopFullyDrawnTraceIfNeeded(); mService.updateCpuStats(); @@ -1411,7 +1462,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // We can't clobber it, because the stop confirmation will not be handled. // We don't need to schedule another stop, we only need to let it happen. prev.state = STOPPING; - } else if (!prev.visible || mService.isSleepingOrShuttingDownLocked()) { + } else if (!prev.visible || shouldSleepOrShutDownActivities()) { // Clear out any deferred client hide we might currently have. prev.setDeferHidingClient(false); // If we were visible then resumeTopActivities will release resources before @@ -1433,10 +1484,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (resumeNext) { final ActivityStack topStack = mStackSupervisor.getFocusedStack(); - if (!mService.isSleepingOrShuttingDownLocked()) { + if (!topStack.shouldSleepOrShutDownActivities()) { mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null); } else { - mStackSupervisor.checkReadyForSleepLocked(); + checkReadyForSleep(); ActivityRecord top = topStack.topRunningActivityLocked(); if (top == null || (prev != null && top != prev)) { // If there are no more activities available to run, do resume anyway to start @@ -1502,7 +1553,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mStackSupervisor.scheduleIdleTimeoutLocked(r); } } else { - mStackSupervisor.checkReadyForSleepLocked(); + checkReadyForSleep(); } } @@ -1598,7 +1649,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } if (!isHomeOrRecentsStack() && r.frontOfTask && task.isOverHomeStack() - && !StackId.isHomeOrRecentsStack(stackBehindId) && !isAssistantStack()) { + && !StackId.isHomeOrRecentsStack(stackBehindId) + && !isActivityTypeAssistant()) { // Stack isn't translucent if it's top activity should have the home stack // behind it and the stack currently behind it isn't the home or recents stack // or the assistant stack. @@ -1645,7 +1697,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (mStackId == DOCKED_STACK_ID) { // If the assistant stack is focused and translucent, then the docked stack is always // visible - if (topStack.isAssistantStack()) { + if (topStack.isActivityTypeAssistant()) { return (topStack.isStackTranslucent(starting, DOCKED_STACK_ID)) ? STACK_VISIBLE : STACK_INVISIBLE; } @@ -1670,11 +1722,12 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } final int stackBehindTopId = (stackBehindTopIndex >= 0) ? mStacks.get(stackBehindTopIndex).mStackId : INVALID_STACK_ID; - if (topStackId == DOCKED_STACK_ID || StackId.isAlwaysOnTop(topStackId)) { + final boolean alwaysOnTop = topStack.getWindowConfiguration().isAlwaysOnTop(); + if (topStackId == DOCKED_STACK_ID || alwaysOnTop) { if (stackIndex == stackBehindTopIndex) { // Stacks directly behind the docked or pinned stack are always visible. return STACK_VISIBLE; - } else if (StackId.isAlwaysOnTop(topStackId) && stackIndex == stackBehindTopIndex - 1) { + } else if (alwaysOnTop && stackIndex == stackBehindTopIndex - 1) { // Otherwise, this stack can also be visible if it is directly behind a docked stack // or translucent assistant stack behind an always-on-top top-most stack if (stackBehindTopId == DOCKED_STACK_ID) { @@ -1776,14 +1829,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); if (r.finishing) { - // Normally the screenshot will be taken in makeInvisible(). When an activity - // is finishing, we no longer change its visibility, but we still need to take - // the screenshots if startPausingLocked decided it should be taken. - if (r.mUpdateTaskThumbnailWhenHidden) { - r.updateThumbnailLocked(r.screenshotActivityLocked(), - null /* description */); - r.mUpdateTaskThumbnailWhenHidden = false; - } continue; } final boolean isTop = r == top; @@ -1854,39 +1899,22 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // status of an activity in a previous task affects other. behindFullscreenActivity = stackVisibility == STACK_INVISIBLE; } else if (mStackId == HOME_STACK_ID) { - if (task.isHomeTask()) { - if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + task - + " stackInvisible=" + stackInvisible - + " behindFullscreenActivity=" + behindFullscreenActivity); - // No other task in the home stack should be visible behind the home activity. - // Home activities is usually a translucent activity with the wallpaper behind - // them. However, when they don't have the wallpaper behind them, we want to - // show activities in the next application stack behind them vs. another - // task in the home stack like recents. - behindFullscreenActivity = true; - } else if (task.isRecentsTask() - && task.getTaskToReturnTo() == APPLICATION_ACTIVITY_TYPE) { - if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, - "Recents task returning to app: at " + task - + " stackInvisible=" + stackInvisible - + " behindFullscreenActivity=" + behindFullscreenActivity); - // We don't want any other tasks in the home stack visible if the recents - // activity is going to be returning to an application activity type. - // We do this to preserve the visible order the user used to get into the - // recents activity. The recents activity is normally translucent and if it - // doesn't have the wallpaper behind it the next activity in the home stack - // shouldn't be visible when the home stack is brought to the front to display - // the recents activity from an app. - behindFullscreenActivity = true; - } + if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + task + + " stackInvisible=" + stackInvisible + + " behindFullscreenActivity=" + behindFullscreenActivity); + // No other task in the home stack should be visible behind the home activity. + // Home activities is usually a translucent activity with the wallpaper behind + // them. However, when they don't have the wallpaper behind them, we want to + // show activities in the next application stack behind them vs. another + // task in the home stack like recents. + behindFullscreenActivity = true; } else if (mStackId == FULLSCREEN_WORKSPACE_STACK_ID) { if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Skipping after task=" + task + " returning to non-application type=" + task.getTaskToReturnTo()); // Once we reach a fullscreen stack task that has a running activity and should // return to another stack task, then no other activities behind that one should // be visible. - if (task.topRunningActivityLocked() != null && - task.getTaskToReturnTo() != APPLICATION_ACTIVITY_TYPE) { + if (task.topRunningActivityLocked() != null && !task.returnsToStandardTask()) { behindFullscreenActivity = true; } } @@ -2030,7 +2058,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Making invisible: " + r + " " + r.state); try { final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState( - "makeInvisible", true /* noThrow */, true /* beforeStopping */); + "makeInvisible", true /* beforeStopping */); // Defer telling the client it is hidden if it can enter Pip and isn't current stopped // or stopping. This gives it a chance to enter Pip in onPause(). final boolean deferHidingClient = canEnterPictureInPicture @@ -2049,7 +2077,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // Reset the flag indicating that an app can enter picture-in-picture once the // activity is hidden - r.supportsPictureInPictureWhilePausing = false; + r.supportsEnterPipOnTaskSwitch = false; break; case INITIALIZING: @@ -2211,7 +2239,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // is skipped. final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */); if (next == null || !next.canTurnScreenOn()) { - mStackSupervisor.checkReadyForSleepLocked(); + checkReadyForSleep(); } return result; @@ -2283,10 +2311,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // This task is going away but it was supposed to return to the home stack. // Now the task above it has to return to the home task instead. final int taskNdx = mTaskHistory.indexOf(prevTask) + 1; - mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE); + mTaskHistory.get(taskNdx).setTaskToReturnTo(ACTIVITY_TYPE_HOME); } else if (!isOnHomeDisplay()) { return false; - } else if (!isHomeStack()){ + } else if (!isActivityTypeHome()){ if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Launching home next"); return isOnHomeDisplay() && @@ -2296,7 +2324,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // If we are sleeping, and there is no resumed activity, and the top // activity is paused, well that is the state we want. - if (mService.isSleepingOrShuttingDownLocked() + if (shouldSleepOrShutDownActivities() && mLastPausedActivity == next && mStackSupervisor.allPausedActivitiesComplete()) { // Make sure we have executed any pending transitions, since there @@ -2344,7 +2372,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // represent the last resumed activity. However, the last focus stack does if it isn't null. final ActivityRecord lastResumed = lastFocusedStack.mResumedActivity; lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState( - "resumeTopActivity", true /* noThrow */, userLeaving /* beforeStopping */); + "resumeTopActivity", userLeaving /* beforeStopping */); } // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity // to be paused, while at the same time resuming the new resume activity only if the @@ -2388,7 +2416,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // If the most recent activity was noHistory but was only stopped rather // than stopped+finished because the device went to sleep, we need to make // sure to finish it as we're making a new activity topmost. - if (mService.isSleepingLocked() && mLastNoHistoryActivity != null && + if (shouldSleepActivities() && mLastNoHistoryActivity != null && !mLastNoHistoryActivity.finishing) { if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + mLastNoHistoryActivity + " on new resume"); @@ -2534,6 +2562,16 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // the screen based on the new activity order. boolean notUpdated = true; if (mStackSupervisor.isFocusedStack(this)) { + + // We have special rotation behavior when Keyguard is locked. Make sure all activity + // visibilities are set correctly as well as the transition is updated if needed to + // get the correct rotation behavior. + // TODO: Remove this once visibilities are set correctly immediately when starting + // an activity. + if (mStackSupervisor.mKeyguardController.isKeyguardLocked()) { + mStackSupervisor.ensureActivitiesVisibleLocked(null /* starting */, + 0 /* configChanges */, false /* preserveWindows */); + } final Configuration config = mWindowManager.updateOrientationFromAppTokens( mStackSupervisor.getDisplayOverrideConfiguration(mDisplayId), next.mayFreezeScreenLocked(next.app) ? next.appToken : null, mDisplayId); @@ -2759,7 +2797,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // If this is not on the default display, then just set the return type to application if (!isOnHomeDisplay()) { - task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE); + task.setTaskToReturnTo(ACTIVITY_TYPE_STANDARD); return; } @@ -2771,8 +2809,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } // If the task was launched from the assistant stack, set the return type to assistant - if (lastStack.isAssistantStack()) { - task.setTaskToReturnTo(ASSISTANT_ACTIVITY_TYPE); + if (lastStack.isActivityTypeAssistant()) { + task.setTaskToReturnTo(ACTIVITY_TYPE_ASSISTANT); return; } @@ -2784,9 +2822,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // If it's a last task over home - we default to keep its return to type not to // make underlying task focused when this one will be finished. int returnToType = isLastTaskOverHome - ? task.getTaskToReturnTo() : APPLICATION_ACTIVITY_TYPE; + ? task.getTaskToReturnTo() : ACTIVITY_TYPE_STANDARD; if (fromHomeOrRecents && StackId.allowTopTaskToReturnHome(mStackId)) { - returnToType = topTask == null ? HOME_ACTIVITY_TYPE : topTask.taskType; + returnToType = topTask == null + ? ACTIVITY_TYPE_HOME : topTask.getActivityType(); } task.setTaskToReturnTo(returnToType); } @@ -2871,11 +2910,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // supporting picture-in-picture while pausing only if the starting activity // would not be considered an overlay on top of the current activity // (eg. not fullscreen, or the assistant) - if (focusedTopActivity != null - && focusedTopActivity.getStackId() != PINNED_STACK_ID - && r.getStackId() != ASSISTANT_STACK_ID - && r.fullscreen) { - focusedTopActivity.supportsPictureInPictureWhilePausing = true; + if (canEnterPipOnTaskSwitch(focusedTopActivity, + null /* toFrontTask */, r, options)) { + focusedTopActivity.supportsEnterPipOnTaskSwitch = true; } transit = TRANSIT_TASK_OPEN; } @@ -2930,6 +2967,37 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } } + /** + * @return Whether the switch to another task can trigger the currently running activity to + * enter PiP while it is pausing (if supported). Only one of {@param toFrontTask} or + * {@param toFrontActivity} should be set. + */ + private boolean canEnterPipOnTaskSwitch(ActivityRecord pipCandidate, + TaskRecord toFrontTask, ActivityRecord toFrontActivity, ActivityOptions opts) { + if (opts != null && opts.disallowEnterPictureInPictureWhileLaunching()) { + // Ensure the caller has requested not to trigger auto-enter PiP + return false; + } + if (pipCandidate == null || pipCandidate.getStackId() == PINNED_STACK_ID) { + // Ensure that we do not trigger entering PiP an activity on the pinned stack + return false; + } + final int targetStackId = toFrontTask != null ? toFrontTask.getStackId() + : toFrontActivity.getStackId(); + if (targetStackId == ASSISTANT_STACK_ID) { + // Ensure the task/activity being brought forward is not the assistant + return false; + } + final boolean isFullscreen = toFrontTask != null + ? toFrontTask.containsOnlyFullscreenActivities() + : toFrontActivity.fullscreen; + if (!isFullscreen) { + // Ensure the task/activity being brought forward is fullscreen + return false; + } + return true; + } + private boolean isTaskSwitch(ActivityRecord r, ActivityRecord topFocusedActivity) { return topFocusedActivity != null && r.getTask() != topFocusedActivity.getTask(); @@ -3009,7 +3077,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } else { targetTask = createTaskRecord( mStackSupervisor.getNextTaskIdForUserLocked(target.userId), - target.info, null, null, null, false, target.mActivityType); + target.info, null, null, null, false); targetTask.affinityIntent = target.intent; if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target + " out to new task " + targetTask); @@ -3320,8 +3388,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai throw new IllegalStateException("activity no longer associated with task:" + r); } - final boolean isAssistantOrOverAssistant = task.getStack().isAssistantStack() || - task.isOverAssistantStack(); + final boolean isAssistantOrOverAssistant = + task.getStack().isActivityTypeAssistant() || task.isOverAssistantStack(); if (r.frontOfTask && isATopFinishingTask(task) && (task.isOverHomeStack() || isAssistantOrOverAssistant)) { // For non-fullscreen or assistant stack, we want to move the focus to the next @@ -3356,8 +3424,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai * @param allowFocusSelf Is the focus allowed to remain on the same stack. */ private boolean adjustFocusToNextFocusableStackLocked(String reason, boolean allowFocusSelf) { - if (isAssistantStack() && bottomTask() != null && - bottomTask().getTaskToReturnTo() == HOME_ACTIVITY_TYPE) { + if (isActivityTypeAssistant() && bottomTask() != null + && bottomTask().returnsToHomeTask()) { // If the current stack is the assistant stack, then use the return-to type to determine // whether to return to the home screen. This is needed to workaround an issue where // launching a fullscreen task (and subequently returning from that task) will cause @@ -3382,8 +3450,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai return mStackSupervisor.moveHomeStackTaskToTop(reason); } - if (stack.isAssistantStack() && top != null - && top.getTask().getTaskToReturnTo() == HOME_ACTIVITY_TYPE) { + if (stack.isActivityTypeAssistant() && top != null + && top.getTask().returnsToHomeTask()) { // It is possible for the home stack to not be directly underneath the assistant stack. // For example, the assistant may start an activity in the fullscreen stack. Upon // returning to the assistant stack, we must ensure that the home stack is underneath @@ -3400,7 +3468,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) { if (!r.finishing) { - if (!mService.isSleepingLocked()) { + if (!shouldSleepActivities()) { if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + r); if (requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, "stop-no-history", false)) { @@ -3432,7 +3500,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai EventLogTags.writeAmStopActivity( r.userId, System.identityHashCode(r), r.shortComponentName); r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags); - if (mService.isSleepingOrShuttingDownLocked()) { + if (shouldSleepOrShutDownActivities()) { r.setSleeping(true); } Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r); @@ -3521,7 +3589,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (r.state == ActivityState.RESUMED || r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) { - if (!r.isHomeActivity() || mService.mHomeProcess != r.app) { + if (!r.isActivityTypeHome() || mService.mHomeProcess != r.app) { Slog.w(TAG, " Force finishing activity " + r.intent.getComponent().flattenToShortString()); finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false); @@ -3682,7 +3750,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } if (endTask) { - mStackSupervisor.removeLockedTaskLocked(task); + mService.mLockTaskController.removeLockedTask(task); } } else if (r.state != ActivityState.PAUSING) { // If the activity is PAUSING, we will complete the finish once @@ -3838,7 +3906,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (srec.frontOfTask && task != null && task.getBaseIntent() != null && task.getBaseIntent().isDocument()) { // Okay, this activity is at the root of its task. What to do, what to do... - if (task.getTaskToReturnTo() != ActivityRecord.APPLICATION_ACTIVITY_TYPE) { + if (!task.returnsToStandardTask()) { // Finishing won't return to an application, so we need to recreate. return true; } @@ -3848,11 +3916,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai Slog.w(TAG, "shouldUpRecreateTask: task not in history for " + srec); return false; } - if (taskIdx == 0) { - // At the bottom of the stack, nothing to go back to. - return true; - } - TaskRecord prevTask = mTaskHistory.get(taskIdx); + final TaskRecord prevTask = mTaskHistory.get(taskIdx); if (!task.affinity.equals(prevTask.affinity)) { // These are different apps, so need to recreate. return true; @@ -4437,17 +4501,18 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } void moveHomeStackTaskToTop() { + if (!isActivityTypeHome()) { + throw new IllegalStateException("Calling moveHomeStackTaskToTop() on non-home stack: " + + this); + } final int top = mTaskHistory.size() - 1; - for (int taskNdx = top; taskNdx >= 0; --taskNdx) { - final TaskRecord task = mTaskHistory.get(taskNdx); - if (task.taskType == HOME_ACTIVITY_TYPE) { - if (DEBUG_TASKS || DEBUG_STACK) Slog.d(TAG_STACK, - "moveHomeStackTaskToTop: moving " + task); - mTaskHistory.remove(taskNdx); - mTaskHistory.add(top, task); - updateTaskMovement(task, true); - return; - } + if (top >= 0) { + final TaskRecord task = mTaskHistory.get(top); + if (DEBUG_TASKS || DEBUG_STACK) Slog.d(TAG_STACK, + "moveHomeStackTaskToTop: moving " + task); + mTaskHistory.remove(top); + mTaskHistory.add(top, task); + updateTaskMovement(task, true); } } @@ -4505,9 +4570,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // If a new task is moved to the front, then mark the existing top activity as supporting // picture-in-picture while paused only if the task would not be considered an oerlay on top // of the current activity (eg. not fullscreen, or the assistant) - if (topActivity != null && topActivity.getStackId() != PINNED_STACK_ID - && tr.getStackId() != ASSISTANT_STACK_ID && tr.containsOnlyFullscreenActivities()) { - topActivity.supportsPictureInPictureWhilePausing = true; + if (canEnterPipOnTaskSwitch(topActivity, tr, null /* toFrontActivity */, + options)) { + topActivity.supportsEnterPipOnTaskSwitch = true; } mStackSupervisor.resumeFocusedStackTopActivityLocked(); @@ -4536,8 +4601,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai Slog.i(TAG, "moveTaskToBack: " + tr); // If the task is locked, then show the lock task toast - if (mStackSupervisor.isLockedTask(tr)) { - mStackSupervisor.showLockTaskToast(); + if (!mService.mLockTaskController.checkLockedTask(tr)) { return false; } @@ -4571,7 +4635,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // If true, we should resume the home activity next if the task we are moving to the // back is over the home stack. We force to false if the task we are moving to back // is the home task and we don't want it resumed after moving to the back. - final boolean canGoHome = !tr.isHomeTask() && tr.isOverHomeStack(); + final boolean canGoHome = !tr.isActivityTypeHome() && tr.isOverHomeStack(); if (canGoHome) { final TaskRecord nextTask = getNextTask(tr); if (nextTask != null) { @@ -4606,7 +4670,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } if (taskNdx == 1) { // Set the last task before tr to go to home. - task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); + task.setTaskToReturnTo(ACTIVITY_TYPE_HOME); } } @@ -4616,7 +4680,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // Not ready yet! return false; } - tr.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE); + tr.setTaskToReturnTo(ACTIVITY_TYPE_STANDARD); return mStackSupervisor.resumeHomeStackTask(null, "moveTaskToBack"); } @@ -4830,7 +4894,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } return true; } - if (r.isHomeActivity()) { + if (r.isActivityTypeHome()) { if (homeActivity != null && homeActivity.equals(r.realActivity)) { Slog.i(TAG, "Skip force-stop again " + r); continue; @@ -4873,7 +4937,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai int numActivities = 0; int numRunning = 0; final ArrayList<ActivityRecord> activities = task.mActivities; - if (!allowed && !task.isHomeTask() && task.effectiveUid != callingUid) { + if (!allowed && !task.isActivityTypeHome() && task.effectiveUid != callingUid) { continue; } for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { @@ -4973,24 +5037,29 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll, - boolean dumpClient, String dumpPackage, boolean needSep, String header) { - boolean printed = false; + boolean dumpClient, String dumpPackage, boolean needSep) { + + if (mTaskHistory.isEmpty()) { + return false; + } + final String prefix = " "; for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { final TaskRecord task = mTaskHistory.get(taskNdx); - printed |= ActivityStackSupervisor.dumpHistoryList(fd, pw, - mTaskHistory.get(taskNdx).mActivities, " ", "Hist", true, !dumpAll, - dumpClient, dumpPackage, needSep, header, - " Task id #" + task.taskId + "\n" + - " mFullscreen=" + task.mFullscreen + "\n" + - " mBounds=" + task.mBounds + "\n" + - " mMinWidth=" + task.mMinWidth + "\n" + - " mMinHeight=" + task.mMinHeight + "\n" + - " mLastNonFullscreenBounds=" + task.mLastNonFullscreenBounds); - if (printed) { - header = null; - } + if (needSep) { + pw.println(""); + } + pw.println(prefix + "Task id #" + task.taskId); + pw.println(prefix + "mFullscreen=" + task.mFullscreen); + pw.println(prefix + "mBounds=" + task.mBounds); + pw.println(prefix + "mMinWidth=" + task.mMinWidth); + pw.println(prefix + "mMinHeight=" + task.mMinHeight); + pw.println(prefix + "mLastNonFullscreenBounds=" + task.mLastNonFullscreenBounds); + pw.println(prefix + "* " + task); + task.dump(pw, prefix + " "); + ActivityStackSupervisor.dumpHistoryList(fd, pw, mTaskHistory.get(taskNdx).mActivities, + prefix, "Hist", true, !dumpAll, dumpClient, dumpPackage, false, null, task); } - return printed; + return true; } ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) { @@ -5064,7 +5133,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (task.isOverHomeStack() && taskNdx < topTaskNdx) { final TaskRecord nextTask = mTaskHistory.get(taskNdx + 1); if (!nextTask.isOverHomeStack() && !nextTask.isOverAssistantStack()) { - nextTask.setTaskToReturnTo(HOME_ACTIVITY_TYPE); + nextTask.setTaskToReturnTo(ACTIVITY_TYPE_HOME); } } mTaskHistory.remove(task); @@ -5120,9 +5189,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, - boolean toTop, int type) { - TaskRecord task = new TaskRecord(mService, taskId, info, intent, voiceSession, - voiceInteractor, type); + boolean toTop) { + final TaskRecord task = new TaskRecord(mService, taskId, info, intent, voiceSession, + voiceInteractor); // add the task to stack first, mTaskPositioner might need the stack association addTask(task, toTop, "createTaskRecord"); final boolean isLockscreenShown = @@ -5278,4 +5347,13 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mNoAnimActivities.clear(); ActivityOptions.abort(options); } + + boolean shouldSleepActivities() { + final ActivityStackSupervisor.ActivityDisplay display = getDisplay(); + return display != null ? display.isSleeping() : mService.isSleepingLocked(); + } + + boolean shouldSleepOrShutDownActivities() { + return shouldSleepActivities() || mService.isShuttingDownLocked(); + } } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index e8bc68f21981..e4a2273387be 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -16,12 +16,10 @@ package com.android.server.am; +import static android.Manifest.permission.ACTIVITY_EMBEDDING; import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; import static android.Manifest.permission.START_ANY_ACTIVITY; import static android.Manifest.permission.START_TASKS_FROM_RECENTS; -import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED; -import static android.app.ActivityManager.LOCK_TASK_MODE_NONE; -import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED; import static android.app.ActivityManager.START_TASK_TO_FRONT; import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID; @@ -35,21 +33,23 @@ import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static android.app.ActivityManager.StackId.RECENTS_STACK_ID; import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY; import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.os.Process.SYSTEM_UID; import static android.os.PowerManager.PARTIAL_WAKE_LOCK; +import static android.os.Process.SYSTEM_UID; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.FLAG_PRIVATE; import static android.view.Display.INVALID_DISPLAY; import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT; import static android.view.Display.TYPE_VIRTUAL; - import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_PICTURE_IN_PICTURE_EXPANDED_TO_FULLSCREEN; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_IDLE; -import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PAUSE; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RELEASE; @@ -57,10 +57,8 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONTAINERS; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_IDLE; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PAUSE; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RELEASE; @@ -72,8 +70,6 @@ import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.ActivityManagerService.ANIMATE; import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG; -import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE; -import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE; import static com.android.server.am.ActivityStack.ActivityState.DESTROYED; import static com.android.server.am.ActivityStack.ActivityState.DESTROYING; import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING; @@ -85,11 +81,8 @@ import static com.android.server.am.ActivityStack.ActivityState.STOPPING; import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING; import static com.android.server.am.ActivityStack.STACK_INVISIBLE; import static com.android.server.am.ActivityStack.STACK_VISIBLE; -import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV; -import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE; -import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED; import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT; import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE; import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT; @@ -105,13 +98,12 @@ import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityManager.StackId; import android.app.ActivityManager.StackInfo; +import android.app.ActivityManagerInternal.SleepToken; import android.app.ActivityOptions; import android.app.AppOpsManager; import android.app.ProfilerInfo; import android.app.ResultInfo; -import android.app.StatusBarManager; import android.app.WaitResult; -import android.app.admin.IDevicePolicyManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -134,19 +126,15 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; -import android.os.ParcelFileDescriptor; import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; -import android.os.ServiceManager; import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.os.WorkSource; import android.provider.MediaStore; -import android.provider.Settings; -import android.provider.Settings.SettingNotFoundException; import android.service.voice.IVoiceInteractionSession; import android.util.ArrayMap; import android.util.ArraySet; @@ -156,17 +144,17 @@ import android.util.MergedConfiguration; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; +import android.util.TimeUtils; import android.view.Display; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.content.ReferrerIntent; import com.android.internal.logging.MetricsLogger; import com.android.internal.os.TransferPipe; -import com.android.internal.statusbar.IStatusBarService; import com.android.internal.util.ArrayUtils; -import com.android.internal.widget.LockPatternUtils; import com.android.server.LocalServices; import com.android.server.am.ActivityStack.ActivityState; +import com.android.server.wm.ConfigurationContainer; import com.android.server.wm.PinnedStackWindowController; import com.android.server.wm.WindowManagerService; @@ -177,6 +165,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; +import java.util.Iterator; import java.util.List; import java.util.Set; @@ -184,7 +173,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStackSupervisor" : TAG_AM; private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS; private static final String TAG_IDLE = TAG + POSTFIX_IDLE; - private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK; private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE; private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS; private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE; @@ -210,17 +198,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D static final int HANDLE_DISPLAY_ADDED = FIRST_SUPERVISOR_STACK_MSG + 5; static final int HANDLE_DISPLAY_CHANGED = FIRST_SUPERVISOR_STACK_MSG + 6; static final int HANDLE_DISPLAY_REMOVED = FIRST_SUPERVISOR_STACK_MSG + 7; - static final int LOCK_TASK_START_MSG = FIRST_SUPERVISOR_STACK_MSG + 9; - static final int LOCK_TASK_END_MSG = FIRST_SUPERVISOR_STACK_MSG + 10; static final int LAUNCH_TASK_BEHIND_COMPLETE = FIRST_SUPERVISOR_STACK_MSG + 12; - static final int SHOW_LOCK_TASK_ESCAPE_MESSAGE_MSG = FIRST_SUPERVISOR_STACK_MSG + 13; static final int REPORT_MULTI_WINDOW_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 14; static final int REPORT_PIP_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 15; private static final String VIRTUAL_DISPLAY_BASE_NAME = "ActivityViewVirtualDisplay"; - private static final String LOCK_TASK_TAG = "Lock-to-App"; - // Used to indicate if an object (e.g. stack) that we are trying to get // should be created if it doesn't exist already. static final boolean CREATE_IF_NEEDED = true; @@ -288,11 +271,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D /** Action restriction: launching the activity is restricted by an app op. */ private static final int ACTIVITY_RESTRICTION_APPOP = 2; - /** Status Bar Service **/ - private IBinder mToken = new Binder(); - private IStatusBarService mStatusBarService; - private IDevicePolicyManager mDevicePolicyManager; - // For debugging to make sure the caller when acquiring/releasing our // wake lock is the system process. static final boolean VALIDATE_WAKE_LOCK_CALLER = false; @@ -375,9 +353,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D * is being brought in front of us. */ boolean mUserLeaving = false; - /** Set when we have taken too long waiting to go to sleep. */ - boolean mSleepTimeout = false; - /** * We don't want to allow the device to go to sleep while in the process * of launching an activity. This is primarily to allow alarm intent @@ -393,6 +368,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D */ PowerManager.WakeLock mGoingToSleep; + /** + * A list of tokens that cause the top activity to be put to sleep. + * They are used by components that may hide and block interaction with underlying + * activities. + */ + final ArrayList<SleepToken> mSleepTokens = new ArrayList<SleepToken>(); + /** Stack id of the front stack when user switched, indexed by userId. */ SparseIntArray mUserStackInFront = new SparseIntArray(2); @@ -409,20 +391,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D private DisplayManagerInternal mDisplayManagerInternal; private InputManagerInternal mInputManagerInternal; - /** The chain of tasks in lockTask mode. The current frontmost task is at the top, and tasks - * may be finished until there is only one entry left. If this is empty the system is not - * in lockTask mode. */ - ArrayList<TaskRecord> mLockTaskModeTasks = new ArrayList<>(); - /** Store the current lock task mode. Possible values: - * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED}, - * {@link ActivityManager#LOCK_TASK_MODE_PINNED} - */ - private int mLockTaskModeState; - /** - * Notifies the user when entering/exiting lock-task. - */ - private LockTaskNotify mLockTaskNotify; - /** Used to keep resumeTopActivityUncheckedLocked() from being entered recursively */ boolean inResumeTopActivity; @@ -619,34 +587,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mLaunchingActivity.setReferenceCounted(false); } - // This function returns a IStatusBarService. The value is from ServiceManager. - // getService and is cached. - private IStatusBarService getStatusBarService() { - synchronized (mService) { - if (mStatusBarService == null) { - mStatusBarService = IStatusBarService.Stub.asInterface( - ServiceManager.checkService(Context.STATUS_BAR_SERVICE)); - if (mStatusBarService == null) { - Slog.w("StatusBarManager", "warning: no STATUS_BAR_SERVICE"); - } - } - return mStatusBarService; - } - } - - private IDevicePolicyManager getDevicePolicyManager() { - synchronized (mService) { - if (mDevicePolicyManager == null) { - mDevicePolicyManager = IDevicePolicyManager.Stub.asInterface( - ServiceManager.checkService(Context.DEVICE_POLICY_SERVICE)); - if (mDevicePolicyManager == null) { - Slog.w(TAG, "warning: no DEVICE_POLICY_SERVICE"); - } - } - return mDevicePolicyManager; - } - } - void setWindowManager(WindowManagerService wm) { synchronized (mService) { mWindowManager = wm; @@ -750,7 +690,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } if (prev != null) { - prev.getTask().setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE); + prev.getTask().setTaskToReturnTo(ACTIVITY_TYPE_STANDARD); } mHomeStack.moveHomeStackTaskToTop(); @@ -1329,6 +1269,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D r.app = app; + if (mKeyguardController.isKeyguardLocked()) { + r.notifyUnknownVisibilityLaunched(); + } + // Have the window manager re-evaluate the orientation of the screen based on the new // activity order. Note that as a result of this, it can call back into the activity // manager with a new orientation. We don't care about that, because the activity is @@ -1355,9 +1299,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D r.setVisibility(true); } - if (mKeyguardController.isKeyguardLocked()) { - r.notifyUnknownVisibilityLaunched(); - } final int applicationInfoUid = (r.info.applicationInfo != null) ? r.info.applicationInfo.uid : -1; if ((r.userId != app.userId) || (r.appInfo.uid != applicationInfoUid)) { @@ -1383,8 +1324,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE || task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV) { - setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE", - false); + mService.mLockTaskController.startLockTaskMode(task, false, 0 /* blank UID */); } try { @@ -1404,7 +1344,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D + " newIntents=" + newIntents + " andResume=" + andResume); EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY, r.userId, System.identityHashCode(r), task.taskId, r.shortComponentName); - if (r.isHomeActivity()) { + if (r.isActivityTypeHome()) { // Home process is the root process of the task. mService.mHomeProcess = task.mActivities.get(0).app; } @@ -1644,7 +1584,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D if (options.getLaunchTaskId() != INVALID_STACK_ID) { final int startInTaskPerm = mService.checkPermission(START_TASKS_FROM_RECENTS, callingPid, callingUid); - if (startInTaskPerm != PERMISSION_GRANTED) { + if (startInTaskPerm == PERMISSION_DENIED) { final String msg = "Permission Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ") with launchTaskId=" @@ -1697,9 +1637,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return true; } - if (activityDisplay.mDisplay.getType() == TYPE_VIRTUAL - && activityDisplay.mDisplay.getOwnerUid() != SYSTEM_UID - && activityDisplay.mDisplay.getOwnerUid() != aInfo.applicationInfo.uid) { + final int displayOwnerUid = activityDisplay.mDisplay.getOwnerUid(); + if (activityDisplay.mDisplay.getType() == TYPE_VIRTUAL && displayOwnerUid != SYSTEM_UID + && displayOwnerUid != aInfo.applicationInfo.uid) { // Limit launching on virtual displays, because their contents can be read from Surface // by apps that created them. if ((aInfo.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) { @@ -1707,6 +1647,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D + " disallow launch on virtual display for not-embedded activity."); return false; } + // Check if the caller is allowed to embed activities from other apps. + if (mService.checkPermission(ACTIVITY_EMBEDDING, callingPid, callingUid) + == PERMISSION_DENIED) { + if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:" + + " disallow activity embedding without permission."); + return false; + } } if (!activityDisplay.isPrivate()) { @@ -1717,7 +1664,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } // Check if the caller is the owner of the display. - if (activityDisplay.mDisplay.getOwnerUid() == callingUid) { + if (displayOwnerUid == callingUid) { if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:" + " allow launch for owner of the display"); return true; @@ -1762,7 +1709,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D String callingPackage, int callingPid, int callingUid, boolean ignoreTargetSecurity) { if (!ignoreTargetSecurity && mService.checkComponentPermission(activityInfo.permission, callingPid, callingUid, activityInfo.applicationInfo.uid, activityInfo.exported) - == PackageManager.PERMISSION_DENIED) { + == PERMISSION_DENIED) { return ACTIVITY_RESTRICTION_PERMISSION; } @@ -1809,8 +1756,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return ACTIVITY_RESTRICTION_NONE; } - if (mService.checkPermission(permission, callingPid, callingUid) == - PackageManager.PERMISSION_DENIED) { + if (mService.checkPermission(permission, callingPid, callingUid) == PERMISSION_DENIED) { return ACTIVITY_RESTRICTION_PERMISSION; } @@ -2133,7 +2079,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) { // Caller wants the home activity moved with it. To accomplish this, // we'll just indicate that this task returns to the home task. - task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); + task.setTaskToReturnTo(ACTIVITY_TYPE_HOME); } ActivityStack currentStack = task.getStack(); if (currentStack == null) { @@ -2319,11 +2265,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D final ArrayList<TaskRecord> tasks = mHomeStack.getAllTasks(); for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { final TaskRecord task = tasks.get(taskNdx); - if (task.isHomeTask()) { + if (task.isActivityTypeHome()) { final ArrayList<ActivityRecord> activities = task.mActivities; for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); - if (r.isHomeActivity() + if (r.isActivityTypeHome() && ((userId == UserHandle.USER_ALL) || (r.userId == userId))) { return r; } @@ -2355,8 +2301,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return; } - if (!allowResizeInDockedMode && !StackId.tasksAreFloating(stackId) && - getStack(DOCKED_STACK_ID) != null) { + if (!allowResizeInDockedMode + && !stack.getWindowConfiguration().tasksAreFloating() + && getStack(DOCKED_STACK_ID) != null) { // If the docked stack exists, don't resize non-floating stacks independently of the // size computed from the docked stack size (otherwise they will be out of sync) return; @@ -2455,8 +2402,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // Update the return-to to reflect where the pinned stack task was moved // from so that we retain the stack that was previously visible if the // pinned stack is recreated. See moveActivityToPinnedStackLocked(). - task.setTaskToReturnTo(isFullscreenStackVisible && onTop ? - APPLICATION_ACTIVITY_TYPE : HOME_ACTIVITY_TYPE); + task.setTaskToReturnTo(isFullscreenStackVisible ? + ACTIVITY_TYPE_STANDARD : ACTIVITY_TYPE_HOME); } // Defer resume until all the tasks have been moved to the fullscreen stack task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP, @@ -2976,8 +2923,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // move the home stack forward if we are currently entering picture-in-picture // while pausing because that changes the focused stack and may prevent the new // starting activity from resuming. - if (moveHomeStackToFront && task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE - && (r.state == RESUMED || !r.supportsPictureInPictureWhilePausing)) { + if (moveHomeStackToFront && task.returnsToHomeTask() + && (r.state == RESUMED || !r.supportsEnterPipOnTaskSwitch)) { // Move the home stack forward if the task we just moved to the pinned stack // was launched from home so home should be visible behind it. moveHomeStackToFront(reason); @@ -2995,8 +2942,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // ensures that all the necessary work to migrate states in the old and new stacks // is also done. final TaskRecord newTask = task.getStack().createTaskRecord( - getNextTaskIdForUserLocked(r.userId), r.info, r.intent, null, null, true, - r.mActivityType); + getNextTaskIdForUserLocked(r.userId), r.info, r.intent, null, null, true); r.reparent(newTask, MAX_VALUE, "moveActivityToStack"); // Defer resume until below, and do not schedule PiP changes until we animate below @@ -3006,7 +2952,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // Reset the state that indicates it can enter PiP while pausing after we've moved it // to the pinned stack - r.supportsPictureInPictureWhilePausing = false; + r.supportsEnterPipOnTaskSwitch = false; } finally { mWindowManager.continueSurfaceLayout(); } @@ -3068,7 +3014,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); - if (!checkActivityBelongsInStack(r, stack)) { + if (!r.hasCompatibleActivityType(stack)) { if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping stack: (mismatch activity/stack) " + stack); continue; @@ -3096,21 +3042,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return affinityMatch; } - /** - * Checks that for the given activity {@param r}, its activity type matches the {@param stack} - * type. - */ - private boolean checkActivityBelongsInStack(ActivityRecord r, ActivityStack stack) { - if (r.isHomeActivity()) { - return stack.isHomeStack(); - } else if (r.isRecentsActivity()) { - return stack.isRecentsStack(); - } else if (r.isAssistantActivity()) { - return stack.isAssistantStack(); - } - return true; - } - ActivityRecord findActivityLocked(Intent intent, ActivityInfo info, boolean compareIntentFilters) { for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { @@ -3126,6 +3057,16 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return null; } + boolean hasAwakeDisplay() { + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx); + if (!display.shouldSleep()) { + return true; + } + } + return false; + } + void goingToSleepLocked() { scheduleSleepTimeout(); if (!mGoingToSleep.isHeld()) { @@ -3138,7 +3079,16 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG); } } - checkReadyForSleepLocked(); + + applySleepTokensLocked(false /* applyToStacks */); + + checkReadyForSleepLocked(true /* allowDelay */); + } + + void prepareForShutdownLocked() { + for (int i = 0; i < mActivityDisplays.size(); i++) { + createSleepTokenLocked("shutdown", mActivityDisplays.keyAt(i)); + } } boolean shutdownLocked(int timeout) { @@ -3147,14 +3097,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D boolean timedout = false; final long endTime = System.currentTimeMillis() + timeout; while (true) { - boolean cantShutdown = false; - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; - for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { - cantShutdown |= stacks.get(stackNdx).checkReadyForSleepLocked(); - } - } - if (cantShutdown) { + if (!putStacksToSleepLocked(true /* allowDelay */, true /* shuttingDown */)) { long timeRemaining = endTime - System.currentTimeMillis(); if (timeRemaining > 0) { try { @@ -3172,8 +3115,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } // Force checkReadyForSleep to complete. - mSleepTimeout = true; - checkReadyForSleepLocked(); + checkReadyForSleepLocked(false /* allowDelay */); return timedout; } @@ -3183,69 +3125,72 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D if (mGoingToSleep.isHeld()) { mGoingToSleep.release(); } + } + + void applySleepTokensLocked(boolean applyToStacks) { for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + // Set the sleeping state of the display. + final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx); + final boolean displayShouldSleep = display.shouldSleep(); + if (displayShouldSleep == display.isSleeping()) { + continue; + } + display.setIsSleeping(displayShouldSleep); + + if (!applyToStacks) { + continue; + } + + // Set the sleeping state of the stacks on the display. + final ArrayList<ActivityStack> stacks = display.mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); - stack.awakeFromSleepingLocked(); - if (isFocusedStack(stack)) { - resumeFocusedStackTopActivityLocked(); + if (displayShouldSleep) { + stack.goToSleepIfPossible(false /* shuttingDown */); + } else { + stack.awakeFromSleepingLocked(); + if (isFocusedStack(stack)) { + resumeFocusedStackTopActivityLocked(); + } + } + } + + if (displayShouldSleep || mGoingToSleepActivities.isEmpty()) { + continue; + } + // The display is awake now, so clean up the going to sleep list. + for (Iterator<ActivityRecord> it = mGoingToSleepActivities.iterator(); it.hasNext(); ) { + final ActivityRecord r = it.next(); + if (r.getDisplayId() == display.mDisplayId) { + it.remove(); } } } - mGoingToSleepActivities.clear(); } void activitySleptLocked(ActivityRecord r) { mGoingToSleepActivities.remove(r); - checkReadyForSleepLocked(); + final ActivityStack s = r.getStack(); + if (s != null) { + s.checkReadyForSleep(); + } else { + checkReadyForSleepLocked(true); + } } - void checkReadyForSleepLocked() { + void checkReadyForSleepLocked(boolean allowDelay) { if (!mService.isSleepingOrShuttingDownLocked()) { // Do not care. return; } - if (!mSleepTimeout) { - boolean dontSleep = false; - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; - for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { - dontSleep |= stacks.get(stackNdx).checkReadyForSleepLocked(); - } - } - - if (mStoppingActivities.size() > 0) { - // Still need to tell some activities to stop; can't sleep yet. - if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to stop " - + mStoppingActivities.size() + " activities"); - scheduleIdleLocked(); - dontSleep = true; - } - - if (mGoingToSleepActivities.size() > 0) { - // Still need to tell some activities to sleep; can't sleep yet. - if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to sleep " - + mGoingToSleepActivities.size() + " activities"); - dontSleep = true; - } - - if (dontSleep) { - return; - } + if (!putStacksToSleepLocked(allowDelay, false /* shuttingDown */)) { + return; } // Send launch end powerhint before going sleep mService.mActivityStarter.sendPowerHintForLaunchEndIfNeeded(); - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; - for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { - stacks.get(stackNdx).goToSleep(); - } - } - removeSleepTimeouts(); if (mGoingToSleep.isHeld()) { @@ -3256,7 +3201,27 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } + // Tries to put all activity stacks to sleep. Returns true if all stacks were + // successfully put to sleep. + private boolean putStacksToSleepLocked(boolean allowDelay, boolean shuttingDown) { + boolean allSleep = true; + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + if (allowDelay) { + allSleep &= stacks.get(stackNdx).goToSleepIfPossible(shuttingDown); + } else { + stacks.get(stackNdx).goToSleep(); + } + } + } + return allSleep; + } + boolean reportResumedActivityLocked(ActivityRecord r) { + // A resumed activity cannot be stopping. remove from list + mStoppingActivities.remove(r); + final ActivityStack stack = r.getStack(); if (isFocusedStack(stack)) { mService.updateUsageStats(r, true); @@ -3286,7 +3251,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D final ActivityStack stack = task.getStack(); r.mLaunchTaskBehind = false; - task.setLastThumbnailLocked(r.screenshotActivityLocked()); mRecentTasks.addLocked(task); mService.mTaskChangeNotificationController.notifyTaskStackChanged(); r.setVisibility(false); @@ -3460,7 +3424,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D if (stack == null) { stack = mHomeStack; } - final boolean homeInFront = stack.isHomeStack(); + final boolean homeInFront = stack.isActivityTypeHome(); if (stack.isOnHomeDisplay()) { stack.moveToFront("switchUserOnHomeDisplay"); } else { @@ -3516,21 +3480,27 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D s.setVisibility(false); } } - if ((!waitingVisible || mService.isSleepingOrShuttingDownLocked()) && remove) { - if (!processPausingActivities && s.state == PAUSING) { - // Defer processing pausing activities in this iteration and reschedule - // a delayed idle to reprocess it again - removeTimeoutsForActivityLocked(idleActivity); - scheduleIdleTimeoutLocked(idleActivity); - continue; - } + if (remove) { + final ActivityStack stack = s.getStack(); + final boolean shouldSleepOrShutDown = stack != null + ? stack.shouldSleepOrShutDownActivities() + : mService.isSleepingOrShuttingDownLocked(); + if (!waitingVisible || shouldSleepOrShutDown) { + if (!processPausingActivities && s.state == PAUSING) { + // Defer processing pausing activities in this iteration and reschedule + // a delayed idle to reprocess it again + removeTimeoutsForActivityLocked(idleActivity); + scheduleIdleTimeoutLocked(idleActivity); + continue; + } - if (DEBUG_STATES) Slog.v(TAG, "Ready to stop: " + s); - if (stops == null) { - stops = new ArrayList<>(); + if (DEBUG_STATES) Slog.v(TAG, "Ready to stop: " + s); + if (stops == null) { + stops = new ArrayList<>(); + } + stops.add(s); + mStoppingActivities.remove(activityNdx); } - stops.add(s); - mStoppingActivities.remove(activityNdx); } } @@ -3568,27 +3538,14 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } - private String lockTaskModeToString() { - switch (mLockTaskModeState) { - case LOCK_TASK_MODE_LOCKED: - return "LOCKED"; - case LOCK_TASK_MODE_PINNED: - return "PINNED"; - case LOCK_TASK_MODE_NONE: - return "NONE"; - default: return "unknown=" + mLockTaskModeState; - } - } - public void dump(PrintWriter pw, String prefix) { pw.print(prefix); pw.print("mFocusedStack=" + mFocusedStack); pw.print(" mLastFocusedStack="); pw.println(mLastFocusedStack); - pw.print(prefix); pw.println("mSleepTimeout=" + mSleepTimeout); pw.print(prefix); pw.println("mCurTaskIdForUser=" + mCurTaskIdForUser); pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront); pw.print(prefix); pw.println("mStacks=" + mStacks); - pw.print(prefix); pw.print("mLockTaskModeState=" + lockTaskModeToString()); + // TODO: move this to LockTaskController final SparseArray<String[]> packages = mService.mLockTaskPackages; if (packages.size() > 0) { pw.print(prefix); pw.println("mLockTaskPackages (userId:packages)="); @@ -3604,8 +3561,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } - pw.println(" mLockTaskModeTasks" + mLockTaskModeTasks); mKeyguardController.dump(pw, prefix); + mService.mLockTaskController.dump(pw, prefix); } /** @@ -3673,23 +3630,14 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D ArrayList<ActivityStack> stacks = activityDisplay.mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); - StringBuilder stackHeader = new StringBuilder(128); - stackHeader.append(" Stack #"); - stackHeader.append(stack.mStackId); - stackHeader.append(":"); - stackHeader.append("\n"); - stackHeader.append(" mFullscreen=" + stack.mFullscreen); - stackHeader.append("\n"); - stackHeader.append(" mBounds=" + stack.mBounds); - - final boolean printedStackHeader = stack.dumpActivitiesLocked(fd, pw, dumpAll, - dumpClient, dumpPackage, needSep, stackHeader.toString()); - printed |= printedStackHeader; - if (!printedStackHeader) { - // Ensure we always dump the stack header even if there are no activities - pw.println(); - pw.println(stackHeader); - } + pw.println(); + pw.println(" Stack #" + stack.mStackId + ":"); + pw.println(" mFullscreen=" + stack.mFullscreen); + pw.println(" isSleeping=" + stack.shouldSleepActivities()); + pw.println(" mBounds=" + stack.mBounds); + + printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, + needSep); printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, false, dumpPackage, true, @@ -3731,16 +3679,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D " Activities waiting for another to become visible:", null); printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll, false, dumpPackage, true, " Activities waiting to sleep:", null); - printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll, - false, dumpPackage, true, " Activities waiting to sleep:", null); return printed; } static boolean dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list, String prefix, String label, boolean complete, boolean brief, boolean client, - String dumpPackage, boolean needNL, String header1, String header2) { - TaskRecord lastTask = null; + String dumpPackage, boolean needNL, String header, TaskRecord lastTask) { String innerPrefix = null; String[] args = null; boolean printed = false; @@ -3759,13 +3704,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D pw.println(""); needNL = false; } - if (header1 != null) { - pw.println(header1); - header1 = null; - } - if (header2 != null) { - pw.println(header2); - header2 = null; + if (header != null) { + pw.println(header); + header = null; } if (lastTask != r.getTask()) { lastTask = r.getTask(); @@ -3843,7 +3784,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } void removeSleepTimeouts() { - mSleepTimeout = false; mHandler.removeMessages(SLEEP_TIMEOUT_MSG); } @@ -3945,6 +3885,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D moveTasksToFullscreenStackLocked(stack.getStackId(), true /* onTop */); } } + + releaseSleepTokens(activityDisplay); + mActivityDisplays.remove(displayId); mWindowManager.onDisplayRemoved(displayId); } @@ -3955,12 +3898,60 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D synchronized (mService) { ActivityDisplay activityDisplay = mActivityDisplays.get(displayId); if (activityDisplay != null) { + // The window policy is responsible for stopping activities on the default display + if (displayId != Display.DEFAULT_DISPLAY) { + int displayState = activityDisplay.mDisplay.getState(); + if (displayState == Display.STATE_OFF && activityDisplay.mOffToken == null) { + activityDisplay.mOffToken = + mService.acquireSleepToken("Display-off", displayId); + } else if (displayState == Display.STATE_ON + && activityDisplay.mOffToken != null) { + activityDisplay.mOffToken.release(); + activityDisplay.mOffToken = null; + } + } // TODO: Update the bounds. } mWindowManager.onDisplayChanged(displayId); } } + SleepToken createSleepTokenLocked(String tag, int displayId) { + ActivityDisplay display = mActivityDisplays.get(displayId); + if (display == null) { + throw new IllegalArgumentException("Invalid display: " + displayId); + } + + final SleepTokenImpl token = new SleepTokenImpl(tag, displayId); + mSleepTokens.add(token); + display.mAllSleepTokens.add(token); + return token; + } + + private void removeSleepTokenLocked(SleepTokenImpl token) { + mSleepTokens.remove(token); + + ActivityDisplay display = mActivityDisplays.get(token.mDisplayId); + if (display != null) { + display.mAllSleepTokens.remove(token); + if (display.mAllSleepTokens.isEmpty()) { + mService.updateSleepIfNeededLocked(); + } + } + } + + private void releaseSleepTokens(ActivityDisplay display) { + if (display.mAllSleepTokens.isEmpty()) { + return; + } + for (SleepTokenImpl token : display.mAllSleepTokens) { + mSleepTokens.remove(token); + } + display.mAllSleepTokens.clear(); + + mService.updateSleepIfNeededLocked(); + } + private StackInfo getStackInfoLocked(ActivityStack stack) { final int displayId = stack.mDisplayId; final ActivityDisplay display = mActivityDisplays.get(displayId); @@ -4021,51 +4012,19 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return list; } - TaskRecord getLockedTaskLocked() { - final int top = mLockTaskModeTasks.size() - 1; - if (top >= 0) { - return mLockTaskModeTasks.get(top); - } - return null; - } - - boolean isLockedTask(TaskRecord task) { - return mLockTaskModeTasks.contains(task); - } - - boolean isLastLockedTask(TaskRecord task) { - return mLockTaskModeTasks.size() == 1 && mLockTaskModeTasks.contains(task); - } - - void removeLockedTaskLocked(final TaskRecord task) { - if (!mLockTaskModeTasks.remove(task)) { - return; - } - if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "removeLockedTaskLocked: removed " + task); - if (mLockTaskModeTasks.isEmpty()) { - // Last one. - if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "removeLockedTask: task=" + task + - " last task, reverting locktask mode. Callers=" + Debug.getCallers(3)); - final Message lockTaskMsg = Message.obtain(); - lockTaskMsg.arg1 = task.userId; - lockTaskMsg.what = LOCK_TASK_END_MSG; - mHandler.sendMessage(lockTaskMsg); - } - } - void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredStackId, int preferredDisplayId, int actualStackId) { handleNonResizableTaskIfNeeded(task, preferredStackId, preferredDisplayId, actualStackId, false /* forceNonResizable */); } - private void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredStackId, + void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredStackId, int preferredDisplayId, int actualStackId, boolean forceNonResizable) { final boolean isSecondaryDisplayPreferred = (preferredDisplayId != DEFAULT_DISPLAY && preferredDisplayId != INVALID_DISPLAY) || StackId.isDynamicStack(preferredStackId); if (((!isStackDockedInEffect(actualStackId) && preferredStackId != DOCKED_STACK_ID) - && !isSecondaryDisplayPreferred) || task.isHomeTask()) { + && !isSecondaryDisplayPreferred) || task.isActivityTypeHome()) { return; } @@ -4118,157 +4077,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } - void showLockTaskToast() { - if (mLockTaskNotify != null) { - mLockTaskNotify.showToast(mLockTaskModeState); - } - } - - void showLockTaskEscapeMessageLocked(TaskRecord task) { - if (mLockTaskModeTasks.contains(task)) { - mHandler.sendEmptyMessage(SHOW_LOCK_TASK_ESCAPE_MESSAGE_MSG); - } - } - - void setLockTaskModeLocked(TaskRecord task, int lockTaskModeState, String reason, - boolean andResume) { - if (task == null) { - // Take out of lock task mode if necessary - final TaskRecord lockedTask = getLockedTaskLocked(); - if (lockedTask != null) { - removeLockedTaskLocked(lockedTask); - if (!mLockTaskModeTasks.isEmpty()) { - // There are locked tasks remaining, can only finish this task, not unlock it. - if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, - "setLockTaskModeLocked: Tasks remaining, can't unlock"); - lockedTask.performClearTaskLocked(); - resumeFocusedStackTopActivityLocked(); - return; - } - } - if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, - "setLockTaskModeLocked: No tasks to unlock. Callers=" + Debug.getCallers(4)); - return; - } - - // Should have already been checked, but do it again. - if (task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) { - if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, - "setLockTaskModeLocked: Can't lock due to auth"); - return; - } - if (isLockTaskModeViolation(task)) { - Slog.e(TAG_LOCKTASK, "setLockTaskMode: Attempt to start an unauthorized lock task."); - return; - } - - if (mLockTaskModeTasks.isEmpty()) { - // First locktask. - final Message lockTaskMsg = Message.obtain(); - lockTaskMsg.obj = task.intent.getComponent().getPackageName(); - lockTaskMsg.arg1 = task.userId; - lockTaskMsg.what = LOCK_TASK_START_MSG; - lockTaskMsg.arg2 = lockTaskModeState; - mHandler.sendMessage(lockTaskMsg); - } - // Add it or move it to the top. - if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "setLockTaskModeLocked: Locking to " + task + - " Callers=" + Debug.getCallers(4)); - mLockTaskModeTasks.remove(task); - mLockTaskModeTasks.add(task); - - if (task.mLockTaskUid == -1) { - task.mLockTaskUid = task.effectiveUid; - } - - if (andResume) { - findTaskToMoveToFrontLocked(task, 0, null, reason, - lockTaskModeState != LOCK_TASK_MODE_NONE); - resumeFocusedStackTopActivityLocked(); - mWindowManager.executeAppTransition(); - } else if (lockTaskModeState != LOCK_TASK_MODE_NONE) { - handleNonResizableTaskIfNeeded(task, INVALID_STACK_ID, DEFAULT_DISPLAY, - task.getStackId(), true /* forceNonResizable */); - } - } - - boolean isLockTaskModeViolation(TaskRecord task) { - return isLockTaskModeViolation(task, false); - } - - boolean isLockTaskModeViolation(TaskRecord task, boolean isNewClearTask) { - if (getLockedTaskLocked() == task && !isNewClearTask) { - return false; - } - final int lockTaskAuth = task.mLockTaskAuth; - switch (lockTaskAuth) { - case LOCK_TASK_AUTH_DONT_LOCK: - return !mLockTaskModeTasks.isEmpty(); - case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: - case LOCK_TASK_AUTH_LAUNCHABLE: - case LOCK_TASK_AUTH_WHITELISTED: - return false; - case LOCK_TASK_AUTH_PINNABLE: - // Pinnable tasks can't be launched on top of locktask tasks. - return !mLockTaskModeTasks.isEmpty(); - default: - Slog.w(TAG, "isLockTaskModeViolation: invalid lockTaskAuth value=" + lockTaskAuth); - return true; - } - } - - void onLockTaskPackagesUpdatedLocked() { - boolean didSomething = false; - for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx >= 0; --taskNdx) { - final TaskRecord lockedTask = mLockTaskModeTasks.get(taskNdx); - final boolean wasWhitelisted = - (lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) || - (lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED); - lockedTask.setLockTaskAuth(); - final boolean isWhitelisted = - (lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) || - (lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED); - if (wasWhitelisted && !isWhitelisted) { - // Lost whitelisting authorization. End it now. - if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "onLockTaskPackagesUpdated: removing " + - lockedTask + " mLockTaskAuth=" + lockedTask.lockTaskAuthToString()); - removeLockedTaskLocked(lockedTask); - lockedTask.performClearTaskLocked(); - didSomething = true; - } - } - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; - for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { - final ActivityStack stack = stacks.get(stackNdx); - stack.onLockTaskPackagesUpdatedLocked(); - } - } - final ActivityRecord r = topRunningActivityLocked(); - final TaskRecord task = r != null ? r.getTask() : null; - if (mLockTaskModeTasks.isEmpty() && task != null - && task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) { - // This task must have just been authorized. - if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, - "onLockTaskPackagesUpdated: starting new locktask task=" + task); - setLockTaskModeLocked(task, ActivityManager.LOCK_TASK_MODE_LOCKED, "package updated", - false); - didSomething = true; - } - if (didSomething) { - resumeFocusedStackTopActivityLocked(); - } - } - - int getLockTaskModeState() { - return mLockTaskModeState; - } - void activityRelaunchedLocked(IBinder token) { mWindowManager.notifyAppRelaunchingFinished(token); - if (mService.isSleepingOrShuttingDownLocked()) { - final ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r != null) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r != null) { + if (r.getStack().shouldSleepOrShutDownActivities()) { r.setSleeping(true, true); } } @@ -4308,31 +4121,29 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return; } - scheduleUpdatePictureInPictureModeIfNeeded(task, stack.mBounds, false /* immediate */); + scheduleUpdatePictureInPictureModeIfNeeded(task, stack.mBounds); } - void scheduleUpdatePictureInPictureModeIfNeeded(TaskRecord task, Rect targetStackBounds, - boolean immediate) { - - if (immediate) { - mHandler.removeMessages(REPORT_PIP_MODE_CHANGED_MSG); - for (int i = task.mActivities.size() - 1; i >= 0; i--) { - final ActivityRecord r = task.mActivities.get(i); - if (r.app != null && r.app.thread != null) { - r.updatePictureInPictureMode(targetStackBounds); - } - } - } else { - for (int i = task.mActivities.size() - 1; i >= 0; i--) { - final ActivityRecord r = task.mActivities.get(i); - if (r.app != null && r.app.thread != null) { - mPipModeChangedActivities.add(r); - } + void scheduleUpdatePictureInPictureModeIfNeeded(TaskRecord task, Rect targetStackBounds) { + for (int i = task.mActivities.size() - 1; i >= 0; i--) { + final ActivityRecord r = task.mActivities.get(i); + if (r.app != null && r.app.thread != null) { + mPipModeChangedActivities.add(r); } - mPipModeChangedTargetStackBounds = targetStackBounds; + } + mPipModeChangedTargetStackBounds = targetStackBounds; + + if (!mHandler.hasMessages(REPORT_PIP_MODE_CHANGED_MSG)) { + mHandler.sendEmptyMessage(REPORT_PIP_MODE_CHANGED_MSG); + } + } - if (!mHandler.hasMessages(REPORT_PIP_MODE_CHANGED_MSG)) { - mHandler.sendEmptyMessage(REPORT_PIP_MODE_CHANGED_MSG); + void updatePictureInPictureMode(TaskRecord task, Rect targetStackBounds, boolean forceUpdate) { + mHandler.removeMessages(REPORT_PIP_MODE_CHANGED_MSG); + for (int i = task.mActivities.size() - 1; i >= 0; i--) { + final ActivityRecord r = task.mActivities.get(i); + if (r.app != null && r.app.thread != null) { + r.updatePictureInPictureMode(targetStackBounds, forceUpdate); } } } @@ -4394,7 +4205,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D synchronized (mService) { for (int i = mPipModeChangedActivities.size() - 1; i >= 0; i--) { final ActivityRecord r = mPipModeChangedActivities.remove(i); - r.updatePictureInPictureMode(mPipModeChangedTargetStackBounds); + r.updatePictureInPictureMode(mPipModeChangedTargetStackBounds, + false /* forceUpdate */); } } } break; @@ -4420,8 +4232,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D synchronized (mService) { if (mService.isSleepingOrShuttingDownLocked()) { Slog.w(TAG, "Sleep timeout! Sleeping now."); - mSleepTimeout = true; - checkReadyForSleepLocked(); + checkReadyForSleepLocked(false /* allowDelay */); } } } break; @@ -4446,78 +4257,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D case HANDLE_DISPLAY_REMOVED: { handleDisplayRemoved(msg.arg1); } break; - case LOCK_TASK_START_MSG: { - // When lock task starts, we disable the status bars. - try { - if (mLockTaskNotify == null) { - mLockTaskNotify = new LockTaskNotify(mService.mContext); - } - mLockTaskNotify.show(true); - mLockTaskModeState = msg.arg2; - if (getStatusBarService() != null) { - int flags = 0; - if (mLockTaskModeState == LOCK_TASK_MODE_LOCKED) { - flags = StatusBarManager.DISABLE_MASK - & (~StatusBarManager.DISABLE_BACK); - } else if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) { - flags = StatusBarManager.DISABLE_MASK - & (~StatusBarManager.DISABLE_BACK) - & (~StatusBarManager.DISABLE_HOME) - & (~StatusBarManager.DISABLE_RECENT); - } - getStatusBarService().disable(flags, mToken, - mService.mContext.getPackageName()); - } - mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG); - if (getDevicePolicyManager() != null) { - getDevicePolicyManager().notifyLockTaskModeChanged(true, - (String)msg.obj, msg.arg1); - } - } catch (RemoteException ex) { - throw new RuntimeException(ex); - } - } break; - case LOCK_TASK_END_MSG: { - // When lock task ends, we enable the status bars. - try { - if (getStatusBarService() != null) { - getStatusBarService().disable(StatusBarManager.DISABLE_NONE, mToken, - mService.mContext.getPackageName()); - } - mWindowManager.reenableKeyguard(mToken); - if (getDevicePolicyManager() != null) { - getDevicePolicyManager().notifyLockTaskModeChanged(false, null, - msg.arg1); - } - if (mLockTaskNotify == null) { - mLockTaskNotify = new LockTaskNotify(mService.mContext); - } - mLockTaskNotify.show(false); - try { - boolean shouldLockKeyguard = Settings.Secure.getInt( - mService.mContext.getContentResolver(), - Settings.Secure.LOCK_TO_APP_EXIT_LOCKED) != 0; - if (mLockTaskModeState == LOCK_TASK_MODE_PINNED && shouldLockKeyguard) { - mWindowManager.lockNow(null); - mWindowManager.dismissKeyguard(null /* callback */); - new LockPatternUtils(mService.mContext) - .requireCredentialEntry(UserHandle.USER_ALL); - } - } catch (SettingNotFoundException e) { - // No setting, don't lock. - } - } catch (RemoteException ex) { - throw new RuntimeException(ex); - } finally { - mLockTaskModeState = LOCK_TASK_MODE_NONE; - } - } break; - case SHOW_LOCK_TASK_ESCAPE_MESSAGE_MSG: { - if (mLockTaskNotify == null) { - mLockTaskNotify = new LockTaskNotify(mService.mContext); - } - mLockTaskNotify.showToast(LOCK_TASK_MODE_PINNED); - } break; case LAUNCH_TASK_BEHIND_COMPLETE: { synchronized (mService) { ActivityRecord r = ActivityRecord.forTokenLocked((IBinder) msg.obj); @@ -4546,6 +4285,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D /** Array of all UIDs that are present on the display. */ private IntArray mDisplayAccessUIDs = new IntArray(); + /** All tokens used to put activities on this stack to sleep (including mOffToken) */ + final ArrayList<SleepTokenImpl> mAllSleepTokens = new ArrayList<>(); + /** The token acquired by ActivityStackSupervisor to put stacks on the display to sleep */ + SleepToken mOffToken; + + private boolean mSleeping; + @VisibleForTesting ActivityDisplay() { mActivityDisplays.put(mDisplayId, this); @@ -4570,12 +4316,14 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D if (DEBUG_STACK) Slog.v(TAG_STACK, "attachStack: attaching " + stack + " to displayId=" + mDisplayId + " position=" + position); mStacks.add(position, stack); + mService.updateSleepIfNeededLocked(); } void detachStack(ActivityStack stack) { if (DEBUG_STACK) Slog.v(TAG_STACK, "detachStack: detaching " + stack + " from displayId=" + mDisplayId); mStacks.remove(stack); + mService.updateSleepIfNeededLocked(); } @Override @@ -4623,6 +4371,19 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D boolean shouldDestroyContentOnRemove() { return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT; } + + boolean shouldSleep() { + return (mStacks.isEmpty() || !mAllSleepTokens.isEmpty()) + && (mService.mRunningVoice == null); + } + + boolean isSleeping() { + return mSleeping; + } + + void setIsSleeping(boolean asleep) { + mSleeping = asleep; + } } ActivityStack findStackBehind(ActivityStack stack) { @@ -4804,4 +4565,30 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mResult.dump(pw, prefix); } } + + private final class SleepTokenImpl extends SleepToken { + private final String mTag; + private final long mAcquireTime; + private final int mDisplayId; + + public SleepTokenImpl(String tag, int displayId) { + mTag = tag; + mDisplayId = displayId; + mAcquireTime = SystemClock.uptimeMillis(); + } + + @Override + public void release() { + synchronized (mService) { + removeSleepTokenLocked(this); + } + } + + @Override + public String toString() { + return "{\"" + mTag + "\", display " + mDisplayId + + ", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}"; + } + } + } diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 761f9eef65fd..16abcfb620d9 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -36,6 +36,9 @@ import static android.app.ActivityManager.StackId.INVALID_STACK_ID; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static android.app.ActivityManager.StackId.RECENTS_STACK_ID; import static android.app.ActivityManager.StackId.isDynamicStack; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; @@ -72,9 +75,6 @@ import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAV import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.ActivityManagerService.ANIMATE; -import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE; -import static com.android.server.am.ActivityRecord.ASSISTANT_ACTIVITY_TYPE; -import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE; import static com.android.server.am.ActivityStack.ActivityState.RESUMED; import static com.android.server.am.ActivityStack.STACK_INVISIBLE; import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED; @@ -1033,10 +1033,9 @@ class ActivityStarter { // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but // still needs to be a lock task mode violation since the task gets cleared out and // the device would otherwise leave the locked task. - if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(), + if (mService.mLockTaskController.isLockTaskModeViolation(reusedActivity.getTask(), (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) { - mSupervisor.showLockTaskToast(); Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode"); return START_RETURN_LOCK_TASK_MODE_VIOLATION; } @@ -1508,7 +1507,7 @@ class ActivityStarter { // There can be one and only one instance of single instance activity in the // history, and it is always in its own unique task, so we do a special search. intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, - mStartActivity.isHomeActivity()); + mStartActivity.isActivityTypeHome()); } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) { // For the launch adjacent case we only want to put the activity in an existing // task if the activity already exists in the history. @@ -1670,21 +1669,21 @@ class ActivityStarter { if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) { // Caller wants to appear on home activity. - task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); + task.setTaskToReturnTo(ACTIVITY_TYPE_HOME); return; - } else if (focusedStack == null || focusedStack.isHomeStack()) { + } else if (focusedStack == null || focusedStack.isActivityTypeHome()) { // Task will be launched over the home stack, so return home. - task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); + task.setTaskToReturnTo(ACTIVITY_TYPE_HOME); return; } else if (focusedStack != null && focusedStack != task.getStack() && - focusedStack.isAssistantStack()) { + focusedStack.isActivityTypeAssistant()) { // Task was launched over the assistant stack, so return there - task.setTaskToReturnTo(ASSISTANT_ACTIVITY_TYPE); + task.setTaskToReturnTo(ACTIVITY_TYPE_ASSISTANT); return; } // Else we are coming from an application stack so return to an application. - task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE); + task.setTaskToReturnTo(ACTIVITY_TYPE_STANDARD); } private void setTaskFromIntentActivity(ActivityRecord intentActivity) { @@ -1792,7 +1791,7 @@ class ActivityStarter { mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info, mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession, - mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType); + mVoiceInteractor, !mLaunchTaskBehind /* toTop */); addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask"); if (mLaunchBounds != null) { final int stackId = mTargetStack.mStackId; @@ -1813,7 +1812,7 @@ class ActivityStarter { mStartActivity.setTaskToAffiliateWith(taskToAffiliate); } - if (mSupervisor.isLockTaskModeViolation(mStartActivity.getTask())) { + if (mService.mLockTaskController.isLockTaskModeViolation(mStartActivity.getTask())) { Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity); return START_RETURN_LOCK_TASK_MODE_VIOLATION; } @@ -1832,7 +1831,7 @@ class ActivityStarter { } private int setTaskFromSourceRecord() { - if (mSupervisor.isLockTaskModeViolation(mSourceRecord.getTask())) { + if (mService.mLockTaskController.isLockTaskModeViolation(mSourceRecord.getTask())) { Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity); return START_RETURN_LOCK_TASK_MODE_VIOLATION; } @@ -1926,7 +1925,7 @@ class ActivityStarter { private int setTaskFromInTask() { // The caller is asking that the new activity be started in an explicit // task it has provided to us. - if (mSupervisor.isLockTaskModeViolation(mInTask)) { + if (mService.mLockTaskController.isLockTaskModeViolation(mInTask)) { Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity); return START_RETURN_LOCK_TASK_MODE_VIOLATION; } @@ -1996,7 +1995,7 @@ class ActivityStarter { final ActivityRecord prev = mTargetStack.topActivity(); final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord( mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info, - mIntent, null, null, true, mStartActivity.mActivityType); + mIntent, null, null, true); addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask"); mTargetStack.positionChildWindowContainerAtTop(task); if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity @@ -2125,7 +2124,7 @@ class ActivityStarter { canUseFocusedStack = true; break; case ASSISTANT_STACK_ID: - canUseFocusedStack = r.isAssistantActivity(); + canUseFocusedStack = r.isActivityTypeAssistant(); break; case DOCKED_STACK_ID: // Any activity which supports split screen can go in the docked stack. @@ -2156,13 +2155,13 @@ class ActivityStarter { // If the activity is of a specific type, return the associated stack, creating it if // necessary - if (r.isHomeActivity()) { + if (r.isActivityTypeHome()) { return mSupervisor.mHomeStack; } - if (r.isRecentsActivity()) { + if (r.isActivityTypeRecents()) { return mSupervisor.getStack(RECENTS_STACK_ID, CREATE_IF_NEEDED, ON_TOP); } - if (r.isAssistantActivity()) { + if (r.isActivityTypeAssistant()) { return mSupervisor.getStack(ASSISTANT_STACK_ID, CREATE_IF_NEEDED, ON_TOP); } @@ -2255,9 +2254,9 @@ class ActivityStarter { case PINNED_STACK_ID: return r.supportsPictureInPicture(); case RECENTS_STACK_ID: - return r.isRecentsActivity(); + return r.isActivityTypeRecents(); case ASSISTANT_STACK_ID: - return r.isAssistantActivity(); + return r.isActivityTypeAssistant(); default: if (StackId.isDynamicStack(stackId)) { return r.canBeLaunchedOnDisplay(displayId); diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index fc03db1203bd..d1424c8d43f2 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -55,7 +55,6 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.List; import java.util.Set; import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST; @@ -676,7 +675,7 @@ class AppErrors { && (mService.mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); - if (r.isHomeActivity()) { + if (r.isActivityTypeHome()) { Log.i(TAG, "Clearing package preferred activities from " + r.packageName); try { ActivityThread.getPackageManager() diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java index 5ff04798110f..5fac397c428f 100644 --- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java @@ -38,6 +38,7 @@ import com.android.internal.os.BatteryStatsImpl; import libcore.util.EmptyArray; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -116,6 +117,10 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { } public synchronized Future<?> scheduleWrite() { + if (mExecutorService.isShutdown()) { + return CompletableFuture.failedFuture(new IllegalStateException("worker shutdown")); + } + scheduleSyncLocked("write", UPDATE_ALL); // Since we use a single threaded executor, we can assume the next scheduled task's // Future finishes after the sync. @@ -127,7 +132,9 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { * within the task, never wait on the resulting Future. This will result in a deadlock. */ public synchronized void scheduleRunnable(Runnable runnable) { - mExecutorService.submit(runnable); + if (!mExecutorService.isShutdown()) { + mExecutorService.submit(runnable); + } } public void shutdown() { @@ -135,6 +142,10 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { } private Future<?> scheduleSyncLocked(String reason, int flags) { + if (mExecutorService.isShutdown()) { + return CompletableFuture.failedFuture(new IllegalStateException("worker shutdown")); + } + if (mCurrentFuture == null) { mUpdateFlags = flags; mCurrentReason = reason; diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java index 58e71df3ba57..cea80c8d0e9d 100644 --- a/services/core/java/com/android/server/am/KeyguardController.java +++ b/services/core/java/com/android/server/am/KeyguardController.java @@ -18,6 +18,7 @@ package com.android.server.am; import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; +import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS; import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE; import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER; @@ -32,6 +33,7 @@ import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_OCCLUDE; import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_UNOCCLUDE; import static com.android.server.wm.AppTransition.TRANSIT_UNSET; +import android.app.ActivityManagerInternal.SleepToken; import android.os.IBinder; import android.os.RemoteException; import android.os.Trace; @@ -63,6 +65,7 @@ class KeyguardController { private ActivityRecord mDismissingKeyguardActivity; private int mBeforeUnoccludeTransit; private int mVisibilityTransactionDepth; + private SleepToken mSleepToken; KeyguardController(ActivityManagerService service, ActivityStackSupervisor stackSupervisor) { @@ -102,7 +105,7 @@ class KeyguardController { mDismissalRequested = false; } mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); - mService.updateSleepIfNeededLocked(); + updateKeyguardSleepToken(); } /** @@ -122,7 +125,7 @@ class KeyguardController { mWindowManager.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY, false /* alwaysKeepCurrent */, convertTransitFlags(flags), false /* forceOverride */); - mService.updateSleepIfNeededLocked(); + updateKeyguardSleepToken(); // Some stack visibility might change (e.g. docked stack) mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); @@ -263,7 +266,7 @@ class KeyguardController { try { mWindowManager.prepareAppTransition(resolveOccludeTransit(), false /* alwaysKeepCurrent */, 0 /* flags */, true /* forceOverride */); - mService.updateSleepIfNeededLocked(); + updateKeyguardSleepToken(); mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); mWindowManager.executeAppTransition(); } finally { @@ -333,6 +336,15 @@ class KeyguardController { } } + private void updateKeyguardSleepToken() { + if (mSleepToken == null && isKeyguardShowing()) { + mSleepToken = mService.acquireSleepToken("Keyguard", DEFAULT_DISPLAY); + } else if (mSleepToken != null && !isKeyguardShowing()) { + mSleepToken.release(); + mSleepToken = null; + } + } + void dump(PrintWriter pw, String prefix) { pw.println(prefix + "KeyguardController:"); pw.println(prefix + " mKeyguardShowing=" + mKeyguardShowing); diff --git a/services/core/java/com/android/server/am/LockTaskController.java b/services/core/java/com/android/server/am/LockTaskController.java new file mode 100644 index 000000000000..d8706bcc5e35 --- /dev/null +++ b/services/core/java/com/android/server/am/LockTaskController.java @@ -0,0 +1,574 @@ +/* + * Copyright 2017, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.am; + +import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED; +import static android.app.ActivityManager.LOCK_TASK_MODE_NONE; +import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED; +import static android.app.ActivityManager.StackId.INVALID_STACK_ID; +import static android.app.StatusBarManager.DISABLE_BACK; +import static android.app.StatusBarManager.DISABLE_HOME; +import static android.app.StatusBarManager.DISABLE_MASK; +import static android.app.StatusBarManager.DISABLE_NONE; +import static android.app.StatusBarManager.DISABLE_RECENT; +import static android.content.Context.DEVICE_POLICY_SERVICE; +import static android.content.Context.STATUS_BAR_SERVICE; +import static android.os.UserHandle.USER_ALL; +import static android.os.UserHandle.USER_CURRENT; +import static android.provider.Settings.Secure.LOCK_TO_APP_EXIT_LOCKED; +import static android.view.Display.DEFAULT_DISPLAY; +import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK; +import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK; +import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; +import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK; +import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE; +import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV; +import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE; +import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.Activity; +import android.app.ActivityManager; +import android.app.admin.IDevicePolicyManager; +import android.content.Context; +import android.os.Binder; +import android.os.Debug; +import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.provider.Settings; +import android.util.Slog; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.statusbar.IStatusBarService; +import com.android.internal.widget.LockPatternUtils; +import com.android.server.LocalServices; +import com.android.server.statusbar.StatusBarManagerInternal; +import com.android.server.wm.WindowManagerService; + +import java.io.PrintWriter; +import java.util.ArrayList; + +/** + * Helper class that deals with all things related to task locking. This includes the screen pinning + * mode that can be launched via System UI as well as the fully locked mode that can be achieved + * on fully managed devices. + * + * Note: All methods in this class should only be called with the ActivityManagerService lock held. + * + * @see Activity#startLockTask() + * @see Activity#stopLockTask() + */ +public class LockTaskController { + private static final String TAG = TAG_WITH_CLASS_NAME ? "LockTaskController" : TAG_AM; + private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK; + + @VisibleForTesting + static final int STATUS_BAR_MASK_LOCKED = DISABLE_MASK + & (~DISABLE_BACK); + @VisibleForTesting + static final int STATUS_BAR_MASK_PINNED = DISABLE_MASK + & (~DISABLE_BACK) + & (~DISABLE_HOME) + & (~DISABLE_RECENT); + + /** Tag used for disabling of keyguard */ + private static final String LOCK_TASK_TAG = "Lock-to-App"; + + private final IBinder mToken = new Binder(); + private final ActivityStackSupervisor mSupervisor; + private final Context mContext; + + // The following system services cannot be final, because they do not exist when this class + // is instantiated during device boot + @VisibleForTesting + IStatusBarService mStatusBarService; + @VisibleForTesting + IDevicePolicyManager mDevicePolicyManager; + @VisibleForTesting + WindowManagerService mWindowManager; + @VisibleForTesting + LockPatternUtils mLockPatternUtils; + + /** + * Helper that is responsible for showing the right toast when a disallowed activity operation + * occurred. In pinned mode, we show instructions on how to break out of this mode, whilst in + * fully locked mode we only show that unlocking is blocked. + */ + @VisibleForTesting + LockTaskNotify mLockTaskNotify; + + /** + * The chain of tasks in lockTask mode. The current frontmost task is at the top, and tasks + * may be finished until there is only one entry left. If this is empty the system is not + * in lockTask mode. + */ + private final ArrayList<TaskRecord> mLockTaskModeTasks = new ArrayList<>(); + + /** + * Store the current lock task mode. Possible values: + * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED}, + * {@link ActivityManager#LOCK_TASK_MODE_PINNED} + */ + private int mLockTaskModeState; + + /** + * This is ActivityStackSupervisor's Handler. + */ + private final Handler mHandler; + + LockTaskController(Context context, ActivityStackSupervisor supervisor, + Handler handler) { + mContext = context; + mSupervisor = supervisor; + mHandler = handler; + } + + /** + * Set the window manager instance used in this class. This is necessary, because the window + * manager does not exist during instantiation of this class. + */ + void setWindowManager(WindowManagerService windowManager) { + mWindowManager = windowManager; + } + + /** + * @return the current lock task state. This can be any of + * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED}, + * {@link ActivityManager#LOCK_TASK_MODE_PINNED}. + */ + int getLockTaskModeState() { + return mLockTaskModeState; + } + + /** + * @return whether the given task can be moved to the back of the stack. Locked tasks cannot be + * moved to the back of the stack. + */ + boolean checkLockedTask(TaskRecord task) { + if (mLockTaskModeTasks.contains(task)) { + showLockTaskToast(); + return true; + } + return false; + } + + /** + * @return whether the given activity is blocked from finishing, because it is the root activity + * of the last locked task and finishing it would mean that lock task mode is ended illegally. + */ + boolean activityBlockedFromFinish(ActivityRecord activity) { + TaskRecord task = activity.getTask(); + if (activity == task.getRootActivity() + && task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV + && mLockTaskModeTasks.size() == 1 + && mLockTaskModeTasks.contains(task)) { + Slog.i(TAG, "Not finishing task in lock task mode"); + showLockTaskToast(); + return true; + } + return false; + } + + /** + * @return whether the requested task is allowed to be launched. + */ + boolean isLockTaskModeViolation(TaskRecord task) { + return isLockTaskModeViolation(task, false); + } + + /** + * @param isNewClearTask whether the task would be cleared as part of the operation. + * @return whether the requested task is allowed to be launched. + */ + boolean isLockTaskModeViolation(TaskRecord task, boolean isNewClearTask) { + if (isLockTaskModeViolationInternal(task, isNewClearTask)) { + showLockTaskToast(); + return true; + } + return false; + } + + private boolean isLockTaskModeViolationInternal(TaskRecord task, boolean isNewClearTask) { + // TODO: Double check what's going on here. If the task is already in lock task mode, it's + // likely whitelisted, so will return false below. + if (getLockedTask() == task && !isNewClearTask) { + // If the task is already at the top and won't be cleared, then allow the operation + return false; + } + final int lockTaskAuth = task.mLockTaskAuth; + switch (lockTaskAuth) { + case LOCK_TASK_AUTH_DONT_LOCK: + return !mLockTaskModeTasks.isEmpty(); + case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: + case LOCK_TASK_AUTH_LAUNCHABLE: + case LOCK_TASK_AUTH_WHITELISTED: + return false; + case LOCK_TASK_AUTH_PINNABLE: + // Pinnable tasks can't be launched on top of locktask tasks. + return !mLockTaskModeTasks.isEmpty(); + default: + Slog.w(TAG, "isLockTaskModeViolation: invalid lockTaskAuth value=" + lockTaskAuth); + return true; + } + } + + /** + * Stop the current lock task mode. + * + * @param isSystemInitiated indicates whether this request was initiated by the system via + * {@link ActivityManagerService#stopSystemLockTaskMode()}. + * @param callingUid the caller that requested the end of lock task mode. + * @throws SecurityException if the caller is not authorized to stop the lock task mode, i.e. if + * they differ from the one that launched lock task mode. + */ + void stopLockTaskMode(boolean isSystemInitiated, int callingUid) { + final TaskRecord lockTask = getLockedTask(); + if (lockTask == null || mLockTaskModeState == LOCK_TASK_MODE_NONE) { + // Our work here is done. + return; + } + + if (isSystemInitiated && mLockTaskModeState == LOCK_TASK_MODE_LOCKED) { + // As system can only start app pinning, we also only let it unlock in this mode. + showLockTaskToast(); + return; + } + + // Ensure the same caller for startLockTaskMode and stopLockTaskMode. + // It is possible lockTaskMode was started by the system process because + // android:lockTaskMode is set to a locking value in the application manifest + // instead of the app calling startLockTaskMode. In this case + // {@link TaskRecord.mLockTaskUid} will be 0, so we compare the callingUid to the + // {@link TaskRecord.effectiveUid} instead. Also caller with + // {@link MANAGE_ACTIVITY_STACKS} can stop any lock task. + if (!isSystemInitiated && callingUid != lockTask.mLockTaskUid + && (lockTask.mLockTaskUid != 0 || callingUid != lockTask.effectiveUid)) { + throw new SecurityException("Invalid uid, expected " + lockTask.mLockTaskUid + + " callingUid=" + callingUid + " effectiveUid=" + lockTask.effectiveUid); + } + + clearLockTaskMode("stopLockTask"); + } + + /** + * Remove the given task from the locked task list. If this was the last task in the list, + * lock task mode is stopped. + */ + void removeLockedTask(final TaskRecord task) { + if (!mLockTaskModeTasks.remove(task)) { + return; + } + if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "removeLockedTask: removed " + task); + if (mLockTaskModeTasks.isEmpty()) { + // Last one. + if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "removeLockedTask: task=" + task + + " last task, reverting locktask mode. Callers=" + Debug.getCallers(3)); + mHandler.post(() -> performStopLockTask(task.userId)); + } + } + + /** + * Remove the topmost task from the locked task list. If this is the last task in the list, it + * will result in the end of locked task mode. + */ + void clearLockTaskMode(String reason) { + // Take out of lock task mode if necessary + final TaskRecord lockedTask = getLockedTask(); + if (lockedTask != null) { + removeLockedTask(lockedTask); + if (!mLockTaskModeTasks.isEmpty()) { + // There are locked tasks remaining, can only finish this task, not unlock it. + if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, + "setLockTaskMode: Tasks remaining, can't unlock"); + lockedTask.performClearTaskLocked(); + mSupervisor.resumeFocusedStackTopActivityLocked(); + return; + } + } + if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, + "setLockTaskMode: No tasks to unlock. Callers=" + Debug.getCallers(4)); + } + + // This method should only be called on the handler thread + private void performStopLockTask(int userId) { + // When lock task ends, we enable the status bars. + try { + if (getStatusBarService() != null) { + getStatusBarService().disable(DISABLE_NONE, mToken, + mContext.getPackageName()); + } + mWindowManager.reenableKeyguard(mToken); + if (getDevicePolicyManager() != null) { + getDevicePolicyManager().notifyLockTaskModeChanged(false, null, userId); + } + getLockTaskNotify().show(false); + try { + boolean shouldLockKeyguard = Settings.Secure.getIntForUser( + mContext.getContentResolver(), + LOCK_TO_APP_EXIT_LOCKED, + USER_CURRENT) != 0; + if (mLockTaskModeState == LOCK_TASK_MODE_PINNED && shouldLockKeyguard) { + mWindowManager.lockNow(null); + mWindowManager.dismissKeyguard(null /* callback */); + getLockPatternUtils().requireCredentialEntry(USER_ALL); + } + } catch (Settings.SettingNotFoundException e) { + // No setting, don't lock. + } + } catch (RemoteException ex) { + throw new RuntimeException(ex); + } finally { + mLockTaskModeState = LOCK_TASK_MODE_NONE; + } + } + + /** + * Show the lock task violation toast. + */ + void showLockTaskToast() { + mHandler.post(() -> getLockTaskNotify().showToast(mLockTaskModeState)); + } + + // Starting lock task + + /** + * Method to start lock task mode on a given task. + * + * @param task the task that should be locked. + * @param isSystemInitiated indicates whether this request was initiated by the system via + * {@link ActivityManagerService#startSystemLockTaskMode(int)}. + * @param callingUid the caller that requested the launch of lock task mode. + */ + void startLockTaskMode(@NonNull TaskRecord task, boolean isSystemInitiated, + int callingUid) { + if (!isSystemInitiated) { + task.mLockTaskUid = callingUid; + if (task.mLockTaskAuth == LOCK_TASK_AUTH_PINNABLE) { + // startLockTask() called by app, but app is not part of lock task whitelist. Show + // app pinning request. We will come back here with isSystemInitiated true. + if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Mode default, asking user"); + StatusBarManagerInternal statusBarManager = LocalServices.getService( + StatusBarManagerInternal.class); + if (statusBarManager != null) { + statusBarManager.showScreenPinningRequest(task.taskId); + } + return; + } + } + + // System can only initiate screen pinning, not full lock task mode + if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, isSystemInitiated ? "Locking pinned" : "Locking fully"); + setLockTaskMode(task, isSystemInitiated ? LOCK_TASK_MODE_PINNED : LOCK_TASK_MODE_LOCKED, + "startLockTask", true); + } + + /** + * Start lock task mode on the given task. + * @param lockTaskModeState whether fully locked or pinned mode. + * @param andResume whether the task should be brought to foreground as part of the operation. + */ + private void setLockTaskMode(@NonNull TaskRecord task, int lockTaskModeState, + String reason, boolean andResume) { + // Should have already been checked, but do it again. + if (task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) { + if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, + "setLockTaskMode: Can't lock due to auth"); + return; + } + if (isLockTaskModeViolation(task)) { + Slog.e(TAG_LOCKTASK, "setLockTaskMode: Attempt to start an unauthorized lock task."); + return; + } + + if (mLockTaskModeTasks.isEmpty()) { + // Start lock task on the handler thread + mHandler.post(() -> performStartLockTask( + task.intent.getComponent().getPackageName(), + task.userId, + lockTaskModeState)); + } + + // Add it or move it to the top. + if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "setLockTaskMode: Locking to " + task + + " Callers=" + Debug.getCallers(4)); + mLockTaskModeTasks.remove(task); + mLockTaskModeTasks.add(task); + + if (task.mLockTaskUid == -1) { + task.mLockTaskUid = task.effectiveUid; + } + + if (andResume) { + mSupervisor.findTaskToMoveToFrontLocked(task, 0, null, reason, + lockTaskModeState != LOCK_TASK_MODE_NONE); + mSupervisor.resumeFocusedStackTopActivityLocked(); + mWindowManager.executeAppTransition(); + } else if (lockTaskModeState != LOCK_TASK_MODE_NONE) { + mSupervisor.handleNonResizableTaskIfNeeded(task, INVALID_STACK_ID, DEFAULT_DISPLAY, + task.getStackId(), true /* forceNonResizable */); + } + } + + // This method should only be called on the handler thread + private void performStartLockTask(String packageName, int userId, int lockTaskModeState) { + // When lock task starts, we disable the status bars. + try { + getLockTaskNotify().show(true); + mLockTaskModeState = lockTaskModeState; + if (getStatusBarService() != null) { + int flags = 0; + if (mLockTaskModeState == LOCK_TASK_MODE_LOCKED) { + flags = STATUS_BAR_MASK_LOCKED; + } else if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) { + flags = STATUS_BAR_MASK_PINNED; + } + getStatusBarService().disable(flags, mToken, mContext.getPackageName()); + } + mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG); + if (getDevicePolicyManager() != null) { + getDevicePolicyManager().notifyLockTaskModeChanged(true, packageName, userId); + } + } catch (RemoteException ex) { + throw new RuntimeException(ex); + } + } + + /** + * Called when the list of packages whitelisted for lock task mode is changed. Any currently + * locked tasks that got removed from the whitelist will be finished. + */ + // TODO: Missing unit tests + void onLockTaskPackagesUpdated() { + boolean didSomething = false; + for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx >= 0; --taskNdx) { + final TaskRecord lockedTask = mLockTaskModeTasks.get(taskNdx); + final boolean wasWhitelisted = + (lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) || + (lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED); + lockedTask.setLockTaskAuth(); + final boolean isWhitelisted = + (lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) || + (lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED); + if (wasWhitelisted && !isWhitelisted) { + // Lost whitelisting authorization. End it now. + if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "onLockTaskPackagesUpdated: removing " + + lockedTask + " mLockTaskAuth()=" + lockedTask.lockTaskAuthToString()); + removeLockedTask(lockedTask); + lockedTask.performClearTaskLocked(); + didSomething = true; + } + } + + for (int displayNdx = mSupervisor.getChildCount() - 1; displayNdx >= 0; --displayNdx) { + ArrayList<ActivityStack> stacks = mSupervisor.getChildAt(displayNdx).mStacks; + for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = stacks.get(stackNdx); + stack.onLockTaskPackagesUpdatedLocked(); + } + } + final ActivityRecord r = mSupervisor.topRunningActivityLocked(); + final TaskRecord task = r != null ? r.getTask() : null; + if (mLockTaskModeTasks.isEmpty() && task != null + && task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) { + // This task must have just been authorized. + if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, + "onLockTaskPackagesUpdated: starting new locktask task=" + task); + setLockTaskMode(task, LOCK_TASK_MODE_LOCKED, "package updated", + false); + didSomething = true; + } + if (didSomething) { + mSupervisor.resumeFocusedStackTopActivityLocked(); + } + } + + /** + * @return the topmost locked task + */ + private TaskRecord getLockedTask() { + final int top = mLockTaskModeTasks.size() - 1; + if (top >= 0) { + return mLockTaskModeTasks.get(top); + } + return null; + } + + // Should only be called on the handler thread + @Nullable + private IStatusBarService getStatusBarService() { + if (mStatusBarService == null) { + mStatusBarService = IStatusBarService.Stub.asInterface( + ServiceManager.checkService(STATUS_BAR_SERVICE)); + if (mStatusBarService == null) { + Slog.w("StatusBarManager", "warning: no STATUS_BAR_SERVICE"); + } + } + return mStatusBarService; + } + + // Should only be called on the handler thread + @Nullable + private IDevicePolicyManager getDevicePolicyManager() { + if (mDevicePolicyManager == null) { + mDevicePolicyManager = IDevicePolicyManager.Stub.asInterface( + ServiceManager.checkService(DEVICE_POLICY_SERVICE)); + if (mDevicePolicyManager == null) { + Slog.w(TAG, "warning: no DEVICE_POLICY_SERVICE"); + } + } + return mDevicePolicyManager; + } + + @NonNull + private LockPatternUtils getLockPatternUtils() { + if (mLockPatternUtils == null) { + // We don't preserve the LPU object to save memory + return new LockPatternUtils(mContext); + } + return mLockPatternUtils; + } + + // Should only be called on the handler thread + @NonNull + private LockTaskNotify getLockTaskNotify() { + if (mLockTaskNotify == null) { + mLockTaskNotify = new LockTaskNotify(mContext); + } + return mLockTaskNotify; + } + + public void dump(PrintWriter pw, String prefix) { + pw.print(prefix); pw.print("mLockTaskModeState=" + lockTaskModeToString()); + pw.println(" mLockTaskModeTasks" + mLockTaskModeTasks); + } + + private String lockTaskModeToString() { + switch (mLockTaskModeState) { + case LOCK_TASK_MODE_LOCKED: + return "LOCKED"; + case LOCK_TASK_MODE_PINNED: + return "PINNED"; + case LOCK_TASK_MODE_NONE: + return "NONE"; + default: return "unknown=" + mLockTaskModeState; + } + } +} diff --git a/services/core/java/com/android/server/am/PinnedActivityStack.java b/services/core/java/com/android/server/am/PinnedActivityStack.java index 392fbb29d091..86ee3f4ba215 100644 --- a/services/core/java/com/android/server/am/PinnedActivityStack.java +++ b/services/core/java/com/android/server/am/PinnedActivityStack.java @@ -39,8 +39,9 @@ class PinnedActivityStack extends ActivityStack<PinnedStackWindowController> @Override PinnedStackWindowController createStackWindowController(int displayId, boolean onTop, - Rect outBounds) { - return new PinnedStackWindowController(mStackId, this, displayId, onTop, outBounds); + Rect outBounds, Configuration overrideConfig) { + return new PinnedStackWindowController(mStackId, this, displayId, onTop, outBounds, + overrideConfig); } Rect getDefaultPictureInPictureBounds(float aspectRatio) { @@ -91,15 +92,16 @@ class PinnedActivityStack extends ActivityStack<PinnedStackWindowController> return mWindowContainerController.deferScheduleMultiWindowModeChanged(); } - public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) { + public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds, + boolean forceUpdate) { // It is guaranteed that the activities requiring the update will be in the pinned stack at // this point (either reparented before the animation into PiP, or before reparenting after // the animation out of PiP) synchronized(this) { ArrayList<TaskRecord> tasks = getAllTasks(); for (int i = 0; i < tasks.size(); i++ ) { - mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(tasks.get(i), - targetStackBounds, true /* immediate */); + mStackSupervisor.updatePictureInPictureMode(tasks.get(i), targetStackBounds, + forceUpdate); } } } diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java index a6ebac44062e..365c5b1d005c 100644 --- a/services/core/java/com/android/server/am/RecentTasks.java +++ b/services/core/java/com/android/server/am/RecentTasks.java @@ -193,10 +193,6 @@ class RecentTasks extends ArrayList<TaskRecord> { return mTaskPersister.getTaskDescriptionIcon(path); } - Bitmap getImageFromWriteQueue(String path) { - return mTaskPersister.getImageFromWriteQueue(path); - } - void saveImage(Bitmap image, String path) { mTaskPersister.saveImage(image, path); } @@ -651,9 +647,6 @@ class RecentTasks extends ArrayList<TaskRecord> { if (task.userId != tr.userId) { continue; } - if (i > MAX_RECENT_BITMAPS) { - tr.freeLastThumbnail(); - } final Intent trIntent = tr.intent; final boolean sameAffinity = task.affinity != null && task.affinity.equals(tr.affinity); @@ -706,7 +699,6 @@ class RecentTasks extends ArrayList<TaskRecord> { // Either task and tr are the same or, their affinities match or their intents match // and neither of them is a document, or they are documents using the same activity // and their maxRecents has been reached. - tr.disposeThumbnail(); remove(i); if (task != tr) { tr.removedFromRecents(); diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 88d894449185..5c0d587a1202 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -16,60 +16,6 @@ package com.android.server.am; -import android.annotation.IntDef; -import android.annotation.Nullable; -import android.app.Activity; -import android.app.ActivityManager; -import android.app.ActivityManager.StackId; -import android.app.ActivityManager.TaskDescription; -import android.app.ActivityManager.TaskSnapshot; -import android.app.ActivityManager.TaskThumbnail; -import android.app.ActivityManager.TaskThumbnailInfo; -import android.app.ActivityOptions; -import android.app.AppGlobals; -import android.app.IActivityManager; -import android.content.ComponentName; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.content.pm.ApplicationInfo; -import android.content.pm.IPackageManager; -import android.content.pm.PackageManager; -import android.content.res.Configuration; -import android.graphics.Bitmap; -import android.graphics.Point; -import android.graphics.Rect; -import android.os.Debug; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; -import android.os.Trace; -import android.os.UserHandle; -import android.provider.Settings; -import android.service.voice.IVoiceInteractionSession; -import android.util.DisplayMetrics; -import android.util.Slog; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.app.IVoiceInteractor; -import com.android.internal.util.XmlUtils; - -import com.android.server.wm.AppWindowContainerController; -import com.android.server.wm.StackWindowController; -import com.android.server.wm.TaskWindowContainerController; -import com.android.server.wm.TaskWindowContainerListener; -import com.android.server.wm.WindowManagerService; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.Objects; - import static android.app.ActivityManager.RESIZE_MODE_FORCED; import static android.app.ActivityManager.RESIZE_MODE_SYSTEM; import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID; @@ -80,6 +26,11 @@ import static android.app.ActivityManager.StackId.HOME_STACK_ID; import static android.app.ActivityManager.StackId.INVALID_STACK_ID; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static android.app.ActivityManager.StackId.RECENTS_STACK_ID; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT; import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS; import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY; @@ -109,10 +60,6 @@ import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; -import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE; -import static com.android.server.am.ActivityRecord.ASSISTANT_ACTIVITY_TYPE; -import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE; -import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE; import static com.android.server.am.ActivityRecord.STARTING_WINDOW_SHOWN; import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING; import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING_TO_TOP; @@ -121,7 +68,56 @@ import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS; import static java.lang.Integer.MAX_VALUE; -final class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener { +import android.annotation.IntDef; +import android.annotation.Nullable; +import android.app.Activity; +import android.app.ActivityManager; +import android.app.ActivityManager.StackId; +import android.app.ActivityManager.TaskDescription; +import android.app.ActivityManager.TaskSnapshot; +import android.app.ActivityOptions; +import android.app.AppGlobals; +import android.app.IActivityManager; +import android.app.WindowConfiguration; +import android.content.ComponentName; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.IPackageManager; +import android.content.pm.PackageManager; +import android.content.res.Configuration; +import android.graphics.Rect; +import android.os.Debug; +import android.os.RemoteException; +import android.os.Trace; +import android.os.UserHandle; +import android.provider.Settings; +import android.service.voice.IVoiceInteractionSession; +import android.util.DisplayMetrics; +import android.util.Slog; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.app.IVoiceInteractor; +import com.android.internal.util.XmlUtils; +import com.android.server.wm.AppWindowContainerController; +import com.android.server.wm.ConfigurationContainer; +import com.android.server.wm.StackWindowController; +import com.android.server.wm.TaskWindowContainerController; +import com.android.server.wm.TaskWindowContainerListener; +import com.android.server.wm.WindowManagerService; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.Objects; + +class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener { private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM; private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE; private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS; @@ -143,6 +139,7 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta private static final String ATTR_USERID = "user_id"; private static final String ATTR_USER_SETUP_COMPLETE = "user_setup_complete"; private static final String ATTR_EFFECTIVE_UID = "effective_uid"; + @Deprecated private static final String ATTR_TASKTYPE = "task_type"; private static final String ATTR_FIRSTACTIVETIME = "first_active_time"; private static final String ATTR_LASTACTIVETIME = "last_active_time"; @@ -256,9 +253,6 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta /** Current stack. Setter must always be used to update the value. */ private ActivityStack mStack; - /** Takes on same set of values as ActivityRecord.mActivityType */ - int taskType; - /** Takes on same value as first root activity */ boolean isPersistable = false; int maxRecents; @@ -268,10 +262,11 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta * (positive) or back (negative). Absolute value indicates time. */ long mLastTimeMoved = System.currentTimeMillis(); - /** Indication of what to run next when task exits. Use ActivityRecord types. - * ActivityRecord.APPLICATION_ACTIVITY_TYPE indicates to resume the task below this one in the - * task stack. */ - private int mTaskToReturnTo = APPLICATION_ACTIVITY_TYPE; + /** Indication of what to run next when task exits. */ + // TODO: Shouldn't be needed if we have things in visual order. I.e. we stop using stacks or + // have a stack per standard application type... + /*@WindowConfiguration.ActivityType*/ + private int mTaskToReturnTo = ACTIVITY_TYPE_STANDARD; /** If original intent did not allow relinquishing task identity, save that information */ private boolean mNeverRelinquishIdentity = true; @@ -280,10 +275,7 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta // do not want to delete the stack when the task goes empty. private boolean mReuseTask = false; - private Bitmap mLastThumbnail; // Last thumbnail captured for this item. - private final File mLastThumbnailFile; // File containing last thumbnail. private final String mFilename; - private TaskThumbnailInfo mLastThumbnailInfo; CharSequence lastDescription; // Last description captured for this item. int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent. @@ -327,13 +319,11 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta private TaskWindowContainerController mWindowContainerController; TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent, - IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor, int type) { + IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) { mService = service; mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX + TaskPersister.IMAGE_EXTENSION; userId = UserHandle.getUserId(info.applicationInfo.uid); - mLastThumbnailFile = new File(TaskPersister.getUserImagesDir(userId), mFilename); - mLastThumbnailInfo = new TaskThumbnailInfo(); taskId = _taskId; mAffiliatedTaskId = _taskId; voiceSession = _voiceSession; @@ -342,7 +332,6 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta mActivities = new ArrayList<>(); mCallingUid = info.applicationInfo.uid; mCallingPackage = info.packageName; - taskType = type; setIntent(_intent, info); setMinDimensions(info); touchActiveTime(); @@ -350,13 +339,11 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta } TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent, - TaskDescription _taskDescription, TaskThumbnailInfo thumbnailInfo) { + TaskDescription _taskDescription) { mService = service; mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX + TaskPersister.IMAGE_EXTENSION; userId = UserHandle.getUserId(info.applicationInfo.uid); - mLastThumbnailFile = new File(TaskPersister.getUserImagesDir(userId), mFilename); - mLastThumbnailInfo = thumbnailInfo; taskId = _taskId; mAffiliatedTaskId = _taskId; voiceSession = null; @@ -373,8 +360,7 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta maxRecents = Math.min(Math.max(info.maxRecents, 1), ActivityManager.getMaxAppRecentsLimitStatic()); - taskType = APPLICATION_ACTIVITY_TYPE; - mTaskToReturnTo = HOME_ACTIVITY_TYPE; + mTaskToReturnTo = ACTIVITY_TYPE_HOME; lastTaskDescription = _taskDescription; touchActiveTime(); mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity); @@ -383,20 +369,17 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta private TaskRecord(ActivityManagerService service, int _taskId, Intent _intent, Intent _affinityIntent, String _affinity, String _rootAffinity, ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset, - boolean _autoRemoveRecents, boolean _askedCompatMode, int _taskType, int _userId, + boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId, int _effectiveUid, String _lastDescription, ArrayList<ActivityRecord> activities, long _firstActiveTime, long _lastActiveTime, long lastTimeMoved, boolean neverRelinquishIdentity, TaskDescription _lastTaskDescription, - TaskThumbnailInfo lastThumbnailInfo, int taskAffiliation, int prevTaskId, - int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage, - int resizeMode, boolean supportsPictureInPicture, boolean privileged, - boolean _realActivitySuspended, boolean userSetupComplete, int minWidth, - int minHeight) { + int taskAffiliation, int prevTaskId, int nextTaskId, int taskAffiliationColor, + int callingUid, String callingPackage, int resizeMode, boolean supportsPictureInPicture, + boolean privileged, boolean _realActivitySuspended, boolean userSetupComplete, + int minWidth, int minHeight) { mService = service; mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX + TaskPersister.IMAGE_EXTENSION; - mLastThumbnailFile = new File(TaskPersister.getUserImagesDir(_userId), mFilename); - mLastThumbnailInfo = lastThumbnailInfo; taskId = _taskId; intent = _intent; affinityIntent = _affinityIntent; @@ -411,8 +394,7 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta isAvailable = true; autoRemoveRecents = _autoRemoveRecents; askedCompatMode = _askedCompatMode; - taskType = _taskType; - mTaskToReturnTo = HOME_ACTIVITY_TYPE; + mTaskToReturnTo = ACTIVITY_TYPE_HOME; userId = _userId; mUserSetupComplete = userSetupComplete; effectiveUid = _effectiveUid; @@ -451,8 +433,8 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta final Configuration overrideConfig = getOverrideConfiguration(); setWindowContainerController(new TaskWindowContainerController(taskId, this, getStack().getWindowContainerController(), userId, bounds, overrideConfig, - mResizeMode, mSupportsPictureInPicture, isHomeTask(), onTop, showForAllUsers, - lastTaskDescription)); + mResizeMode, mSupportsPictureInPicture, onTop, + showForAllUsers, lastTaskDescription)); } /** @@ -469,9 +451,9 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta } void removeWindowContainer() { - mService.mStackSupervisor.removeLockedTaskLocked(this); + mService.mLockTaskController.removeLockedTask(this); mWindowContainerController.removeContainer(); - if (!StackId.persistTaskBounds(getStackId())) { + if (!getWindowConfiguration().persistTaskBounds()) { // Reset current bounds for task whose bounds shouldn't be persisted so it uses // default configuration the next time it launches. updateOverrideConfiguration(null); @@ -905,16 +887,16 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta return this.intent.filterEquals(intent); } - void setTaskToReturnTo(int taskToReturnTo) { - mTaskToReturnTo = (taskToReturnTo == RECENTS_ACTIVITY_TYPE) - ? HOME_ACTIVITY_TYPE : taskToReturnTo; + void setTaskToReturnTo(/*@WindowConfiguration.ActivityType*/ int taskToReturnTo) { + mTaskToReturnTo = taskToReturnTo == ACTIVITY_TYPE_RECENTS + ? ACTIVITY_TYPE_HOME : taskToReturnTo; } void setTaskToReturnTo(ActivityRecord source) { - if (source.isRecentsActivity()) { - setTaskToReturnTo(RECENTS_ACTIVITY_TYPE); - } else if (source.isAssistantActivity()) { - setTaskToReturnTo(ASSISTANT_ACTIVITY_TYPE); + if (source.isActivityTypeRecents()) { + setTaskToReturnTo(ACTIVITY_TYPE_RECENTS); + } else if (source.isActivityTypeAssistant()) { + setTaskToReturnTo(ACTIVITY_TYPE_ASSISTANT); } } @@ -922,6 +904,14 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta return mTaskToReturnTo; } + boolean returnsToHomeTask() { + return mTaskToReturnTo == ACTIVITY_TYPE_HOME; + } + + boolean returnsToStandardTask() { + return mTaskToReturnTo == ACTIVITY_TYPE_STANDARD; + } + void setPrevAffiliate(TaskRecord prevAffiliate) { mPrevAffiliate = prevAffiliate; mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.taskId; @@ -971,7 +961,7 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta } @Override - void onParentChanged() { + protected void onParentChanged() { super.onParentChanged(); mService.mStackSupervisor.updateUIDsPresentOnDisplay(); } @@ -989,7 +979,6 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta } void removedFromRecents() { - disposeThumbnail(); closeRecentsChain(); if (inRecents) { inRecents = false; @@ -1023,89 +1012,6 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta setNextAffiliate(null); } - /** - * Sets the last thumbnail with the current task bounds and the system orientation. - * @return whether the thumbnail was set - */ - boolean setLastThumbnailLocked(Bitmap thumbnail) { - int taskWidth = 0; - int taskHeight = 0; - if (mBounds != null) { - // Non-fullscreen tasks - taskWidth = mBounds.width(); - taskHeight = mBounds.height(); - } else if (mStack != null) { - // Fullscreen tasks - final Point displaySize = new Point(); - mStack.getDisplaySize(displaySize); - taskWidth = displaySize.x; - taskHeight = displaySize.y; - } else { - Slog.e(TAG, "setLastThumbnailLocked() called on Task without stack"); - } - // We need to provide the current orientation of the display on which this task resides, - // not the orientation of the task. - final int orientation = getStack().getDisplay().getConfiguration().orientation; - return setLastThumbnailLocked(thumbnail, taskWidth, taskHeight, orientation); - } - - /** - * Sets the last thumbnail with the current task bounds. - * @return whether the thumbnail was set - */ - private boolean setLastThumbnailLocked(Bitmap thumbnail, int taskWidth, int taskHeight, - int screenOrientation) { - if (mLastThumbnail != thumbnail) { - mLastThumbnail = thumbnail; - mLastThumbnailInfo.taskWidth = taskWidth; - mLastThumbnailInfo.taskHeight = taskHeight; - mLastThumbnailInfo.screenOrientation = screenOrientation; - if (thumbnail == null) { - if (mLastThumbnailFile != null) { - mLastThumbnailFile.delete(); - } - } else { - mService.mRecentTasks.saveImage(thumbnail, mLastThumbnailFile.getAbsolutePath()); - } - return true; - } - return false; - } - - void getLastThumbnail(TaskThumbnail thumbs) { - thumbs.mainThumbnail = mLastThumbnail; - thumbs.thumbnailInfo = mLastThumbnailInfo; - thumbs.thumbnailFileDescriptor = null; - if (mLastThumbnail == null) { - thumbs.mainThumbnail = mService.mRecentTasks.getImageFromWriteQueue( - mLastThumbnailFile.getAbsolutePath()); - } - // Only load the thumbnail file if we don't have a thumbnail - if (thumbs.mainThumbnail == null && mLastThumbnailFile.exists()) { - try { - thumbs.thumbnailFileDescriptor = ParcelFileDescriptor.open(mLastThumbnailFile, - ParcelFileDescriptor.MODE_READ_ONLY); - } catch (IOException e) { - } - } - } - - /** - * Removes in-memory thumbnail data when the max number of in-memory task thumbnails is reached. - */ - void freeLastThumbnail() { - mLastThumbnail = null; - } - - /** - * Removes all associated thumbnail data when a task is removed or pruned from recents. - */ - void disposeThumbnail() { - mLastThumbnailInfo.reset(); - mLastThumbnail = null; - lastDescription = null; - } - /** Returns the intent for the root activity for this task */ Intent getBaseIntent() { return intent != null ? intent : affinityIntent; @@ -1235,6 +1141,16 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta addActivityAtIndex(mActivities.size(), r); } + @Override + /*@WindowConfiguration.ActivityType*/ + public int getActivityType() { + final int applicationType = super.getActivityType(); + if (applicationType != ACTIVITY_TYPE_UNDEFINED || mActivities.isEmpty()) { + return applicationType; + } + return mActivities.get(0).getActivityType(); + } + /** * Adds an activity {@param r} at the given {@param index}. The activity {@param r} must either * be in the current task or unparented to any task. @@ -1255,7 +1171,17 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta } // Only set this based on the first activity if (mActivities.isEmpty()) { - taskType = r.mActivityType; + // TODO: propagating this change to the WM side...Should probably be done by having + // ConfigurationContainer change listener that the WindowContainerController registers + // for. + if (r.getActivityType() == ACTIVITY_TYPE_UNDEFINED) { + // Normally non-standard activity type for the activity record will be set when the + // object is created, however we delay setting the standard application type until + // this point so that the task can set the type for additional activities added in + // the else condition below. + r.setActivityType(ACTIVITY_TYPE_STANDARD); + } + setActivityType(r.getActivityType()); isPersistable = r.isPersistable(); mCallingUid = r.launchedFromUid; mCallingPackage = r.launchedFromPackage; @@ -1264,7 +1190,7 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta ActivityManager.getMaxAppRecentsLimitStatic()); } else { // Otherwise make all added activities match this one. - r.mActivityType = taskType; + r.setActivityType(getActivityType()); } final int size = mActivities.size(); @@ -1293,7 +1219,6 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta // created controller for the activity we are starting yet. mWindowContainerController.positionChildAt(appController, index); } - r.onOverrideConfigurationSent(); // Make sure the list of display UID whitelists is updated // now that this record is in a new task. @@ -1394,7 +1319,7 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta /** * Completely remove all activities associated with an existing task. */ - final void performClearTaskLocked() { + void performClearTaskLocked() { mReuseTask = true; performClearTaskAtIndexLocked(0, !PAUSE_IMMEDIATELY); mReuseTask = false; @@ -1467,19 +1392,6 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta return null; } - TaskThumbnail getTaskThumbnailLocked() { - if (mStack != null) { - final ActivityRecord resumedActivity = mStack.mResumedActivity; - if (resumedActivity != null && resumedActivity.getTask() == this) { - final Bitmap thumbnail = resumedActivity.screenshotActivityLocked(); - setLastThumbnailLocked(thumbnail); - } - } - final TaskThumbnail taskThumbnail = new TaskThumbnail(); - getLastThumbnail(taskThumbnail); - return taskThumbnail; - } - void removeTaskActivitiesLocked(boolean pauseImmediately) { // Just remove the entire task. performClearTaskAtIndexLocked(0, pauseImmediately); @@ -1526,7 +1438,7 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta " mLockTaskAuth=" + lockTaskAuthToString()); } - boolean isLockTaskWhitelistedLocked() { + private boolean isLockTaskWhitelistedLocked() { String pkg = (realActivity != null) ? realActivity.getPackageName() : null; if (pkg == null) { return false; @@ -1543,28 +1455,12 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta return false; } - boolean isHomeTask() { - return taskType == HOME_ACTIVITY_TYPE; - } - - boolean isRecentsTask() { - return taskType == RECENTS_ACTIVITY_TYPE; - } - - boolean isAssistantTask() { - return taskType == ASSISTANT_ACTIVITY_TYPE; - } - - boolean isApplicationTask() { - return taskType == APPLICATION_ACTIVITY_TYPE; - } - boolean isOverHomeStack() { - return mTaskToReturnTo == HOME_ACTIVITY_TYPE; + return mTaskToReturnTo == ACTIVITY_TYPE_HOME; } boolean isOverAssistantStack() { - return mTaskToReturnTo == ASSISTANT_ACTIVITY_TYPE; + return mTaskToReturnTo == ACTIVITY_TYPE_ASSISTANT; } private boolean isResizeable(boolean checkSupportsPip) { @@ -1580,8 +1476,9 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta // A task can not be docked even if it is considered resizeable because it only supports // picture-in-picture mode but has a non-resizeable resizeMode return mService.mSupportsSplitScreenMultiWindow - && isResizeable(false /* checkSupportsPip */) - && !ActivityInfo.isPreserveOrientationMode(mResizeMode); + && (mService.mForceResizableActivities + || (isResizeable(false /* checkSupportsPip */) + && !ActivityInfo.isPreserveOrientationMode(mResizeMode))); } /** @@ -1757,7 +1654,6 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta out.attribute(null, ATTR_USERID, String.valueOf(userId)); out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete)); out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid)); - out.attribute(null, ATTR_TASKTYPE, String.valueOf(taskType)); out.attribute(null, ATTR_FIRSTACTIVETIME, String.valueOf(firstActiveTime)); out.attribute(null, ATTR_LASTACTIVETIME, String.valueOf(lastActiveTime)); out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved)); @@ -1768,7 +1664,6 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta if (lastTaskDescription != null) { lastTaskDescription.saveToXml(out); } - mLastThumbnailInfo.saveToXml(out); out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor)); out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId)); out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId)); @@ -1828,7 +1723,7 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta boolean rootHasReset = false; boolean autoRemoveRecents = false; boolean askedCompatMode = false; - int taskType = ActivityRecord.APPLICATION_ACTIVITY_TYPE; + int taskType = 0; int userId = 0; boolean userSetupComplete = true; int effectiveUid = -1; @@ -1840,7 +1735,6 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta int taskId = INVALID_TASK_ID; final int outerDepth = in.getDepth(); TaskDescription taskDescription = new TaskDescription(); - TaskThumbnailInfo thumbnailInfo = new TaskThumbnailInfo(); int taskAffiliation = INVALID_TASK_ID; int taskAffiliationColor = 0; int prevTaskId = INVALID_TASK_ID; @@ -1897,8 +1791,6 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta lastTimeOnTop = Long.parseLong(attrValue); } else if (ATTR_NEVERRELINQUISH.equals(attrName)) { neverRelinquishIdentity = Boolean.parseBoolean(attrValue); - } else if (attrName.startsWith(TaskThumbnailInfo.ATTR_TASK_THUMBNAILINFO_PREFIX)) { - thumbnailInfo.restoreFromXml(attrName, attrValue); } else if (attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) { taskDescription.restoreFromXml(attrName, attrValue); } else if (ATTR_TASK_AFFILIATION.equals(attrName)) { @@ -1986,7 +1878,7 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta // they are marked as RESIZE_MODE_RESIZEABLE to RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION // since we didn't have that differentiation before version 1 and the system didn't // resize home activities before then. - if (taskType == HOME_ACTIVITY_TYPE && resizeMode == RESIZE_MODE_RESIZEABLE) { + if (taskType == 1 /* old home type */ && resizeMode == RESIZE_MODE_RESIZEABLE) { resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION; } } else { @@ -2002,12 +1894,11 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent, affinityIntent, affinity, rootAffinity, realActivity, origActivity, rootHasReset, - autoRemoveRecents, askedCompatMode, taskType, userId, effectiveUid, lastDescription, + autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription, activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity, - taskDescription, thumbnailInfo, taskAffiliation, prevTaskId, nextTaskId, - taskAffiliationColor, callingUid, callingPackage, resizeMode, - supportsPictureInPicture, privileged, realActivitySuspended, userSetupComplete, - minWidth, minHeight); + taskDescription, taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, + callingUid, callingPackage, resizeMode, supportsPictureInPicture, privileged, + realActivitySuspended, userSetupComplete, minWidth, minHeight); task.updateOverrideConfiguration(bounds); for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) { @@ -2106,8 +1997,9 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta final Configuration newConfig = getOverrideConfiguration(); mFullscreen = bounds == null; + final boolean persistBounds = getWindowConfiguration().persistTaskBounds(); if (mFullscreen) { - if (mBounds != null && StackId.persistTaskBounds(mStack.mStackId)) { + if (mBounds != null && persistBounds) { mLastNonFullscreenBounds = mBounds; } mBounds = null; @@ -2120,7 +2012,7 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta } else { mBounds.set(mTmpRect); } - if (mStack == null || StackId.persistTaskBounds(mStack.mStackId)) { + if (mStack == null || persistBounds) { mLastNonFullscreenBounds = mBounds; } computeOverrideConfiguration(newConfig, mTmpRect, insetBounds, @@ -2224,13 +2116,13 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta * The task will be moved (and stack focus changed) later if necessary. */ int getLaunchStackId() { - if (isRecentsTask()) { + if (isActivityTypeRecents()) { return RECENTS_STACK_ID; } - if (isHomeTask()) { + if (isActivityTypeHome()) { return HOME_STACK_ID; } - if (isAssistantTask()) { + if (isActivityTypeAssistant()) { return ASSISTANT_STACK_ID; } if (mBounds != null) { @@ -2240,7 +2132,7 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta } /** Returns the bounds that should be used to launch this task. */ - Rect getLaunchBounds() { + private Rect getLaunchBounds() { if (mStack == null) { return null; } @@ -2252,7 +2144,7 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta || stackId == FULLSCREEN_WORKSPACE_STACK_ID || (stackId == DOCKED_STACK_ID && !isResizeable())) { return isResizeable() ? mStack.mBounds : null; - } else if (!StackId.persistTaskBounds(stackId)) { + } else if (!getWindowConfiguration().persistTaskBounds()) { return mStack.mBounds; } return mLastNonFullscreenBounds; @@ -2309,12 +2201,12 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta pw.print(prefix); pw.print("realActivity="); pw.println(realActivity.flattenToShortString()); } - if (autoRemoveRecents || isPersistable || taskType != 0 || mTaskToReturnTo != 0 - || numFullscreen != 0) { + if (autoRemoveRecents || isPersistable || !isActivityTypeStandard() + || mTaskToReturnTo != ACTIVITY_TYPE_STANDARD || numFullscreen != 0) { pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents); pw.print(" isPersistable="); pw.print(isPersistable); pw.print(" numFullscreen="); pw.print(numFullscreen); - pw.print(" taskType="); pw.print(taskType); + pw.print(" activityType="); pw.print(getActivityType()); pw.print(" mTaskToReturnTo="); pw.println(mTaskToReturnTo); } if (rootWasReset || mNeverRelinquishIdentity || mReuseTask @@ -2350,8 +2242,6 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta pw.print(" inRecents="); pw.print(inRecents); pw.print(" isAvailable="); pw.println(isAvailable); } - pw.print(prefix); pw.print("lastThumbnail="); pw.print(mLastThumbnail); - pw.print(" lastThumbnailFile="); pw.println(mLastThumbnailFile); if (lastDescription != null) { pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription); } diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 7e9a2ac91127..db6bb7d8e653 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -36,6 +36,7 @@ import static com.android.server.am.ActivityManagerService.REPORT_USER_SWITCH_MS import static com.android.server.am.ActivityManagerService.SYSTEM_USER_CURRENT_MSG; import static com.android.server.am.ActivityManagerService.SYSTEM_USER_START_MSG; import static com.android.server.am.ActivityManagerService.SYSTEM_USER_UNLOCK_MSG; +import static com.android.server.am.ActivityManagerService.USER_SWITCH_CALLBACKS_TIMEOUT_MSG; import static com.android.server.am.ActivityManagerService.USER_SWITCH_TIMEOUT_MSG; import static com.android.server.am.UserState.STATE_BOOTING; import static com.android.server.am.UserState.STATE_RUNNING_LOCKED; @@ -115,7 +116,12 @@ class UserController { // Amount of time we wait for observers to handle a user switch before // giving up on them and unfreezing the screen. - static final int USER_SWITCH_TIMEOUT = 3 * 1000; + static final int USER_SWITCH_TIMEOUT_MS = 3 * 1000; + + // If a callback wasn't called within USER_SWITCH_CALLBACKS_TIMEOUT_MS after + // USER_SWITCH_TIMEOUT_MS, an error is reported. Usually it indicates a problem in the observer + // when it never calls back. + private static final int USER_SWITCH_CALLBACKS_TIMEOUT_MS = 5 * 1000; private final Object mLock; private final Injector mInjector; @@ -171,7 +177,11 @@ class UserController { @GuardedBy("mLock") private volatile ArraySet<String> mCurWaitingUserSwitchCallbacks; - private volatile UserManagerService mUserManager; + /** + * Callbacks that are still active after {@link #USER_SWITCH_TIMEOUT_MS} + */ + @GuardedBy("mLock") + private ArraySet<String> mTimeoutUserSwitchCallbacks; private final LockPatternUtils mLockPatternUtils; @@ -831,8 +841,9 @@ class UserController { } if (foreground) { - mInjector.getActivityStackSupervisor().setLockTaskModeLocked( - null, ActivityManager.LOCK_TASK_MODE_NONE, "startUser", false); + // TODO: I don't think this does what the caller think it does. Seems to only + // remove one locked task and won't work if multiple locked tasks are present. + mInjector.getLockTaskController().clearLockTaskMode("startUser"); } final UserInfo userInfo = getUserInfo(userId); @@ -925,7 +936,7 @@ class UserController { mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_MSG, oldUserId, userId, uss)); mHandler.sendMessageDelayed(mHandler.obtainMessage(USER_SWITCH_TIMEOUT_MSG, - oldUserId, userId, uss), USER_SWITCH_TIMEOUT); + oldUserId, userId, uss), USER_SWITCH_TIMEOUT_MS); } if (needStart) { @@ -1131,8 +1142,23 @@ class UserController { void timeoutUserSwitch(UserState uss, int oldUserId, int newUserId) { synchronized (mLock) { - Slog.wtf(TAG, "User switch timeout: from " + oldUserId + " to " + newUserId); + Slog.e(TAG, "User switch timeout: from " + oldUserId + " to " + newUserId); + mTimeoutUserSwitchCallbacks = mCurWaitingUserSwitchCallbacks; + mHandler.removeMessages(USER_SWITCH_CALLBACKS_TIMEOUT_MSG); sendContinueUserSwitchLocked(uss, oldUserId, newUserId); + // Report observers that never called back (USER_SWITCH_CALLBACKS_TIMEOUT) + mHandler.sendMessageDelayed(mHandler.obtainMessage(USER_SWITCH_CALLBACKS_TIMEOUT_MSG, + oldUserId, newUserId), USER_SWITCH_CALLBACKS_TIMEOUT_MS); + } + } + + void timeoutUserSwitchCallbacks(int oldUserId, int newUserId) { + synchronized (mLock) { + if (mTimeoutUserSwitchCallbacks != null && !mTimeoutUserSwitchCallbacks.isEmpty()) { + Slog.wtf(TAG, "User switch timeout: from " + oldUserId + " to " + newUserId + + ". Observers that didn't respond: " + mTimeoutUserSwitchCallbacks); + mTimeoutUserSwitchCallbacks = null; + } } } @@ -1159,18 +1185,16 @@ class UserController { public void sendResult(Bundle data) throws RemoteException { synchronized (mLock) { long delay = SystemClock.elapsedRealtime() - dispatchStartedTime; - if (delay > USER_SWITCH_TIMEOUT) { - Slog.wtf(TAG, "User switch timeout: observer " + name + if (delay > USER_SWITCH_TIMEOUT_MS) { + Slog.e(TAG, "User switch timeout: observer " + name + " sent result after " + delay + " ms"); } - // Early return if this session is no longer valid - if (curWaitingUserSwitchCallbacks - != mCurWaitingUserSwitchCallbacks) { - return; - } curWaitingUserSwitchCallbacks.remove(name); - // Continue switching if all callbacks have been notified - if (waitingCallbacksCount.decrementAndGet() == 0) { + // Continue switching if all callbacks have been notified and + // user switching session is still valid + if (waitingCallbacksCount.decrementAndGet() == 0 + && (curWaitingUserSwitchCallbacks + == mCurWaitingUserSwitchCallbacks)) { sendContinueUserSwitchLocked(uss, oldUserId, newUserId); } } @@ -1777,5 +1801,9 @@ class UserController { ActivityStackSupervisor getActivityStackSupervisor() { return mService.mStackSupervisor; } + + LockTaskController getLockTaskController() { + return mService.mLockTaskController; + } } } diff --git a/services/core/java/com/android/server/audio/AudioEventLogger.java b/services/core/java/com/android/server/audio/AudioEventLogger.java new file mode 100644 index 000000000000..c96138fff8e6 --- /dev/null +++ b/services/core/java/com/android/server/audio/AudioEventLogger.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.audio; + +import java.io.PrintWriter; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.LinkedList; + +public class AudioEventLogger { + + // ring buffer of events to log. + private final LinkedList<Event> mEvents; + + private final String mTitle; + + // the maximum number of events to keep in log + private final int mMemSize; + + public static abstract class Event { + // formatter for timestamps + private final static SimpleDateFormat sFormat = new SimpleDateFormat("MM-dd HH:mm:ss:SSS"); + + private final long mTimestamp; + + Event() { + mTimestamp = System.currentTimeMillis(); + } + + public String toString() { + return (new StringBuilder(sFormat.format(new Date(mTimestamp)))) + .append(" ").append(eventToString()).toString(); + } + + /** + * Convert event to String. + * This method is only called when the logger history is about to the dumped, + * so this method is where expensive String conversions should be made, not when the Event + * subclass is created. + * Timestamp information will be automatically added, do not include it. + * @return a string representation of the event that occurred. + */ + abstract public String eventToString(); + } + + public static class StringEvent extends Event { + private final String mMsg; + + public StringEvent(String msg) { + mMsg = msg; + } + + @Override + public String eventToString() { + return mMsg; + } + } + + /** + * Constructor for logger. + * @param size the maximum number of events to keep in log + * @param title the string displayed before the recorded log + */ + public AudioEventLogger(int size, String title) { + mEvents = new LinkedList<Event>(); + mMemSize = size; + mTitle = title; + } + + public synchronized void log(Event evt) { + if (mEvents.size() >= mMemSize) { + mEvents.removeFirst(); + } + mEvents.add(evt); + } + + public synchronized void dump(PrintWriter pw) { + pw.println("Audio event log: " + mTitle); + for (Event evt : mEvents) { + pw.println(evt.toString()); + } + } +} diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 2943b5c8805c..91b15912fcb5 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -16,6 +16,11 @@ package com.android.server.audio; +import com.android.server.audio.AudioServiceEvents.ForceUseEvent; +import com.android.server.audio.AudioServiceEvents.PhoneStateEvent; +import com.android.server.audio.AudioServiceEvents.VolumeEvent; +import com.android.server.audio.AudioServiceEvents.WiredDevConnectEvent; + import static android.Manifest.permission.REMOTE_AUDIO_PLAYBACK; import static android.media.AudioManager.RINGER_MODE_NORMAL; import static android.media.AudioManager.RINGER_MODE_SILENT; @@ -718,7 +723,7 @@ public class AudioService extends IAudioService.Stub AudioSystem.FOR_SYSTEM, cameraSoundForced ? AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE, - null, + new String("AudioService ctor"), 0); mSafeMediaVolumeState = new Integer(Settings.Global.getInt(mContentResolver, @@ -796,12 +801,23 @@ public class AudioService extends IAudioService.Stub public void systemReady() { sendMsg(mAudioHandler, MSG_SYSTEM_READY, SENDMSG_QUEUE, 0, 0, null, 0); - try { - ActivityManager.getService().registerUidObserver(mUidObserver, - ActivityManager.UID_OBSERVER_CACHED | ActivityManager.UID_OBSERVER_GONE, - ActivityManager.PROCESS_STATE_UNKNOWN, null); - } catch (RemoteException e) { - // ignored; both services live in system_server + if (false) { + // This is turned off for now, because it is racy and thus causes apps to break. + // Currently banning a uid means that if an app tries to start playing an audio + // stream, that will be preventing, and unbanning it will not allow that stream + // to resume. However these changes in uid state are racy with what the app is doing, + // so that after taking a process out of the cached state we can't guarantee that + // we will unban the uid before the app actually tries to start playing audio. + // (To do that, the activity manager would need to wait until it knows for sure + // that the ban has been removed, before telling the app to do whatever it is + // supposed to do that caused it to go out of the cached state.) + try { + ActivityManager.getService().registerUidObserver(mUidObserver, + ActivityManager.UID_OBSERVER_CACHED | ActivityManager.UID_OBSERVER_GONE, + ActivityManager.PROCESS_STATE_UNKNOWN, null); + } catch (RemoteException e) { + // ignored; both services live in system_server + } } } @@ -896,13 +912,23 @@ public class AudioService extends IAudioService.Stub } } // Restore call state - AudioSystem.setPhoneState(mMode); + if (AudioSystem.setPhoneState(mMode) == AudioSystem.AUDIO_STATUS_OK) { + mModeLogger.log(new AudioEventLogger.StringEvent( + "onAudioServerDied causes setPhoneState(" + AudioSystem.modeToString(mMode) + ")")); + } - // Restore forced usage for communcations and record + // Restore forced usage for communications and record + mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, + "onAudioServerDied")); AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm); + mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_RECORD, mForcedUseForComm, + "onAudioServerDied")); AudioSystem.setForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm); - AudioSystem.setForceUse(AudioSystem.FOR_SYSTEM, mCameraSoundForced ? - AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE); + final int forSys = mCameraSoundForced ? + AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE; + mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_SYSTEM, forSys, + "onAudioServerDied")); + AudioSystem.setForceUse(AudioSystem.FOR_SYSTEM, forSys); // Restore stream volumes int numStreamTypes = AudioSystem.getNumStreamTypes(); @@ -929,16 +955,20 @@ public class AudioService extends IAudioService.Stub } synchronized (mBluetoothA2dpEnabledLock) { - AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, - mBluetoothA2dpEnabled ? - AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP); + final int forMed = mBluetoothA2dpEnabled ? + AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP; + mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_MEDIA, forMed, + "onAudioServerDied")); + AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, forMed); } synchronized (mSettingsLock) { - AudioSystem.setForceUse(AudioSystem.FOR_DOCK, - mDockAudioMediaEnabled ? - AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE); - sendEncodedSurroundMode(mContentResolver); + final int forDock = mDockAudioMediaEnabled ? + AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE; + mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_DOCK, forDock, + "onAudioServerDied")); + AudioSystem.setForceUse(AudioSystem.FOR_DOCK, forDock); + sendEncodedSurroundMode(mContentResolver, "onAudioServerDied"); } if (mHdmiManager != null) { synchronized (mHdmiManager) { @@ -1131,7 +1161,7 @@ public class AudioService extends IAudioService.Stub AudioSystem.FOR_DOCK, mDockAudioMediaEnabled ? AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE, - null, + new String("readDockAudioSettings"), 0); } @@ -1146,15 +1176,15 @@ public class AudioService extends IAudioService.Stub AudioSystem.setMasterMono(masterMono); } - private void sendEncodedSurroundMode(ContentResolver cr) + private void sendEncodedSurroundMode(ContentResolver cr, String eventSource) { int encodedSurroundMode = Settings.Global.getInt( cr, Settings.Global.ENCODED_SURROUND_OUTPUT, Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO); - sendEncodedSurroundMode(encodedSurroundMode); + sendEncodedSurroundMode(encodedSurroundMode, eventSource); } - private void sendEncodedSurroundMode(int encodedSurroundMode) + private void sendEncodedSurroundMode(int encodedSurroundMode, String eventSource) { // initialize to guaranteed bad value int forceSetting = AudioSystem.NUM_FORCE_CONFIG; @@ -1179,7 +1209,7 @@ public class AudioService extends IAudioService.Stub SENDMSG_QUEUE, AudioSystem.FOR_ENCODED_SURROUND, forceSetting, - null, + eventSource, 0); } } @@ -1225,7 +1255,7 @@ public class AudioService extends IAudioService.Stub updateRingerModeAffectedStreams(); readDockAudioSettings(cr); - sendEncodedSurroundMode(cr); + sendEncodedSurroundMode(cr, "readPersistedSettings"); } mMuteAffectedStreams = System.getIntForUser(cr, @@ -1296,6 +1326,9 @@ public class AudioService extends IAudioService.Stub + ", flags=" + flags + ", caller=" + caller + ", volControlStream=" + mVolumeControlStream + ", userSelect=" + mUserSelectedVolumeControlStream); + mVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_SUGG_VOL, suggestedStreamType, + direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage) + .append("/").append(caller).append(" uid:").append(uid).toString())); final int streamType; if (mUserSelectedVolumeControlStream) { // implies mVolumeControlStream != -1 streamType = mVolumeControlStream; @@ -1345,6 +1378,8 @@ public class AudioService extends IAudioService.Stub + "CHANGE_ACCESSIBILITY_VOLUME / callingPackage=" + callingPackage); return; } + mVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_STREAM_VOL, streamType, + direction/*val1*/, flags/*val2*/, callingPackage)); adjustStreamVolume(streamType, direction, flags, callingPackage, callingPackage, Binder.getCallingUid()); } @@ -1661,6 +1696,8 @@ public class AudioService extends IAudioService.Stub + " CHANGE_ACCESSIBILITY_VOLUME callingPackage=" + callingPackage); return; } + mVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType, + index/*val1*/, flags/*val2*/, callingPackage)); setStreamVolume(streamType, index, flags, callingPackage, callingPackage, Binder.getCallingUid()); } @@ -2542,6 +2579,7 @@ public class AudioService extends IAudioService.Stub if (status == AudioSystem.AUDIO_STATUS_OK) { if (DEBUG_MODE) { Log.v(TAG, " mode successfully set to " + mode); } mMode = mode; + mModeLogger.log(new PhoneStateEvent(caller, pid, mode)); } else { if (hdlr != null) { mSetModeDeathHandlers.remove(hdlr); @@ -2836,11 +2874,16 @@ public class AudioService extends IAudioService.Stub if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) { return; } + // for logging only + final String eventSource = new StringBuilder("setSpeakerphoneOn(").append(on) + .append(") from u/pid:").append(Binder.getCallingUid()).append("/") + .append(Binder.getCallingPid()).toString(); if (on) { if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, - AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, null, 0); + AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, + eventSource, 0); } mForcedUseForComm = AudioSystem.FORCE_SPEAKER; } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER){ @@ -2848,7 +2891,7 @@ public class AudioService extends IAudioService.Stub } sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, - AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0); + AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource, 0); } /** @see AudioManager#isSpeakerphoneOn() */ @@ -2861,10 +2904,14 @@ public class AudioService extends IAudioService.Stub if (!checkAudioSettingsPermission("setBluetoothScoOn()")) { return; } - setBluetoothScoOnInt(on); + // for logging only + final String eventSource = new StringBuilder("setBluetoothScoOn(").append(on) + .append(") from u/pid:").append(Binder.getCallingUid()).append("/") + .append(Binder.getCallingPid()).toString(); + setBluetoothScoOnInt(on, eventSource); } - public void setBluetoothScoOnInt(boolean on) { + public void setBluetoothScoOnInt(boolean on, String eventSource) { if (on) { mForcedUseForComm = AudioSystem.FORCE_BT_SCO; } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { @@ -2872,9 +2919,9 @@ public class AudioService extends IAudioService.Stub } sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, - AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0); + AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource, 0); sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, - AudioSystem.FOR_RECORD, mForcedUseForComm, null, 0); + AudioSystem.FOR_RECORD, mForcedUseForComm, eventSource, 0); } /** @see AudioManager#isBluetoothScoOn() */ @@ -2884,12 +2931,17 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#setBluetoothA2dpOn(boolean) */ public void setBluetoothA2dpOn(boolean on) { + // for logging only + final String eventSource = new StringBuilder("setBluetoothA2dpOn(").append(on) + .append(") from u/pid:").append(Binder.getCallingUid()).append("/") + .append(Binder.getCallingPid()).toString(); + synchronized (mBluetoothA2dpEnabledLock) { mBluetoothA2dpEnabled = on; sendMsg(mAudioHandler, MSG_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE, AudioSystem.FOR_MEDIA, mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP, - null, 0); + eventSource, 0); } } @@ -3226,7 +3278,7 @@ public class AudioService extends IAudioService.Stub broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); } AudioSystem.setParameters("A2dpSuspended=false"); - setBluetoothScoOnInt(false); + setBluetoothScoOnInt(false, "resetBluetoothSco"); } private void broadcastScoConnectionState(int state) { @@ -3988,7 +4040,7 @@ public class AudioService extends IAudioService.Stub /* * A class just for packaging up a set of connection parameters. */ - private class WiredDeviceConnectionState { + class WiredDeviceConnectionState { public final int mType; public final int mState; public final String mAddress; @@ -4837,9 +4889,9 @@ public class AudioService extends IAudioService.Stub } } - private void setForceUse(int usage, int config) { + private void setForceUse(int usage, int config, String eventSource) { synchronized (mConnectedDevices) { - setForceUseInt_SyncDevices(usage, config); + setForceUseInt_SyncDevices(usage, config, eventSource); } } @@ -4905,7 +4957,7 @@ public class AudioService extends IAudioService.Stub case MSG_SET_FORCE_USE: case MSG_SET_FORCE_BT_A2DP_USE: - setForceUse(msg.arg1, msg.arg2); + setForceUse(msg.arg1, msg.arg2, (String) msg.obj); break; case MSG_BT_HEADSET_CNCT_FAILED: @@ -4915,6 +4967,7 @@ public class AudioService extends IAudioService.Stub case MSG_SET_WIRED_DEVICE_CONNECTION_STATE: { WiredDeviceConnectionState connectState = (WiredDeviceConnectionState)msg.obj; + mWiredDevLogger.log(new WiredDevConnectEvent(connectState)); onSetWiredDeviceConnectionState(connectState.mType, connectState.mState, connectState.mAddress, connectState.mName, connectState.mCaller); mAudioEventWakeLock.release(); @@ -5062,7 +5115,7 @@ public class AudioService extends IAudioService.Stub // Did it change? if (mEncodedSurroundMode != newSurroundMode) { // Send to AudioPolicyManager - sendEncodedSurroundMode(newSurroundMode); + sendEncodedSurroundMode(newSurroundMode, "SettingsObserver"); synchronized(mConnectedDevices) { // Is HDMI connected? String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_HDMI, ""); @@ -5083,13 +5136,13 @@ public class AudioService extends IAudioService.Stub } // must be called synchronized on mConnectedDevices - private void makeA2dpDeviceAvailable(String address, String name) { + private void makeA2dpDeviceAvailable(String address, String name, String eventSource) { // enable A2DP before notifying A2DP connection to avoid unnecessary processing in // audio policy manager VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC]; sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, streamState, 0); - setBluetoothA2dpOnInt(true); + setBluetoothA2dpOnInt(true, eventSource); AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, AudioSystem.DEVICE_STATE_AVAILABLE, address, name); // Reset A2DP suspend state each time a new sink is connected @@ -5218,7 +5271,8 @@ public class AudioService extends IAudioService.Stub makeA2dpDeviceUnavailableNow(mDockAddress); } } - makeA2dpDeviceAvailable(address, btDevice.getName()); + makeA2dpDeviceAvailable(address, btDevice.getName(), + "onSetA2dpSinkConnectionState"); synchronized (mCurAudioRoutes) { String name = btDevice.getAliasName(); if (!TextUtils.equals(mCurAudioRoutes.bluetoothName, name)) { @@ -5450,15 +5504,30 @@ public class AudioService extends IAudioService.Stub } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE || device == AudioSystem.DEVICE_OUT_LINE) { intent.setAction(Intent.ACTION_HEADSET_PLUG); - intent.putExtra("microphone", (device & AudioSystem.DEVICE_BIT_IN) != 0 ? 1 : 0); + intent.putExtra("microphone", 0); } else if (device == AudioSystem.DEVICE_OUT_USB_HEADSET) { intent.setAction(Intent.ACTION_HEADSET_PLUG); - intent.putExtra("microphone", 0); + intent.putExtra("microphone", + AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_IN_USB_HEADSET, "") + == AudioSystem.DEVICE_STATE_AVAILABLE ? 1 : 0); + } else if (device == AudioSystem.DEVICE_IN_USB_HEADSET) { + if (AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_OUT_USB_HEADSET, "") + == AudioSystem.DEVICE_STATE_AVAILABLE) { + intent.setAction(Intent.ACTION_HEADSET_PLUG); + intent.putExtra("microphone", 1); + } else { + // do not send ACTION_HEADSET_PLUG when only the input side is seen as changing + return; + } } else if (device == AudioSystem.DEVICE_OUT_HDMI || device == AudioSystem.DEVICE_OUT_HDMI_ARC) { configureHdmiPlugIntent(intent, state); } + if (intent.getAction() == null) { + return; + } + intent.putExtra(CONNECT_INTENT_KEY_STATE, state); intent.putExtra(CONNECT_INTENT_KEY_ADDRESS, address); intent.putExtra(CONNECT_INTENT_KEY_PORT_NAME, deviceName); @@ -5490,7 +5559,7 @@ public class AudioService extends IAudioService.Stub synchronized (mConnectedDevices) { if ((state == 0) && ((device & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0)) { - setBluetoothA2dpOnInt(true); + setBluetoothA2dpOnInt(true, "onSetWiredDeviceConnectionState state 0"); } if (!handleDeviceConnection(state == 1, device, address, deviceName)) { @@ -5499,7 +5568,7 @@ public class AudioService extends IAudioService.Stub } if (state != 0) { if ((device & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0) { - setBluetoothA2dpOnInt(false); + setBluetoothA2dpOnInt(false, "onSetWiredDeviceConnectionState state not 0"); } if ((device & mSafeMediaVolumeDevices) != 0) { sendMsg(mAudioHandler, @@ -5532,9 +5601,7 @@ public class AudioService extends IAudioService.Stub } } } - if (device != AudioSystem.DEVICE_IN_WIRED_HEADSET) { - sendDeviceConnectionIntent(device, state, address, deviceName); - } + sendDeviceConnectionIntent(device, state, address, deviceName); updateAudioRoutes(device, state); } } @@ -5624,6 +5691,8 @@ public class AudioService extends IAudioService.Stub if (!((dockState == Intent.EXTRA_DOCK_STATE_LE_DESK) || ((dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) && (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK)))) { + mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_DOCK, config, + "ACTION_DOCK_EVENT intent")); AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config); } mDockState = dockState; @@ -5954,7 +6023,7 @@ public class AudioService extends IAudioService.Stub AudioSystem.FOR_SYSTEM, cameraSoundForced ? AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE, - null, + new String("handleConfigurationChanged"), 0); sendMsg(mAudioHandler, @@ -5997,21 +6066,23 @@ public class AudioService extends IAudioService.Stub // Handles request to override default use of A2DP for media. // Must be called synchronized on mConnectedDevices - public void setBluetoothA2dpOnInt(boolean on) { + public void setBluetoothA2dpOnInt(boolean on, String eventSource) { synchronized (mBluetoothA2dpEnabledLock) { mBluetoothA2dpEnabled = on; mAudioHandler.removeMessages(MSG_SET_FORCE_BT_A2DP_USE); setForceUseInt_SyncDevices(AudioSystem.FOR_MEDIA, - mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP); + mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP, + eventSource); } } // Must be called synchronized on mConnectedDevices - private void setForceUseInt_SyncDevices(int usage, int config) { + private void setForceUseInt_SyncDevices(int usage, int config, String eventSource) { if (usage == AudioSystem.FOR_MEDIA) { sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, SENDMSG_NOOP, 0, 0, null, 0); } + mForceUseLogger.log(new ForceUseEvent(usage, config, eventSource)); AudioSystem.setForceUse(usage, config); } @@ -6216,9 +6287,11 @@ public class AudioService extends IAudioService.Stub synchronized (mHdmiTvClient) { if (mHdmiSystemAudioSupported != on) { mHdmiSystemAudioSupported = on; - AudioSystem.setForceUse(AudioSystem.FOR_HDMI_SYSTEM_AUDIO, - on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED : - AudioSystem.FORCE_NONE); + final int config = on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED : + AudioSystem.FORCE_NONE; + mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_HDMI_SYSTEM_AUDIO, + config, "setHdmiSystemAudioSupported")); + AudioSystem.setForceUse(AudioSystem.FOR_HDMI_SYSTEM_AUDIO, config); } device = getDevicesForStream(AudioSystem.STREAM_MUSIC); } @@ -6316,6 +6389,29 @@ public class AudioService extends IAudioService.Stub } } + //========================================================================================== + // AudioService logging and dumpsys + //========================================================================================== + final int LOG_NB_EVENTS_PHONE_STATE = 20; + final int LOG_NB_EVENTS_WIRED_DEV_CONNECTION = 30; + final int LOG_NB_EVENTS_FORCE_USE = 20; + final int LOG_NB_EVENTS_VOLUME = 40; + + final private AudioEventLogger mModeLogger = new AudioEventLogger(LOG_NB_EVENTS_PHONE_STATE, + "phone state (logged after successfull call to AudioSystem.setPhoneState(int))"); + + final private AudioEventLogger mWiredDevLogger = new AudioEventLogger( + LOG_NB_EVENTS_WIRED_DEV_CONNECTION, + "wired device connection (logged before onSetWiredDeviceConnectionState() is executed)" + ); + + final private AudioEventLogger mForceUseLogger = new AudioEventLogger( + LOG_NB_EVENTS_FORCE_USE, + "force use (logged before setForceUse() is executed)"); + + final private AudioEventLogger mVolumeLogger = new AudioEventLogger(LOG_NB_EVENTS_VOLUME, + "volume changes (logged when command received by AudioService)"); + private static final String[] RINGER_MODE_NAMES = new String[] { "SILENT", "VIBRATE", @@ -6386,6 +6482,16 @@ public class AudioService extends IAudioService.Stub mPlaybackMonitor.dump(pw); mRecordMonitor.dump(pw); + + pw.println("\n"); + pw.println("\nEvent logs:"); + mModeLogger.dump(pw); + pw.println("\n"); + mWiredDevLogger.dump(pw); + pw.println("\n"); + mForceUseLogger.dump(pw); + pw.println("\n"); + mVolumeLogger.dump(pw); } private static String safeMediaVolumeStateToString(Integer state) { @@ -6878,6 +6984,10 @@ public class AudioService extends IAudioService.Stub mPlaybackMonitor.playerEvent(piid, event, Binder.getCallingUid()); } + public void playerHasOpPlayAudio(int piid, boolean hasOpPlayAudio) { + mPlaybackMonitor.playerHasOpPlayAudio(piid, hasOpPlayAudio, Binder.getCallingUid()); + } + public void releasePlayer(int piid) { mPlaybackMonitor.releasePlayer(piid, Binder.getCallingUid()); } diff --git a/services/core/java/com/android/server/audio/AudioServiceEvents.java b/services/core/java/com/android/server/audio/AudioServiceEvents.java new file mode 100644 index 000000000000..634c8c27a3cc --- /dev/null +++ b/services/core/java/com/android/server/audio/AudioServiceEvents.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.audio; + +import android.media.AudioManager; +import android.media.AudioSystem; + +import com.android.server.audio.AudioService.WiredDeviceConnectionState; + + +public class AudioServiceEvents { + + final static class PhoneStateEvent extends AudioEventLogger.Event { + final String mPackage; + final int mPid; + final int mMode; + + PhoneStateEvent(String callingPackage, int pid, int mode) { + mPackage = callingPackage; + mPid = pid; + mMode = mode; + } + + @Override + public String eventToString() { + return new StringBuilder("setMode(").append(AudioSystem.modeToString(mMode)) + .append(") from package=").append(mPackage) + .append(" pid=").append(mPid).toString(); + } + } + + final static class WiredDevConnectEvent extends AudioEventLogger.Event { + final WiredDeviceConnectionState mState; + + WiredDevConnectEvent(WiredDeviceConnectionState state) { + mState = state; + } + + @Override + public String eventToString() { + return new StringBuilder("setWiredDeviceConnectionState(") + .append(" type:").append(Integer.toHexString(mState.mType)) + .append(" state:").append(AudioSystem.deviceStateToString(mState.mState)) + .append(" addr:").append(mState.mAddress) + .append(" name:").append(mState.mName) + .append(") from ").append(mState.mCaller).toString(); + } + } + + final static class ForceUseEvent extends AudioEventLogger.Event { + final int mUsage; + final int mConfig; + final String mReason; + + ForceUseEvent(int usage, int config, String reason) { + mUsage = usage; + mConfig = config; + mReason = reason; + } + + @Override + public String eventToString() { + return new StringBuilder("setForceUse(") + .append(AudioSystem.forceUseUsageToString(mUsage)) + .append(", ").append(AudioSystem.forceUseConfigToString(mConfig)) + .append(") due to ").append(mReason).toString(); + } + } + + final static class VolumeEvent extends AudioEventLogger.Event { + final static int VOL_ADJUST_SUGG_VOL = 0; + final static int VOL_ADJUST_STREAM_VOL = 1; + final static int VOL_SET_STREAM_VOL = 2; + + final int mOp; + final int mStream; + final int mVal1; + final int mVal2; + final String mCaller; + + VolumeEvent(int op, int stream, int val1, int val2, String caller) { + mOp = op; + mStream = stream; + mVal1 = val1; + mVal2 = val2; + mCaller = caller; + } + + @Override + public String eventToString() { + switch (mOp) { + case VOL_ADJUST_SUGG_VOL: + return new StringBuilder("adjustSuggestedStreamVolume(sugg:") + .append(AudioSystem.streamToString(mStream)) + .append(" dir:").append(AudioManager.adjustToString(mVal1)) + .append(" flags:0x").append(Integer.toHexString(mVal2)) + .append(") from ").append(mCaller) + .toString(); + case VOL_ADJUST_STREAM_VOL: + return new StringBuilder("adjustStreamVolume(stream:") + .append(AudioSystem.streamToString(mStream)) + .append(" dir:").append(AudioManager.adjustToString(mVal1)) + .append(" flags:0x").append(Integer.toHexString(mVal2)) + .append(") from ").append(mCaller) + .toString(); + case VOL_SET_STREAM_VOL: + return new StringBuilder("setStreamVolume(stream:") + .append(AudioSystem.streamToString(mStream)) + .append(" index:").append(mVal1) + .append(" flags:0x").append(Integer.toHexString(mVal2)) + .append(") from ").append(mCaller) + .toString(); + default: return new StringBuilder("FIXME invalid op:").append(mOp).toString(); + } + } + } +} diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java index 9ef45ea56dfe..3e5eed320ccd 100644 --- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java +++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java @@ -104,6 +104,9 @@ public final class PlaybackActivityMonitor final int index = mBannedUids.indexOf(new Integer(uid)); if (index >= 0) { if (!disable) { + if (DEBUG) { // hidden behind DEBUG, too noisy otherwise + mEventLogger.log(new AudioEventLogger.StringEvent("unbanning uid:" + uid)); + } mBannedUids.remove(index); // nothing else to do, future playback requests from this uid are ok } // no else to handle, uid already present, so disabling again is no-op @@ -112,6 +115,9 @@ public final class PlaybackActivityMonitor for (AudioPlaybackConfiguration apc : mPlayers.values()) { checkBanPlayer(apc, uid); } + if (DEBUG) { // hidden behind DEBUG, too noisy otherwise + mEventLogger.log(new AudioEventLogger.StringEvent("banning uid:" + uid)); + } mBannedUids.add(new Integer(uid)); } // no else to handle, uid already not in list, so enabling again is no-op } @@ -145,6 +151,7 @@ public final class PlaybackActivityMonitor new AudioPlaybackConfiguration(pic, newPiid, Binder.getCallingUid(), Binder.getCallingPid()); apc.init(); + mEventLogger.log(new NewPlayerEvent(apc)); synchronized(mPlayerLock) { mPlayers.put(newPiid, apc); } @@ -156,6 +163,7 @@ public final class PlaybackActivityMonitor synchronized(mPlayerLock) { final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid)); if (checkConfigurationCaller(piid, apc, binderUid)) { + mEventLogger.log(new AudioAttrEvent(piid, attr)); change = apc.handleAudioAttributesEvent(attr); } else { Log.e(TAG, "Error updating audio attributes"); @@ -175,10 +183,13 @@ public final class PlaybackActivityMonitor if (apc == null) { return; } + mEventLogger.log(new PlayerEvent(piid, event)); if (event == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) { for (Integer uidInteger: mBannedUids) { if (checkBanPlayer(apc, uidInteger.intValue())) { // player was banned, do not update its state + mEventLogger.log(new AudioEventLogger.StringEvent( + "not starting piid:" + piid + " ,is banned")); return; } } @@ -203,11 +214,18 @@ public final class PlaybackActivityMonitor } } + public void playerHasOpPlayAudio(int piid, boolean hasOpPlayAudio, int binderUid) { + // no check on UID yet because this is only for logging at the moment + mEventLogger.log(new PlayerOpPlayAudioEvent(piid, hasOpPlayAudio, binderUid)); + } + public void releasePlayer(int piid, int binderUid) { if (DEBUG) { Log.v(TAG, "releasePlayer() for piid=" + piid); } synchronized(mPlayerLock) { final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid)); if (checkConfigurationCaller(piid, apc, binderUid)) { + mEventLogger.log(new AudioEventLogger.StringEvent( + "releasing player piid:" + piid)); mPlayers.remove(new Integer(piid)); mDuckingManager.removeReleased(apc); } @@ -250,6 +268,8 @@ public final class PlaybackActivityMonitor pw.print(" " + uid); } pw.println(); + // log + mEventLogger.dump(pw); } } @@ -672,4 +692,85 @@ public final class PlaybackActivityMonitor } } } + + //================================================================= + // For logging + private final static class PlayerEvent extends AudioEventLogger.Event { + // only keeping the player interface ID as it uniquely identifies the player in the event + final int mPlayerIId; + final int mState; + + PlayerEvent(int piid, int state) { + mPlayerIId = piid; + mState = state; + } + + @Override + public String eventToString() { + return new StringBuilder("player piid:").append(mPlayerIId).append(" state:") + .append(AudioPlaybackConfiguration.toLogFriendlyPlayerState(mState)).toString(); + } + } + + private final static class PlayerOpPlayAudioEvent extends AudioEventLogger.Event { + // only keeping the player interface ID as it uniquely identifies the player in the event + final int mPlayerIId; + final boolean mHasOp; + final int mUid; + + PlayerOpPlayAudioEvent(int piid, boolean hasOp, int uid) { + mPlayerIId = piid; + mHasOp = hasOp; + mUid = uid; + } + + @Override + public String eventToString() { + return new StringBuilder("player piid:").append(mPlayerIId) + .append(" has OP_PLAY_AUDIO:").append(mHasOp) + .append(" in uid:").append(mUid).toString(); + } + } + + private final static class NewPlayerEvent extends AudioEventLogger.Event { + private final int mPlayerIId; + private final int mPlayerType; + private final int mClientUid; + private final int mClientPid; + private final AudioAttributes mPlayerAttr; + + NewPlayerEvent(AudioPlaybackConfiguration apc) { + mPlayerIId = apc.getPlayerInterfaceId(); + mPlayerType = apc.getPlayerType(); + mClientUid = apc.getClientUid(); + mClientPid = apc.getClientPid(); + mPlayerAttr = apc.getAudioAttributes(); + } + + @Override + public String eventToString() { + return new String("new player piid:" + mPlayerIId + " uid/pid:" + mClientUid + "/" + + mClientPid + " type:" + + AudioPlaybackConfiguration.toLogFriendlyPlayerType(mPlayerType) + + " attr:" + mPlayerAttr); + } + } + + private final static class AudioAttrEvent extends AudioEventLogger.Event { + private final int mPlayerIId; + private final AudioAttributes mPlayerAttr; + + AudioAttrEvent(int piid, AudioAttributes attr) { + mPlayerIId = piid; + mPlayerAttr = attr; + } + + @Override + public String eventToString() { + return new String("player piid:" + mPlayerIId + " new AudioAttributes:" + mPlayerAttr); + } + } + + private final AudioEventLogger mEventLogger = new AudioEventLogger(100, + "playback activity as reported through PlayerBase"); } diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index b3908847137a..f8d23d4c8d51 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -16,9 +16,6 @@ package com.android.server.connectivity; -import java.net.Inet4Address; - -import android.content.Context; import android.net.InterfaceConfiguration; import android.net.ConnectivityManager; import android.net.LinkAddress; @@ -34,18 +31,22 @@ import android.util.Slog; import com.android.server.net.BaseNetworkObserver; import com.android.internal.util.ArrayUtils; +import java.net.Inet4Address; +import java.util.Objects; + /** - * @hide - * * Class to manage a 464xlat CLAT daemon. + * + * @hide */ public class Nat464Xlat extends BaseNetworkObserver { - private static final String TAG = "Nat464Xlat"; + private static final String TAG = Nat464Xlat.class.getSimpleName(); // This must match the interface prefix in clatd.c. private static final String CLAT_PREFIX = "v4-"; - // The network types we will start clatd on. + // The network types we will start clatd on, + // allowing clat only on networks for which we can support IPv6-only. private static final int[] NETWORK_TYPES = { ConnectivityManager.TYPE_MOBILE, ConnectivityManager.TYPE_WIFI, @@ -60,25 +61,20 @@ public class Nat464Xlat extends BaseNetworkObserver { // The network we're running on, and its type. private final NetworkAgentInfo mNetwork; - // Internal state variables. - // - // The possible states are: - // - Idle: start() not called. Everything is null. - // - Starting: start() called. Interfaces are non-null. isStarted() returns true. - // mIsRunning is false. - // - Running: start() called, and interfaceLinkStateChanged() told us that mIface is up. - // mIsRunning is true. - // + private enum State { + IDLE, // start() not called. Base iface and stacked iface names are null. + STARTING, // start() called. Base iface and stacked iface names are known. + RUNNING; // start() called, and the stacked iface is known to be up. + } + // Once mIface is non-null and isStarted() is true, methods called by ConnectivityService on // its handler thread must not modify any internal state variables; they are only updated by the // interface observers, called on the notification threads. private String mBaseIface; private String mIface; - private boolean mIsRunning; + private volatile State mState = State.IDLE; - public Nat464Xlat( - Context context, INetworkManagementService nmService, - Handler handler, NetworkAgentInfo nai) { + public Nat464Xlat(INetworkManagementService nmService, Handler handler, NetworkAgentInfo nai) { mNMService = nmService; mHandler = handler; mNetwork = nai; @@ -90,30 +86,47 @@ public class Nat464Xlat extends BaseNetworkObserver { * @return true if the network requires clat, false otherwise. */ public static boolean requiresClat(NetworkAgentInfo nai) { + // TODO: migrate to NetworkCapabilities.TRANSPORT_*. final int netType = nai.networkInfo.getType(); + final boolean supported = ArrayUtils.contains(NETWORK_TYPES, nai.networkInfo.getType()); final boolean connected = nai.networkInfo.isConnected(); + // We only run clat on networks that don't have a native IPv4 address. final boolean hasIPv4Address = - (nai.linkProperties != null) ? nai.linkProperties.hasIPv4Address() : false; - // Only support clat on mobile and wifi for now, because these are the only IPv6-only - // networks we can connect to. - return connected && !hasIPv4Address && ArrayUtils.contains(NETWORK_TYPES, netType); + (nai.linkProperties != null) && nai.linkProperties.hasIPv4Address(); + return supported && connected && !hasIPv4Address; } /** - * Determines whether clatd is started. Always true, except a) if start has not yet been called, - * or b) if our interface was removed. + * @return true if clatd has been started and has not yet stopped. + * A true result corresponds to internal states STARTING and RUNNING. */ public boolean isStarted() { - return mIface != null; + return mState != State.IDLE; + } + + /** + * @return true if clatd has been started and the stacked interface is up. + */ + public boolean isRunning() { + return mState == State.RUNNING; + } + + /** + * Sets internal state. + */ + private void enterStartingState(String baseIface) { + mIface = CLAT_PREFIX + baseIface; + mBaseIface = baseIface; + mState = State.STARTING; } /** * Clears internal state. Must not be called by ConnectivityService. */ - private void clear() { + private void enterIdleState() { mIface = null; mBaseIface = null; - mIsRunning = false; + mState = State.IDLE; } /** @@ -137,19 +150,19 @@ public class Nat464Xlat extends BaseNetworkObserver { return; } - mBaseIface = mNetwork.linkProperties.getInterfaceName(); - if (mBaseIface == null) { + String baseIface = mNetwork.linkProperties.getInterfaceName(); + if (baseIface == null) { Slog.e(TAG, "startClat: Can't start clat on null interface"); return; } - mIface = CLAT_PREFIX + mBaseIface; - // From now on, isStarted() will return true. + // TODO: should we only do this if mNMService.startClatd() succeeds? + enterStartingState(baseIface); Slog.i(TAG, "Starting clatd on " + mBaseIface); try { mNMService.startClatd(mBaseIface); } catch(RemoteException|IllegalStateException e) { - Slog.e(TAG, "Error starting clatd: " + e); + Slog.e(TAG, "Error starting clatd on " + mBaseIface, e); } } @@ -157,18 +170,19 @@ public class Nat464Xlat extends BaseNetworkObserver { * Stops the clat daemon. Called by ConnectivityService on the handler thread. */ public void stop() { - if (isStarted()) { - Slog.i(TAG, "Stopping clatd"); - try { - mNMService.stopClatd(mBaseIface); - } catch(RemoteException|IllegalStateException e) { - Slog.e(TAG, "Error stopping clatd: " + e); - } - // When clatd stops and its interface is deleted, interfaceRemoved() will notify - // ConnectivityService and call clear(). - } else { - Slog.e(TAG, "clatd: already stopped"); + if (!isStarted()) { + Slog.e(TAG, "stopClat: already stopped or not started"); + return; + } + + Slog.i(TAG, "Stopping clatd on " + mBaseIface); + try { + mNMService.stopClatd(mBaseIface); + } catch(RemoteException|IllegalStateException e) { + Slog.e(TAG, "Error stopping clatd on " + mBaseIface, e); } + // When clatd stops and its interface is deleted, interfaceRemoved() will notify + // ConnectivityService and call enterIdleState(). } private void updateConnectivityService(LinkProperties lp) { @@ -184,16 +198,19 @@ public class Nat464Xlat extends BaseNetworkObserver { * has no idea that 464xlat is running on top of it. */ public void fixupLinkProperties(LinkProperties oldLp) { - if (mNetwork.clatd != null && - mIsRunning && - mNetwork.linkProperties != null && - !mNetwork.linkProperties.getAllInterfaceNames().contains(mIface)) { - Slog.d(TAG, "clatd running, updating NAI for " + mIface); - for (LinkProperties stacked: oldLp.getStackedLinks()) { - if (mIface.equals(stacked.getInterfaceName())) { - mNetwork.linkProperties.addStackedLink(stacked); - break; - } + if (!isRunning()) { + return; + } + LinkProperties lp = mNetwork.linkProperties; + if (lp == null || lp.getAllInterfaceNames().contains(mIface)) { + return; + } + + Slog.d(TAG, "clatd running, updating NAI for " + mIface); + for (LinkProperties stacked: oldLp.getStackedLinks()) { + if (Objects.equals(mIface, stacked.getInterfaceName())) { + lp.addStackedLink(stacked); + return; } } } @@ -227,6 +244,7 @@ public class Nat464Xlat extends BaseNetworkObserver { } private void maybeSetIpv6NdOffload(String iface, boolean on) { + // TODO: migrate to NetworkCapabilities.TRANSPORT_*. if (mNetwork.networkInfo.getType() != ConnectivityManager.TYPE_WIFI) { return; } @@ -238,52 +256,64 @@ public class Nat464Xlat extends BaseNetworkObserver { } } + /** + * Adds stacked link on base link and transitions to Running state + * This is called by the InterfaceObserver on its own thread, so can race with stop(). + */ @Override public void interfaceLinkStateChanged(String iface, boolean up) { - // Called by the InterfaceObserver on its own thread, so can race with stop(). - if (isStarted() && up && mIface.equals(iface)) { - Slog.i(TAG, "interface " + iface + " is up, mIsRunning " + mIsRunning + "->true"); - - if (!mIsRunning) { - LinkAddress clatAddress = getLinkAddress(iface); - if (clatAddress == null) { - return; - } - mIsRunning = true; - maybeSetIpv6NdOffload(mBaseIface, false); - LinkProperties lp = new LinkProperties(mNetwork.linkProperties); - lp.addStackedLink(makeLinkProperties(clatAddress)); - Slog.i(TAG, "Adding stacked link " + mIface + " on top of " + mBaseIface); - updateConnectivityService(lp); - } + if (!isStarted() || !up || !Objects.equals(mIface, iface)) { + return; + } + if (isRunning()) { + return; + } + LinkAddress clatAddress = getLinkAddress(iface); + if (clatAddress == null) { + return; } + mState = State.RUNNING; + Slog.i(TAG, String.format("interface %s is up, adding stacked link %s on top of %s", + mIface, mIface, mBaseIface)); + + maybeSetIpv6NdOffload(mBaseIface, false); + LinkProperties lp = new LinkProperties(mNetwork.linkProperties); + lp.addStackedLink(makeLinkProperties(clatAddress)); + updateConnectivityService(lp); } @Override public void interfaceRemoved(String iface) { - if (isStarted() && mIface.equals(iface)) { - Slog.i(TAG, "interface " + iface + " removed, mIsRunning " + mIsRunning + "->false"); - - if (mIsRunning) { - // The interface going away likely means clatd has crashed. Ask netd to stop it, - // because otherwise when we try to start it again on the same base interface netd - // will complain that it's already started. - // - // Note that this method can be called by the interface observer at the same time - // that ConnectivityService calls stop(). In this case, the second call to - // stopClatd() will just throw IllegalStateException, which we'll ignore. - try { - mNMService.unregisterObserver(this); - mNMService.stopClatd(mBaseIface); - } catch (RemoteException|IllegalStateException e) { - // Well, we tried. - } - maybeSetIpv6NdOffload(mBaseIface, true); - LinkProperties lp = new LinkProperties(mNetwork.linkProperties); - lp.removeStackedLink(mIface); - clear(); - updateConnectivityService(lp); - } + if (!isStarted() || !Objects.equals(mIface, iface)) { + return; + } + if (!isRunning()) { + return; } + + Slog.i(TAG, "interface " + iface + " removed"); + // The interface going away likely means clatd has crashed. Ask netd to stop it, + // because otherwise when we try to start it again on the same base interface netd + // will complain that it's already started. + // + // Note that this method can be called by the interface observer at the same time + // that ConnectivityService calls stop(). In this case, the second call to + // stopClatd() will just throw IllegalStateException, which we'll ignore. + try { + mNMService.unregisterObserver(this); + mNMService.stopClatd(mBaseIface); + } catch (RemoteException|IllegalStateException e) { + // Well, we tried. + } + maybeSetIpv6NdOffload(mBaseIface, true); + LinkProperties lp = new LinkProperties(mNetwork.linkProperties); + lp.removeStackedLink(mIface); + enterIdleState(); + updateConnectivityService(lp); + } + + @Override + public String toString() { + return "mBaseIface: " + mBaseIface + ", mIface: " + mIface + ", mState: " + mState; } } diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 2a618bcc2eac..872923a03256 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -562,13 +562,13 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { "acceptUnvalidated{" + networkMisc.acceptUnvalidated + "} " + "everCaptivePortalDetected{" + everCaptivePortalDetected + "} " + "lastCaptivePortalDetected{" + lastCaptivePortalDetected + "} " + + "clat{" + clatd + "} " + "}"; } public String name() { return "NetworkAgentInfo [" + networkInfo.getTypeName() + " (" + - networkInfo.getSubtypeName() + ") - " + - (network == null ? "null" : network.toString()) + "]"; + networkInfo.getSubtypeName() + ") - " + Objects.toString(network) + "]"; } // Enables sorting in descending order of score. diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java index 836d61aa58ee..5583e86cde70 100644 --- a/services/core/java/com/android/server/connectivity/Tethering.java +++ b/services/core/java/com/android/server/connectivity/Tethering.java @@ -49,6 +49,7 @@ import android.net.ConnectivityManager; import android.net.INetworkPolicyManager; import android.net.INetworkStatsService; import android.net.IpPrefix; +import android.net.LinkAddress; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; @@ -1252,6 +1253,7 @@ public class Tethering extends BaseNetworkObserver { // to tear itself down. private final ArrayList<TetherInterfaceStateMachine> mNotifyList; private final IPv6TetheringCoordinator mIPv6TetheringCoordinator; + private final OffloadWrapper mOffload; private static final int UPSTREAM_SETTLE_TIME_MS = 10000; @@ -1276,33 +1278,11 @@ public class Tethering extends BaseNetworkObserver { mNotifyList = new ArrayList<>(); mIPv6TetheringCoordinator = new IPv6TetheringCoordinator(mNotifyList, mLog); + mOffload = new OffloadWrapper(); setInitialState(mInitialState); } - private void startOffloadController() { - mOffloadController.start(); - sendOffloadExemptPrefixes(); - } - - private void sendOffloadExemptPrefixes() { - sendOffloadExemptPrefixes(mUpstreamNetworkMonitor.getLocalPrefixes()); - } - - private void sendOffloadExemptPrefixes(Set<IpPrefix> localPrefixes) { - // Add in well-known minimum set. - PrefixUtils.addNonForwardablePrefixes(localPrefixes); - // Add tragically hardcoded prefixes. - localPrefixes.add(PrefixUtils.DEFAULT_WIFI_P2P_PREFIX); - - // Add prefixes for all downstreams, regardless of IP serving mode. - for (TetherInterfaceStateMachine tism : mNotifyList) { - localPrefixes.addAll(PrefixUtils.localPrefixesFrom(tism.linkProperties())); - } - - mOffloadController.setLocalPrefixes(localPrefixes); - } - class InitialState extends State { @Override public boolean processMessage(Message message) { @@ -1460,7 +1440,7 @@ public class Tethering extends BaseNetworkObserver { protected void handleNewUpstreamNetworkState(NetworkState ns) { mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns); - mOffloadController.setUpstreamLinkProperties((ns != null) ? ns.linkProperties : null); + mOffload.updateUpstreamNetworkState(ns); } private void handleInterfaceServingStateActive(int mode, TetherInterfaceStateMachine who) { @@ -1470,9 +1450,12 @@ public class Tethering extends BaseNetworkObserver { } if (mode == IControlsTethering.STATE_TETHERED) { + // No need to notify OffloadController just yet as there are no + // "offload-able" prefixes to pass along. This will handled + // when the TISM informs Tethering of its LinkProperties. mForwardedDownstreams.add(who); } else { - mOffloadController.removeDownstreamInterface(who.interfaceName()); + mOffload.excludeDownstreamInterface(who.interfaceName()); mForwardedDownstreams.remove(who); } @@ -1497,7 +1480,7 @@ public class Tethering extends BaseNetworkObserver { private void handleInterfaceServingStateInactive(TetherInterfaceStateMachine who) { mNotifyList.remove(who); mIPv6TetheringCoordinator.removeActiveDownstream(who); - mOffloadController.removeDownstreamInterface(who.interfaceName()); + mOffload.excludeDownstreamInterface(who.interfaceName()); mForwardedDownstreams.remove(who); // If this is a Wi-Fi interface, tell WifiManager of any errors. @@ -1511,7 +1494,7 @@ public class Tethering extends BaseNetworkObserver { private void handleUpstreamNetworkMonitorCallback(int arg1, Object o) { if (arg1 == UpstreamNetworkMonitor.NOTIFY_LOCAL_PREFIXES) { - sendOffloadExemptPrefixes((Set<IpPrefix>) o); + mOffload.sendOffloadExemptPrefixes((Set<IpPrefix>) o); return; } @@ -1581,7 +1564,7 @@ public class Tethering extends BaseNetworkObserver { // TODO: De-duplicate with updateUpstreamWanted() below. if (upstreamWanted()) { mUpstreamWanted = true; - startOffloadController(); + mOffload.start(); chooseUpstreamType(true); mTryCell = false; } @@ -1589,7 +1572,7 @@ public class Tethering extends BaseNetworkObserver { @Override public void exit() { - mOffloadController.stop(); + mOffload.stop(); mUpstreamNetworkMonitor.stop(); mSimChange.stopListening(); notifyDownstreamsOfNewUpstreamIface(null); @@ -1601,9 +1584,9 @@ public class Tethering extends BaseNetworkObserver { mUpstreamWanted = upstreamWanted(); if (mUpstreamWanted != previousUpstreamWanted) { if (mUpstreamWanted) { - startOffloadController(); + mOffload.start(); } else { - mOffloadController.stop(); + mOffload.stop(); } } return previousUpstreamWanted; @@ -1658,12 +1641,9 @@ public class Tethering extends BaseNetworkObserver { case EVENT_IFACE_UPDATE_LINKPROPERTIES: { final LinkProperties newLp = (LinkProperties) message.obj; if (message.arg1 == IControlsTethering.STATE_TETHERED) { - mOffloadController.notifyDownstreamLinkProperties(newLp); + mOffload.updateDownstreamLinkProperties(newLp); } else { - mOffloadController.removeDownstreamInterface(newLp.getInterfaceName()); - // Another interface might be in local-only hotspot mode; - // resend all local prefixes to the OffloadController. - sendOffloadExemptPrefixes(); + mOffload.excludeDownstreamInterface(newLp.getInterfaceName()); } break; } @@ -1778,6 +1758,82 @@ public class Tethering extends BaseNetworkObserver { } catch (Exception e) {} } } + + // A wrapper class to handle multiple situations where several calls to + // the OffloadController need to happen together. + // + // TODO: This suggests that the interface between OffloadController and + // Tethering is in need of improvement. Refactor these calls into the + // OffloadController implementation. + class OffloadWrapper { + public void start() { + mOffloadController.start(); + sendOffloadExemptPrefixes(); + } + + public void stop() { + mOffloadController.stop(); + } + + public void updateUpstreamNetworkState(NetworkState ns) { + mOffloadController.setUpstreamLinkProperties( + (ns != null) ? ns.linkProperties : null); + } + + public void updateDownstreamLinkProperties(LinkProperties newLp) { + // Update the list of offload-exempt prefixes before adding + // new prefixes on downstream interfaces to the offload HAL. + sendOffloadExemptPrefixes(); + mOffloadController.notifyDownstreamLinkProperties(newLp); + } + + public void excludeDownstreamInterface(String ifname) { + // This and other interfaces may be in local-only hotspot mode; + // resend all local prefixes to the OffloadController. + sendOffloadExemptPrefixes(); + mOffloadController.removeDownstreamInterface(ifname); + } + + public void sendOffloadExemptPrefixes() { + sendOffloadExemptPrefixes(mUpstreamNetworkMonitor.getLocalPrefixes()); + } + + public void sendOffloadExemptPrefixes(final Set<IpPrefix> localPrefixes) { + // Add in well-known minimum set. + PrefixUtils.addNonForwardablePrefixes(localPrefixes); + // Add tragically hardcoded prefixes. + localPrefixes.add(PrefixUtils.DEFAULT_WIFI_P2P_PREFIX); + + // Maybe add prefixes or addresses for downstreams, depending on + // the IP serving mode of each. + for (TetherInterfaceStateMachine tism : mNotifyList) { + final LinkProperties lp = tism.linkProperties(); + + switch (tism.servingMode()) { + case IControlsTethering.STATE_UNAVAILABLE: + case IControlsTethering.STATE_AVAILABLE: + // No usable LinkProperties in these states. + continue; + case IControlsTethering.STATE_TETHERED: + // Only add IPv4 /32 and IPv6 /128 prefixes. The + // directly-connected prefixes will be sent as + // downstream "offload-able" prefixes. + for (LinkAddress addr : lp.getAllLinkAddresses()) { + final InetAddress ip = addr.getAddress(); + if (ip.isLinkLocalAddress()) continue; + localPrefixes.add(PrefixUtils.ipAddressAsPrefix(ip)); + } + break; + case IControlsTethering.STATE_LOCAL_ONLY: + // Add prefixes covering all local IPs. + localPrefixes.addAll(PrefixUtils.localPrefixesFrom(lp)); + break; + } + } + + mOffloadController.setLocalPrefixes(localPrefixes); + } + } } @Override diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index e82eabfe5ad9..a44b18dc2d8c 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -305,8 +305,8 @@ public class Vpn { * In order to support the always-on feature, an app has to * <ul> * <li>target {@link VERSION_CODES#N API 24} or above, and - * <li>not opt out through the {@link VpnService#METADATA_SUPPORTS_ALWAYS_ON} meta-data - * field. + * <li>not opt out through the {@link VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON} + * meta-data field. * </ul> * * @param packageName the canonical package name of the VPN app @@ -340,8 +340,8 @@ public class Vpn { for (ResolveInfo rInfo : services) { final Bundle metaData = rInfo.serviceInfo.metaData; - if (metaData != null - && !metaData.getBoolean(VpnService.METADATA_SUPPORTS_ALWAYS_ON, true)) { + if (metaData != null && + !metaData.getBoolean(VpnService.SERVICE_META_DATA_SUPPORTS_ALWAYS_ON, true)) { return false; } } @@ -1416,7 +1416,11 @@ public class Vpn { notificationManager.cancelAsUser(TAG, SystemMessage.NOTE_VPN_DISCONNECTED, user); return; } - final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS); + final Intent intent = new Intent(); + intent.setComponent(ComponentName.unflattenFromString(mContext.getString( + R.string.config_customVpnAlwaysOnDisconnectedDialogComponent))); + intent.putExtra("lockdown", mLockdown); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); final PendingIntent configIntent = mSystemServices.pendingIntentGetActivityAsUser( intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT, user); final Notification.Builder builder = diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java index 1a5ff778010c..6d5c428e58f8 100644 --- a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java +++ b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java @@ -17,7 +17,9 @@ package com.android.server.connectivity.tethering; import static android.net.NetworkStats.SET_DEFAULT; +import static android.net.NetworkStats.STATS_PER_UID; import static android.net.NetworkStats.TAG_NONE; +import static android.net.NetworkStats.UID_ALL; import static android.net.TrafficStats.UID_TETHERING; import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED; @@ -30,11 +32,13 @@ import android.net.NetworkStats; import android.net.RouteInfo; import android.net.util.SharedLog; import android.os.Handler; +import android.os.Looper; import android.os.INetworkManagementService; import android.os.RemoteException; import android.os.SystemClock; import android.provider.Settings; import android.text.TextUtils; +import com.android.server.connectivity.tethering.OffloadHardwareInterface.ForwardedStats; import com.android.internal.util.IndentingPrintWriter; @@ -44,9 +48,11 @@ import java.net.InetAddress; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; -import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; /** @@ -58,12 +64,13 @@ import java.util.concurrent.TimeUnit; public class OffloadController { private static final String TAG = OffloadController.class.getSimpleName(); - private static final int STATS_FETCH_TIMEOUT_MS = 1000; - private final Handler mHandler; private final OffloadHardwareInterface mHwInterface; private final ContentResolver mContentResolver; + private final INetworkManagementService mNms; + private final ITetheringStatsProvider mStatsProvider; private final SharedLog mLog; + private final HashMap<String, LinkProperties> mDownstreams; private boolean mConfigInitialized; private boolean mControlInitialized; private LinkProperties mUpstreamLinkProperties; @@ -76,21 +83,31 @@ public class OffloadController { private Set<String> mLastLocalPrefixStrs; // Maps upstream interface names to offloaded traffic statistics. - private HashMap<String, OffloadHardwareInterface.ForwardedStats> - mForwardedStats = new HashMap<>(); + // Always contains the latest value received from the hardware for each interface, regardless of + // whether offload is currently running on that interface. + private ConcurrentHashMap<String, ForwardedStats> mForwardedStats = + new ConcurrentHashMap<>(16, 0.75F, 1); + + // Maps upstream interface names to interface quotas. + // Always contains the latest value received from the framework for each interface, regardless + // of whether offload is currently running (or is even supported) on that interface. Only + // includes upstream interfaces that have a quota set. + private HashMap<String, Long> mInterfaceQuotas = new HashMap<>(); public OffloadController(Handler h, OffloadHardwareInterface hwi, ContentResolver contentResolver, INetworkManagementService nms, SharedLog log) { mHandler = h; mHwInterface = hwi; mContentResolver = contentResolver; + mNms = nms; + mStatsProvider = new OffloadTetheringStatsProvider(); mLog = log.forSubComponent(TAG); + mDownstreams = new HashMap<>(); mExemptPrefixes = new HashSet<>(); mLastLocalPrefixStrs = new HashSet<>(); try { - nms.registerTetheringStatsProvider( - new OffloadTetheringStatsProvider(), getClass().getSimpleName()); + mNms.registerTetheringStatsProvider(mStatsProvider, getClass().getSimpleName()); } catch (RemoteException e) { mLog.e("Cannot register offload stats provider: " + e); } @@ -117,21 +134,25 @@ public class OffloadController { new OffloadHardwareInterface.ControlCallback() { @Override public void onStarted() { + if (!started()) return; mLog.log("onStarted"); } @Override public void onStoppedError() { + if (!started()) return; mLog.log("onStoppedError"); } @Override public void onStoppedUnsupported() { + if (!started()) return; mLog.log("onStoppedUnsupported"); } @Override public void onSupportAvailable() { + if (!started()) return; mLog.log("onSupportAvailable"); // [1] Poll for statistics and notify NetworkStats @@ -139,19 +160,40 @@ public class OffloadController { // [a] push local prefixes // [b] push downstreams // [c] push upstream parameters - pushUpstreamParameters(); + pushUpstreamParameters(null); } @Override public void onStoppedLimitReached() { + if (!started()) return; mLog.log("onStoppedLimitReached"); - // Poll for statistics and notify NetworkStats + + // We cannot reliably determine on which interface the limit was reached, + // because the HAL interface does not specify it. We cannot just use the + // current upstream, because that might have changed since the time that + // the HAL queued the callback. + // TODO: rev the HAL so that it provides an interface name. + + // Fetch current stats, so that when our notification reaches + // NetworkStatsService and triggers a poll, we will respond with + // current data (which will be above the limit that was reached). + // Note that if we just changed upstream, this is unnecessary but harmless. + // The stats for the previous upstream were already updated on this thread + // just after the upstream was changed, so they are also up-to-date. + updateStatsForCurrentUpstream(); + + try { + mNms.tetherLimitReached(mStatsProvider); + } catch (RemoteException e) { + mLog.e("Cannot report data limit reached: " + e); + } } @Override public void onNatTimeoutUpdate(int proto, String srcAddr, int srcPort, String dstAddr, int dstPort) { + if (!started()) return; mLog.log(String.format("NAT timeout update: %s (%s,%s) -> (%s,%s)", proto, srcAddr, srcPort, dstAddr, dstPort)); } @@ -164,6 +206,9 @@ public class OffloadController { } public void stop() { + // Completely stops tethering offload. After this method is called, it is no longer safe to + // call any HAL method, no callbacks from the hardware will be delivered, and any in-flight + // callbacks must be ignored. Offload may be started again by calling start(). final boolean wasStarted = started(); updateStatsForCurrentUpstream(); mUpstreamLinkProperties = null; @@ -175,55 +220,89 @@ public class OffloadController { private class OffloadTetheringStatsProvider extends ITetheringStatsProvider.Stub { @Override - public NetworkStats getTetherStats() { + public NetworkStats getTetherStats(int how) { + // getTetherStats() is the only function in OffloadController that can be called from + // a different thread. Do not attempt to update stats by querying the offload HAL + // synchronously from a different thread than our Handler thread. http://b/64771555. + Runnable updateStats = () -> { updateStatsForCurrentUpstream(); }; + if (Looper.myLooper() == mHandler.getLooper()) { + updateStats.run(); + } else { + mHandler.post(updateStats); + } + NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 0); - CountDownLatch latch = new CountDownLatch(1); + NetworkStats.Entry entry = new NetworkStats.Entry(); + entry.set = SET_DEFAULT; + entry.tag = TAG_NONE; + entry.uid = (how == STATS_PER_UID) ? UID_TETHERING : UID_ALL; + + for (Map.Entry<String, ForwardedStats> kv : mForwardedStats.entrySet()) { + ForwardedStats value = kv.getValue(); + entry.iface = kv.getKey(); + entry.rxBytes = value.rxBytes; + entry.txBytes = value.txBytes; + stats.addValues(entry); + } + return stats; + } + + public void setInterfaceQuota(String iface, long quotaBytes) { mHandler.post(() -> { - try { - NetworkStats.Entry entry = new NetworkStats.Entry(); - entry.set = SET_DEFAULT; - entry.tag = TAG_NONE; - entry.uid = UID_TETHERING; - - updateStatsForCurrentUpstream(); - - for (String iface : mForwardedStats.keySet()) { - entry.iface = iface; - entry.rxBytes = mForwardedStats.get(iface).rxBytes; - entry.txBytes = mForwardedStats.get(iface).txBytes; - stats.addValues(entry); - } - } finally { - latch.countDown(); + if (quotaBytes == ITetheringStatsProvider.QUOTA_UNLIMITED) { + mInterfaceQuotas.remove(iface); + } else { + mInterfaceQuotas.put(iface, quotaBytes); } + maybeUpdateDataLimit(iface); }); - - try { - latch.await(STATS_FETCH_TIMEOUT_MS, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - mLog.e("Tethering stats fetch timed out after " + STATS_FETCH_TIMEOUT_MS + "ms"); - } - - return stats; } } + private String currentUpstreamInterface() { + return (mUpstreamLinkProperties != null) + ? mUpstreamLinkProperties.getInterfaceName() : null; + } + private void maybeUpdateStats(String iface) { if (TextUtils.isEmpty(iface)) { return; } - if (!mForwardedStats.containsKey(iface)) { - mForwardedStats.put(iface, new OffloadHardwareInterface.ForwardedStats()); + // Always called on the handler thread. + // + // Use get()/put() instead of updating ForwardedStats in place because we can be called + // concurrently with getTetherStats. In combination with the guarantees provided by + // ConcurrentHashMap, this ensures that getTetherStats always gets the most recent copy of + // the stats for each interface, and does not observe partial writes where rxBytes is + // updated and txBytes is not. + ForwardedStats diff = mHwInterface.getForwardedStats(iface); + ForwardedStats base = mForwardedStats.get(iface); + if (base != null) { + diff.add(base); } - mForwardedStats.get(iface).add(mHwInterface.getForwardedStats(iface)); + mForwardedStats.put(iface, diff); + // diff is a new object, just created by getForwardedStats(). Therefore, anyone reading from + // mForwardedStats (i.e., any caller of getTetherStats) will see the new stats immediately. } - private void updateStatsForCurrentUpstream() { - if (mUpstreamLinkProperties != null) { - maybeUpdateStats(mUpstreamLinkProperties.getInterfaceName()); + private boolean maybeUpdateDataLimit(String iface) { + // setDataLimit may only be called while offload is occuring on this upstream. + if (!started() || !TextUtils.equals(iface, currentUpstreamInterface())) { + return true; } + + Long limit = mInterfaceQuotas.get(iface); + if (limit == null) { + limit = Long.MAX_VALUE; + } + + return mHwInterface.setDataLimit(iface, limit); + } + + private void updateStatsForCurrentUpstream() { + maybeUpdateStats(currentUpstreamInterface()); } public void setUpstreamLinkProperties(LinkProperties lp) { @@ -239,10 +318,7 @@ public class OffloadController { // onOffloadEvent() callback to tell us offload is available again and // then reapply all state). computeAndPushLocalPrefixes(); - pushUpstreamParameters(); - - // Update stats after we've told the hardware to change routing so we don't miss packets. - maybeUpdateStats(prevUpstream); + pushUpstreamParameters(prevUpstream); } public void setLocalPrefixes(Set<IpPrefix> localPrefixes) { @@ -253,17 +329,42 @@ public class OffloadController { } public void notifyDownstreamLinkProperties(LinkProperties lp) { + final String ifname = lp.getInterfaceName(); + final LinkProperties oldLp = mDownstreams.put(ifname, new LinkProperties(lp)); + if (Objects.equals(oldLp, lp)) return; + if (!started()) return; - // TODO: Cache LinkProperties on a per-ifname basis and compute the - // deltas, calling addDownstream()/removeDownstream() accordingly. + final List<RouteInfo> oldRoutes = (oldLp != null) ? oldLp.getRoutes() : new ArrayList<>(); + final List<RouteInfo> newRoutes = lp.getRoutes(); + + // For each old route, if not in new routes: remove. + for (RouteInfo oldRoute : oldRoutes) { + if (shouldIgnoreDownstreamRoute(oldRoute)) continue; + if (!newRoutes.contains(oldRoute)) { + mHwInterface.removeDownstreamPrefix(ifname, oldRoute.getDestination().toString()); + } + } + + // For each new route, if not in old routes: add. + for (RouteInfo newRoute : newRoutes) { + if (shouldIgnoreDownstreamRoute(newRoute)) continue; + if (!oldRoutes.contains(newRoute)) { + mHwInterface.addDownstreamPrefix(ifname, newRoute.getDestination().toString()); + } + } } public void removeDownstreamInterface(String ifname) { + final LinkProperties lp = mDownstreams.remove(ifname); + if (lp == null) return; + if (!started()) return; - // TODO: Check cache for LinkProperties of ifname and, if present, - // call removeDownstream() accordingly. + for (RouteInfo route : lp.getRoutes()) { + if (shouldIgnoreDownstreamRoute(route)) continue; + mHwInterface.removeDownstreamPrefix(ifname, route.getDestination().toString()); + } } private boolean isOffloadDisabled() { @@ -276,8 +377,9 @@ public class OffloadController { return mConfigInitialized && mControlInitialized; } - private boolean pushUpstreamParameters() { + private boolean pushUpstreamParameters(String prevUpstream) { if (mUpstreamLinkProperties == null) { + maybeUpdateStats(prevUpstream); return mHwInterface.setUpstreamParameters(null, null, null, null); } @@ -309,8 +411,26 @@ public class OffloadController { } } - return mHwInterface.setUpstreamParameters( + boolean success = mHwInterface.setUpstreamParameters( iface, v4addr, v4gateway, (v6gateways.isEmpty() ? null : v6gateways)); + + if (!success) { + return success; + } + + // Update stats after we've told the hardware to change routing so we don't miss packets. + maybeUpdateStats(prevUpstream); + + // Data limits can only be set once offload is running on the upstream. + success = maybeUpdateDataLimit(iface); + if (!success) { + // If we failed to set a data limit, don't use this upstream, because we don't want to + // blow through the data limit that we were told to apply. + mLog.log("Setting data limit for " + iface + " failed, disabling offload."); + stop(); + } + + return success; } private boolean computeAndPushLocalPrefixes() { @@ -351,6 +471,13 @@ public class OffloadController { return localPrefixStrs; } + private static boolean shouldIgnoreDownstreamRoute(RouteInfo route) { + // Ignore any link-local routes. + if (!route.getDestinationLinkAddress().isGlobalPreferred()) return true; + + return false; + } + public void dump(IndentingPrintWriter pw) { if (isOffloadDisabled()) { pw.println("Offload disabled"); diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java index 25fab9e403a1..865a98902d0b 100644 --- a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java +++ b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java @@ -40,7 +40,7 @@ public class OffloadHardwareInterface { // Change this value to control whether tether offload is enabled or // disabled by default in the absence of an explicit Settings value. // See accompanying unittest to distinguish 0 from non-0 values. - private static final int DEFAULT_TETHER_OFFLOAD_DISABLED = 1; + private static final int DEFAULT_TETHER_OFFLOAD_DISABLED = 0; private static final String NO_INTERFACE_NAME = ""; private static final String NO_IPV4_ADDRESS = ""; private static final String NO_IPV4_GATEWAY = ""; @@ -188,6 +188,27 @@ public class OffloadHardwareInterface { return results.success; } + public boolean setDataLimit(String iface, long limit) { + + final String logmsg = String.format("setDataLimit(%s, %d)", iface, limit); + + final CbResults results = new CbResults(); + try { + mOffloadControl.setDataLimit( + iface, limit, + (boolean success, String errMsg) -> { + results.success = success; + results.errMsg = errMsg; + }); + } catch (RemoteException e) { + record(logmsg, e); + return false; + } + + record(logmsg, results); + return results.success; + } + public boolean setUpstreamParameters( String iface, String v4addr, String v4gateway, ArrayList<String> v6gws) { iface = (iface != null) ? iface : NO_INTERFACE_NAME; @@ -215,6 +236,44 @@ public class OffloadHardwareInterface { return results.success; } + public boolean addDownstreamPrefix(String ifname, String prefix) { + final String logmsg = String.format("addDownstreamPrefix(%s, %s)", ifname, prefix); + + final CbResults results = new CbResults(); + try { + mOffloadControl.addDownstream(ifname, prefix, + (boolean success, String errMsg) -> { + results.success = success; + results.errMsg = errMsg; + }); + } catch (RemoteException e) { + record(logmsg, e); + return false; + } + + record(logmsg, results); + return results.success; + } + + public boolean removeDownstreamPrefix(String ifname, String prefix) { + final String logmsg = String.format("removeDownstreamPrefix(%s, %s)", ifname, prefix); + + final CbResults results = new CbResults(); + try { + mOffloadControl.removeDownstream(ifname, prefix, + (boolean success, String errMsg) -> { + results.success = success; + results.errMsg = errMsg; + }); + } catch (RemoteException e) { + record(logmsg, e); + return false; + } + + record(logmsg, results); + return results.success; + } + private void record(String msg, Throwable t) { mLog.e(msg + YIELDS + "exception: " + t); } diff --git a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java index 69678df4543d..57d2502c6dc7 100644 --- a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java +++ b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java @@ -115,6 +115,7 @@ public class TetherInterfaceStateMachine extends StateMachine { private final LinkProperties mLinkProperties; private int mLastError; + private int mServingMode; private String mMyUpstreamIfaceName; // may change over time private NetworkInterface mNetworkInterface; private byte[] mHwAddr; @@ -142,6 +143,7 @@ public class TetherInterfaceStateMachine extends StateMachine { mLinkProperties = new LinkProperties(); resetLinkProperties(); mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR; + mServingMode = IControlsTethering.STATE_AVAILABLE; mInitialState = new InitialState(); mLocalHotspotState = new LocalHotspotState(); @@ -161,6 +163,8 @@ public class TetherInterfaceStateMachine extends StateMachine { public int lastError() { return mLastError; } + public int servingMode() { return mServingMode; } + public LinkProperties linkProperties() { return new LinkProperties(mLinkProperties); } public void stop() { sendMessage(CMD_INTERFACE_DOWN); } @@ -448,6 +452,7 @@ public class TetherInterfaceStateMachine extends StateMachine { } private void sendInterfaceState(int newInterfaceState) { + mServingMode = newInterfaceState; mTetherController.updateInterfaceState( TetherInterfaceStateMachine.this, newInterfaceState, mLastError); sendLinkProperties(); diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index ad74ff88e80f..6e1c21eea15a 100644 --- a/services/core/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java @@ -646,6 +646,7 @@ public final class ContentService extends IContentService.Stub { SyncManager syncManager = getSyncManager(); if (syncManager == null) return; int userId = UserHandle.getCallingUserId(); + final int callingUid = Binder.getCallingUid(); long identityToken = clearCallingIdentity(); try { @@ -658,7 +659,8 @@ public final class ContentService extends IContentService.Stub { // Remove periodic sync. mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, "no permission to write the sync settings"); - getSyncManager().removePeriodicSync(info, extras); + getSyncManager().removePeriodicSync(info, extras, + "cancelRequest() by uid=" + callingUid); } // Cancel active syncs and clear pending syncs from the queue. syncManager.cancelScheduledSyncOperation(info, extras); @@ -814,13 +816,15 @@ public final class ContentService extends IContentService.Stub { mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, "no permission to write the sync settings"); + final int callingUid = Binder.getCallingUid(); + int userId = UserHandle.getCallingUserId(); long identityToken = clearCallingIdentity(); try { getSyncManager() .removePeriodicSync( new SyncStorageEngine.EndPoint(account, authority, userId), - extras); + extras, "removePeriodicSync() by uid=" + callingUid); } finally { restoreCallingIdentity(identityToken); } diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index f41aa5f7993c..2f3b55960c13 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -59,6 +59,7 @@ import android.net.NetworkInfo; import android.net.TrafficStats; import android.os.BatteryStats; import android.os.Binder; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -98,6 +99,7 @@ import com.android.server.backup.AccountSyncSettingsBackupHelper; import com.android.server.content.SyncStorageEngine.AuthorityInfo; import com.android.server.content.SyncStorageEngine.EndPoint; import com.android.server.content.SyncStorageEngine.OnSyncRequestListener; +import com.android.server.job.JobSchedulerInternal.JobStorePersistStats; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -141,6 +143,8 @@ public class SyncManager { private static final boolean DEBUG_ACCOUNT_ACCESS = false; + private static final boolean ENABLE_SUSPICIOUS_CHECK = Build.IS_DEBUGGABLE; + /** Delay a sync due to local changes this long. In milliseconds */ private static final long LOCAL_SYNC_DELAY; @@ -400,12 +404,21 @@ public class SyncManager { return (networkInfo != null) && networkInfo.isConnected(); } + private String getJobStats() { + JobSchedulerInternal js = LocalServices.getService(JobSchedulerInternal.class); + return "JobStats: " + + ((js == null) ? "(JobSchedulerInternal==null)" + : js.getPersistStats().toString()); + } + private BroadcastReceiver mShutdownIntentReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.w(TAG, "Writing sync state before shutdown..."); getSyncStorageEngine().writeAllState(); + + mLogger.log(getJobStats()); mLogger.log("Shutting down."); } }; @@ -463,7 +476,7 @@ public class SyncManager { } if (opx.key.equals(opy.key)) { mLogger.log("Removing duplicate sync: ", opy); - mJobScheduler.cancel(opy.jobId); + cancelJob(opy, "cleanupJobs() x=" + opx + " y=" + opy); } } } @@ -501,15 +514,19 @@ public class SyncManager { } } } - if (mLogger.enabled()) { - mLogger.log("Connected to JobScheduler: " - + numPersistedPeriodicSyncs + " periodic syncs " - + numPersistedOneshotSyncs + " oneshot syncs."); - } + final String summary = "Loaded persisted syncs: " + + numPersistedPeriodicSyncs + " periodic syncs, " + + numPersistedOneshotSyncs + " oneshot syncs, " + + (pendingJobs.size()) + " total system server jobs, " + + getJobStats(); + Slog.i(TAG, summary); + mLogger.log(summary); + cleanupJobs(); - if ((numPersistedPeriodicSyncs == 0) && likelyHasPeriodicSyncs()) { - Slog.wtf(TAG, "Device booted with no persisted periodic syncs."); + if (ENABLE_SUSPICIOUS_CHECK && + (numPersistedPeriodicSyncs == 0) && likelyHasPeriodicSyncs()) { + Slog.wtf(TAG, "Device booted with no persisted periodic syncs: " + summary); } } finally { Binder.restoreCallingIdentity(token); @@ -520,6 +537,7 @@ public class SyncManager { * @return whether the device most likely has some periodic syncs. */ private boolean likelyHasPeriodicSyncs() { + // STOPSHIP Remove the google specific string. try { return AccountManager.get(mContext).getAccountsByType("com.google").length > 0; } catch (Throwable th) { @@ -566,7 +584,7 @@ public class SyncManager { mSyncStorageEngine.setOnAuthorityRemovedListener(new SyncStorageEngine.OnAuthorityRemovedListener() { @Override public void onAuthorityRemoved(EndPoint removedAuthority) { - removeSyncsForAuthority(removedAuthority); + removeSyncsForAuthority(removedAuthority, "onAuthorityRemoved"); } }); @@ -710,7 +728,7 @@ public class SyncManager { // the account (they run before) which is the genie is out of the bottle. whiteListExistingSyncAdaptersIfNeeded(); - mLogger.log("Sync manager initialized."); + mLogger.log("Sync manager initialized: " + Build.FINGERPRINT); } public void onStartUser(int userHandle) { @@ -1118,14 +1136,14 @@ public class SyncManager { } } - private void removeSyncsForAuthority(EndPoint info) { + private void removeSyncsForAuthority(EndPoint info, String why) { mLogger.log("removeSyncsForAuthority: ", info); verifyJobScheduler(); List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { if (op.target.matchesSpec(info)) { mLogger.log("canceling: ", op); - getJobScheduler().cancel(op.jobId); + cancelJob(op, why); } } } @@ -1133,8 +1151,9 @@ public class SyncManager { /** * Remove a specific periodic sync identified by its target and extras. */ - public void removePeriodicSync(EndPoint target, Bundle extras) { - Message m = mSyncHandler.obtainMessage(mSyncHandler.MESSAGE_REMOVE_PERIODIC_SYNC, target); + public void removePeriodicSync(EndPoint target, Bundle extras, String why) { + Message m = mSyncHandler.obtainMessage(mSyncHandler.MESSAGE_REMOVE_PERIODIC_SYNC, + Pair.create(target, why)); m.setData(extras); m.sendToTarget(); } @@ -1359,7 +1378,7 @@ public class SyncManager { for (SyncOperation op: ops) { if (!op.isPeriodic && op.target.matchesSpec(target)) { count++; - getJobScheduler().cancel(op.jobId); + cancelJob(op, why); postScheduleSyncMessage(op, 0 /* min delay */); } } @@ -1484,7 +1503,7 @@ public class SyncManager { if (isLoggable) { Slog.v(TAG, "Cancelling duplicate sync " + op); } - getJobScheduler().cancel(op.jobId); + cancelJob(op, "scheduleSyncOperationH-duplicate"); } } } @@ -1544,7 +1563,7 @@ public class SyncManager { List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { if (!op.isPeriodic && op.target.matchesSpec(info)) { - getJobScheduler().cancel(op.jobId); + cancelJob(op, "clearScheduledSyncOperations"); getSyncStorageEngine().markPending(op.target, false); } } @@ -1562,7 +1581,7 @@ public class SyncManager { for (SyncOperation op: ops) { if (!op.isPeriodic && op.target.matchesSpec(info) && syncExtrasEquals(extras, op.extras, false)) { - getJobScheduler().cancel(op.jobId); + cancelJob(op, "cancelScheduledSyncOperation"); } } setAuthorityPendingState(info); @@ -1678,7 +1697,7 @@ public class SyncManager { List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { if (op.target.userId == userId) { - getJobScheduler().cancel(op.jobId); + cancelJob(op, "user removed u" + userId); } } } @@ -2710,7 +2729,8 @@ public class SyncManager { data.flex, data.extras); break; case MESSAGE_REMOVE_PERIODIC_SYNC: - removePeriodicSyncH((EndPoint)msg.obj, msg.getData()); + Pair<EndPoint, String> args = (Pair<EndPoint, String>) (msg.obj); + removePeriodicSyncH(args.first, msg.getData(), args.second); break; case SyncHandler.MESSAGE_CANCEL: @@ -2848,7 +2868,7 @@ public class SyncManager { // mSyncJobService.callJobFinished is async, so cancel the job to ensure we don't // find the this job in the pending jobs list while looking for duplicates // before scheduling it at a later time. - getJobScheduler().cancel(op.jobId); + cancelJob(op, "deferSyncH()"); scheduleSyncOperationH(op, delay); } } @@ -2998,7 +3018,7 @@ public class SyncManager { for (SyncOperation op: ops) { if (!containsAccountAndUser(allAccounts, op.target.account, op.target.userId)) { mLogger.log("canceling: ", op); - getJobScheduler().cancel(op.jobId); + cancelJob(op, "updateRunningAccountsH()"); } } @@ -3105,7 +3125,7 @@ public class SyncManager { /** * Remove this periodic sync operation and all one-off operations initiated by it. */ - private void removePeriodicSyncInternalH(SyncOperation syncOperation) { + private void removePeriodicSyncInternalH(SyncOperation syncOperation, String why) { // Remove this periodic sync and all one-off syncs initiated by it. List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { @@ -3117,18 +3137,18 @@ public class SyncManager { runSyncFinishedOrCanceledH(null, asc); } mLogger.log("removePeriodicSyncInternalH-canceling: ", op); - getJobScheduler().cancel(op.jobId); + cancelJob(op, why); } } } - private void removePeriodicSyncH(EndPoint target, Bundle extras) { + private void removePeriodicSyncH(EndPoint target, Bundle extras, String why) { verifyJobScheduler(); List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { if (op.isPeriodic && op.target.matchesSpec(target) && syncExtrasEquals(op.extras, extras, true /* includeSyncSettings */)) { - removePeriodicSyncInternalH(op); + removePeriodicSyncInternalH(op, why); } } } @@ -3354,12 +3374,6 @@ public class SyncManager { int downstreamActivity; int upstreamActivity; - if (!syncOperation.isPeriodic) { - // mSyncJobService.jobFinidhed is async, we need to ensure that this job is - // removed from JobScheduler's pending jobs list before moving forward and - // potentially rescheduling all pending jobs to respect new backoff values. - getJobScheduler().cancel(syncOperation.jobId); - } mLogger.log("runSyncFinishedOrCanceledH() op=", syncOperation, " result=", syncResult); if (syncResult != null) { @@ -3368,6 +3382,16 @@ public class SyncManager { + syncOperation + ", result " + syncResult); } + // In the non-canceled case, close the active sync context before doing the rest + // of the stuff. + closeActiveSyncContext(activeSyncContext); + + // Note this part is probably okay to do before closeActiveSyncContext()... + // But moved here to restore OC-dev's behavior. See b/64597061. + if (!syncOperation.isPeriodic) { + cancelJob(syncOperation, "runSyncFinishedOrCanceledH()-finished"); + } + if (!syncResult.hasError()) { historyMessage = SyncStorageEngine.MESG_SUCCESS; // TODO: set these correctly when the SyncResult is extended to include it @@ -3404,6 +3428,11 @@ public class SyncManager { if (isLoggable) { Slog.v(TAG, "runSyncFinishedOrCanceled [canceled]: " + syncOperation); } + + if (!syncOperation.isPeriodic) { + cancelJob(syncOperation, "runSyncFinishedOrCanceledH()-canceled"); + } + if (activeSyncContext.mSyncAdapter != null) { try { mLogger.log("Calling cancelSync for runSyncFinishedOrCanceled ", @@ -3418,10 +3447,10 @@ public class SyncManager { historyMessage = SyncStorageEngine.MESG_CANCELED; downstreamActivity = 0; upstreamActivity = 0; - } - // Close and unbind the service. Don't use activeSyncContext.mSyncAdapter after this. - closeActiveSyncContext(activeSyncContext); + // In the cancel sync case, close it after calling cancelSync(). + closeActiveSyncContext(activeSyncContext); + } stopSyncEvent(activeSyncContext.mHistoryRowId, syncOperation, historyMessage, upstreamActivity, downstreamActivity, elapsedTime); @@ -3457,6 +3486,8 @@ public class SyncManager { + activeSyncContext.toString()); } mSyncHandler.removeMessages(SyncHandler.MESSAGE_MONITOR_SYNC, activeSyncContext); + + mLogger.log("closeActiveSyncContext: ", activeSyncContext); } /** @@ -3736,4 +3767,58 @@ public class SyncManager { return mContext; } } + + private void cancelJob(SyncOperation op, String why) { + if (op == null) { + Slog.wtf(TAG, "Null sync operation detected."); + return; + } + if (op.isPeriodic) { + mLogger.log("Removing periodic sync ", op, " for ", why); + + if (ENABLE_SUSPICIOUS_CHECK && isSuspiciousPeriodicSyncRemoval(op)) { + wtfWithLog("Suspicious removal of " + op + " for " + why); + } + } + getJobScheduler().cancel(op.jobId); + } + + private boolean isSuspiciousPeriodicSyncRemoval(SyncOperation op) { + // STOPSHIP Remove the google specific string. + if (!op.isPeriodic){ + return false; + } + boolean found = false; + for (UserInfo user : UserManager.get(mContext).getUsers(/*excludeDying=*/ true)) { + if (op.target.userId == user.id) { + found = true; + break; + } + } + if (!found) { + return false; // User is being removed, okay. + } + switch (op.target.provider) { + case "gmail-ls": + case "com.android.contacts.metadata": + break; + default: + return false; + } + final Account account = op.target.account; + final Account[] accounts = AccountManager.get(mContext) + .getAccountsByTypeAsUser(account.type, UserHandle.of(op.target.userId)); + for (Account a : accounts) { + if (a.equals(account)) { + return true; // Account still exists. Suspicious! + } + } + // Account no longer exists. Makes sense... + return false; + } + + private void wtfWithLog(String message) { + Slog.wtf(TAG, message); + mLogger.log("WTF: ", message); + } } diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java index 3d24fed60069..9aabdab7daa8 100644 --- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java +++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java @@ -59,6 +59,13 @@ class AutomaticBrightnessController { private static final int MSG_UPDATE_AMBIENT_LUX = 1; private static final int MSG_BRIGHTNESS_ADJUSTMENT_SAMPLE = 2; + // Length of the ambient light horizon used to calculate the long term estimate of ambient + // light. + private static final int AMBIENT_LIGHT_LONG_HORIZON_MILLIS = 10000; + + // Length of the ambient light horizon used to calculate short-term estimate of ambient light. + private static final int AMBIENT_LIGHT_SHORT_HORIZON_MILLIS = 2000; + // Callbacks for requesting updates to the display's power state private final Callbacks mCallbacks; @@ -345,22 +352,51 @@ class AutomaticBrightnessController { } private void setAmbientLux(float lux) { + if (DEBUG) { + Slog.d(TAG, "setAmbientLux(" + lux + ")"); + } mAmbientLux = lux; mBrighteningLuxThreshold = mDynamicHysteresis.getBrighteningThreshold(lux); mDarkeningLuxThreshold = mDynamicHysteresis.getDarkeningThreshold(lux); } - private float calculateAmbientLux(long now) { + private float calculateAmbientLux(long now, long horizon) { + if (DEBUG) { + Slog.d(TAG, "calculateAmbientLux(" + now + ", " + horizon + ")"); + } final int N = mAmbientLightRingBuffer.size(); if (N == 0) { Slog.e(TAG, "calculateAmbientLux: No ambient light readings available"); return -1; } + + // Find the first measurement that is just outside of the horizon. + int endIndex = 0; + final long horizonStartTime = now - horizon; + for (int i = 0; i < N-1; i++) { + if (mAmbientLightRingBuffer.getTime(i + 1) <= horizonStartTime) { + endIndex++; + } else { + break; + } + } + if (DEBUG) { + Slog.d(TAG, "calculateAmbientLux: selected endIndex=" + endIndex + ", point=(" + + mAmbientLightRingBuffer.getTime(endIndex) + ", " + + mAmbientLightRingBuffer.getLux(endIndex) + + ")"); + } float sum = 0; float totalWeight = 0; long endTime = AMBIENT_LIGHT_PREDICTION_TIME_MILLIS; - for (int i = N - 1; i >= 0; i--) { - long startTime = (mAmbientLightRingBuffer.getTime(i) - now); + for (int i = N - 1; i >= endIndex; i--) { + long eventTime = mAmbientLightRingBuffer.getTime(i); + if (i == endIndex && eventTime < horizonStartTime) { + // If we're at the final value, make sure we only consider the part of the sample + // within our desired horizon. + eventTime = horizonStartTime; + } + final long startTime = eventTime - now; float weight = calculateWeight(startTime, endTime); float lux = mAmbientLightRingBuffer.getLux(i); if (DEBUG) { @@ -435,7 +471,7 @@ class AutomaticBrightnessController { timeWhenSensorWarmedUp); return; } - setAmbientLux(calculateAmbientLux(time)); + setAmbientLux(calculateAmbientLux(time, AMBIENT_LIGHT_SHORT_HORIZON_MILLIS)); mAmbientLuxValid = true; if (DEBUG) { Slog.d(TAG, "updateAmbientLux: Initializing: " @@ -447,14 +483,25 @@ class AutomaticBrightnessController { long nextBrightenTransition = nextAmbientLightBrighteningTransition(time); long nextDarkenTransition = nextAmbientLightDarkeningTransition(time); - float ambientLux = calculateAmbientLux(time); - - if (ambientLux >= mBrighteningLuxThreshold && nextBrightenTransition <= time - || ambientLux <= mDarkeningLuxThreshold && nextDarkenTransition <= time) { - setAmbientLux(ambientLux); + // Essentially, we calculate both a slow ambient lux, to ensure there's a true long-term + // change in lighting conditions, and a fast ambient lux to determine what the new + // brightness situation is since the slow lux can be quite slow to converge. + // + // Note that both values need to be checked for sufficient change before updating the + // proposed ambient light value since the slow value might be sufficiently far enough away + // from the fast value to cause a recalculation while its actually just converging on + // the fast value still. + float slowAmbientLux = calculateAmbientLux(time, AMBIENT_LIGHT_LONG_HORIZON_MILLIS); + float fastAmbientLux = calculateAmbientLux(time, AMBIENT_LIGHT_SHORT_HORIZON_MILLIS); + + if (slowAmbientLux >= mBrighteningLuxThreshold && + fastAmbientLux >= mBrighteningLuxThreshold && nextBrightenTransition <= time + || slowAmbientLux <= mDarkeningLuxThreshold + && fastAmbientLux <= mDarkeningLuxThreshold && nextDarkenTransition <= time) { + setAmbientLux(fastAmbientLux); if (DEBUG) { Slog.d(TAG, "updateAmbientLux: " - + ((ambientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": " + + ((fastAmbientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": " + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold + ", mAmbientLightRingBuffer=" + mAmbientLightRingBuffer + ", mAmbientLux=" + mAmbientLux); @@ -616,6 +663,12 @@ class AutomaticBrightnessController { void updateBrightness(); } + /** + * A ring buffer of ambient light measurements sorted by time. + * + * Each entry consists of a timestamp and a lux measurement, and the overall buffer is sorted + * from oldest to newest. + */ private static final class AmbientLightRingBuffer { // Proportional extra capacity of the buffer beyond the expected number of light samples // in the horizon diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 8269042da24a..d0a1d9e63141 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -31,6 +31,8 @@ import android.Manifest; import android.annotation.NonNull; import android.content.Context; import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.graphics.Point; import android.hardware.SensorManager; import android.hardware.display.DisplayManagerGlobal; import android.hardware.display.DisplayManagerInternal; @@ -211,6 +213,12 @@ public final class DisplayManagerService extends SystemService { // The virtual display adapter, or null if not registered. private VirtualDisplayAdapter mVirtualDisplayAdapter; + // The stable device screen height and width. These are not tied to a specific display, even + // the default display, because they need to be stable over the course of the device's entire + // life, even if the default display changes (e.g. a new monitor is plugged into a PC-like + // device). + private Point mStableDisplaySize = new Point(); + // Viewports of the default display and the display that should receive touch // input from an external source. Used by the input system. private final DisplayViewport mDefaultViewport = new DisplayViewport(); @@ -284,7 +292,10 @@ public final class DisplayManagerService extends SystemService { // adapter is up so that we have it's configuration. We could load it lazily, but since // we're going to have to read it in eventually we may as well do it here rather than after // we've waited for the display to register itself with us. - mPersistentDataStore.loadIfNeeded(); + synchronized(mSyncRoot) { + mPersistentDataStore.loadIfNeeded(); + loadStableDisplayValuesLocked(); + } mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS); publishBinderService(Context.DISPLAY_SERVICE, new BinderService(), @@ -346,6 +357,34 @@ public final class DisplayManagerService extends SystemService { return mHandler; } + private void loadStableDisplayValuesLocked() { + final Point size = mPersistentDataStore.getStableDisplaySize(); + if (size.x > 0 && size.y > 0) { + // Just set these values directly so we don't write the display persistent data again + // unnecessarily + mStableDisplaySize.set(size.x, size.y); + } else { + final Resources res = mContext.getResources(); + final int width = res.getInteger( + com.android.internal.R.integer.config_stableDeviceDisplayWidth); + final int height = res.getInteger( + com.android.internal.R.integer.config_stableDeviceDisplayHeight); + if (width > 0 && height > 0) { + setStableDisplaySizeLocked(width, height); + } + } + } + + private Point getStableDisplaySizeInternal() { + Point r = new Point(); + synchronized (mSyncRoot) { + if (mStableDisplaySize.x > 0 && mStableDisplaySize.y > 0) { + r.set(mStableDisplaySize.x, mStableDisplaySize.y); + } + } + return r; + } + private void registerDisplayTransactionListenerInternal( DisplayTransactionListener listener) { // List is self-synchronized copy-on-write. @@ -770,18 +809,6 @@ public final class DisplayManagerService extends SystemService { if (work != null) { work.run(); } - if (display != null && display.getPrimaryDisplayDeviceLocked() == device) { - int colorMode = mPersistentDataStore.getColorMode(device); - if (colorMode == Display.COLOR_MODE_INVALID) { - if ((device.getDisplayDeviceInfoLocked().flags - & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) { - colorMode = mDefaultDisplayDefaultColorMode; - } else { - colorMode = Display.COLOR_MODE_DEFAULT; - } - } - display.setRequestedColorModeLocked(colorMode); - } scheduleTraversalLocked(false); } @@ -886,6 +913,11 @@ public final class DisplayManagerService extends SystemService { return null; } + configureColorModeLocked(display, device); + if (isDefault) { + recordStableDisplayStatsIfNeededLocked(display); + } + mLogicalDisplays.put(displayId, display); // Wake up waitForDefaultDisplay. @@ -907,6 +939,40 @@ public final class DisplayManagerService extends SystemService { return displayId; } + private void configureColorModeLocked(LogicalDisplay display, DisplayDevice device) { + if (display.getPrimaryDisplayDeviceLocked() == device) { + int colorMode = mPersistentDataStore.getColorMode(device); + if (colorMode == Display.COLOR_MODE_INVALID) { + if ((device.getDisplayDeviceInfoLocked().flags + & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) { + colorMode = mDefaultDisplayDefaultColorMode; + } else { + colorMode = Display.COLOR_MODE_DEFAULT; + } + } + display.setRequestedColorModeLocked(colorMode); + } + } + + // If we've never recorded stable device stats for this device before and they aren't + // explicitly configured, go ahead and record the stable device stats now based on the status + // of the default display at first boot. + private void recordStableDisplayStatsIfNeededLocked(LogicalDisplay d) { + if (mStableDisplaySize.x <= 0 && mStableDisplaySize.y <= 0) { + DisplayInfo info = d.getDisplayInfoLocked(); + setStableDisplaySizeLocked(info.getNaturalWidth(), info.getNaturalHeight()); + } + } + + private void setStableDisplaySizeLocked(int width, int height) { + mStableDisplaySize = new Point(width, height); + try { + mPersistentDataStore.setStableDisplaySize(mStableDisplaySize); + } finally { + mPersistentDataStore.saveIfNeeded(); + } + } + // Updates all existing logical displays given the current set of display devices. // Removes invalid logical displays. // Sends notifications if needed. @@ -1166,6 +1232,8 @@ public final class DisplayManagerService extends SystemService { pw.println(" mDefaultDisplayDefaultColorMode=" + mDefaultDisplayDefaultColorMode); pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode); pw.println(" mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount); + pw.println(" mStableDisplaySize=" + mStableDisplaySize); + IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); ipw.increaseIndent(); @@ -1378,6 +1446,19 @@ public final class DisplayManagerService extends SystemService { } } + /** + * Returns the stable device display size, in pixels. + */ + @Override // Binder call + public Point getStableDisplaySize() { + final long token = Binder.clearCallingIdentity(); + try { + return getStableDisplaySizeInternal(); + } finally { + Binder.restoreCallingIdentity(token); + } + } + @Override // Binder call public void registerCallback(IDisplayManagerCallback callback) { if (callback == null) { diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index fb8ae1247796..f8e58362e7ae 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -984,6 +984,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate); } if (mScreenBrightnessRampAnimator.animateTo(target, rate)) { + Trace.traceCounter(Trace.TRACE_TAG_POWER, "TargetScreenBrightness", target); try { mBatteryStats.noteScreenBrightness(target); } catch (RemoteException ex) { @@ -1010,7 +1011,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // contents of the screen. mPowerState.prepareColorFade(mContext, mColorFadeFadesConfig ? ColorFade.MODE_FADE : ColorFade.MODE_WARM_UP); - mColorFadeOffAnimator.end(); + if (mColorFadeOffAnimator != null) { + mColorFadeOffAnimator.end(); + } // Some display hardware will blank itself on the transition between doze and non-doze // but still on display states. In this case we want to report to policy that the // display has turned off so it can prepare the appropriate power on animation, but we diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index ce5f430c148f..87564846df3b 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -532,7 +532,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { try { mBacklight.setBrightness(brightness); Trace.traceCounter(Trace.TRACE_TAG_POWER, - "DisplayBrightness", brightness); + "ScreenBrightness", brightness); } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } diff --git a/services/core/java/com/android/server/display/NightDisplayService.java b/services/core/java/com/android/server/display/NightDisplayService.java index b3cf57b3564a..aafc6317bfae 100644 --- a/services/core/java/com/android/server/display/NightDisplayService.java +++ b/services/core/java/com/android/server/display/NightDisplayService.java @@ -110,23 +110,7 @@ public final class NightDisplayService extends SystemService private float[] mMatrixNight = new float[16]; - /** - * These coefficients were generated by an LLS quadratic regression fitted to the - * overdetermined system based on experimental readings (and subsequent conversion from xy - * chromaticity coordinates to gamma-corrected RGB values): { (temperature, R, G, B) } -> - * { (7304, 1.0, 1.0, 1.0), (4082, 1.0, 0.857, 0.719), (2850, 1.0, .754, .516), - * (2596, 1.0, 0.722, 0.454) }. The 3x3 matrix is formatted like so: - * <table> - * <tr><td>R: a coefficient</td><td>G: a coefficient</td><td>B: a coefficient</td></tr> - * <tr><td>R: b coefficient</td><td>G: b coefficient</td><td>B: b coefficient</td></tr> - * <tr><td>R: y-intercept</td><td>G: y-intercept</td><td>B: y-intercept</td></tr> - * </table> - */ - private static final float[] mColorTempCoefficients = new float[] { - 0.0f, -0.00000000962353339f, -0.0000000189359041f, - 0.0f, 0.000153045476f, 0.000302412211f, - 1.0f, 0.390782778f, -0.198650895f - }; + private final float[] mColorTempCoefficients = new float[9]; private int mCurrentUser = UserHandle.USER_NULL; private ContentObserver mUserSetupObserver; @@ -140,6 +124,12 @@ public final class NightDisplayService extends SystemService public NightDisplayService(Context context) { super(context); mHandler = new Handler(Looper.getMainLooper()); + + final String[] coefficients = context.getResources().getStringArray( + com.android.internal.R.array.config_nightDisplayColorTemperatureCoefficients); + for (int i = 0; i < 9 && i < coefficients.length; i++) { + mColorTempCoefficients[i] = Float.parseFloat(coefficients[i]); + } } @Override @@ -414,11 +404,11 @@ public final class NightDisplayService extends SystemService final float squareTemperature = colorTemperature * colorTemperature; final float red = squareTemperature * mColorTempCoefficients[0] - + colorTemperature * mColorTempCoefficients[3] + mColorTempCoefficients[6]; - final float green = squareTemperature * mColorTempCoefficients[1] - + colorTemperature * mColorTempCoefficients[4] + mColorTempCoefficients[7]; - final float blue = squareTemperature * mColorTempCoefficients[2] - + colorTemperature * mColorTempCoefficients[5] + mColorTempCoefficients[8]; + + colorTemperature * mColorTempCoefficients[1] + mColorTempCoefficients[2]; + final float green = squareTemperature * mColorTempCoefficients[3] + + colorTemperature * mColorTempCoefficients[4] + mColorTempCoefficients[5]; + final float blue = squareTemperature * mColorTempCoefficients[6] + + colorTemperature * mColorTempCoefficients[7] + mColorTempCoefficients[8]; outTemp[0] = red; outTemp[5] = green; outTemp[10] = blue; diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java index 47701b99860a..34c8e22a9f1e 100644 --- a/services/core/java/com/android/server/display/PersistentDataStore.java +++ b/services/core/java/com/android/server/display/PersistentDataStore.java @@ -23,6 +23,7 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; +import android.graphics.Point; import android.hardware.display.WifiDisplay; import android.util.AtomicFile; import android.util.Slog; @@ -60,6 +61,10 @@ import libcore.util.Objects; * <color-mode>0</color-mode> * </display> * </display-states> + * <stable-device-values> + * <stable-display-height>1920<stable-display-height> + * <stable-display-width>1080<stable-display-width> + * </stable-device-values> * </display-manager-state> * </code> * @@ -75,6 +80,9 @@ final class PersistentDataStore { private final HashMap<String, DisplayState> mDisplayStates = new HashMap<String, DisplayState>(); + // Display values which should be stable across the device's lifetime. + private final StableDeviceValues mStableDeviceValues = new StableDeviceValues(); + // The atomic file used to safely read or write the file. private final AtomicFile mAtomicFile; @@ -162,6 +170,7 @@ final class PersistentDataStore { } public boolean forgetWifiDisplay(String deviceAddress) { + loadIfNeeded(); int index = findRememberedWifiDisplay(deviceAddress); if (index >= 0) { mRememberedWifiDisplays.remove(index); @@ -204,6 +213,18 @@ final class PersistentDataStore { return false; } + public Point getStableDisplaySize() { + loadIfNeeded(); + return mStableDeviceValues.getDisplaySize(); + } + + public void setStableDisplaySize(Point size) { + loadIfNeeded(); + if (mStableDeviceValues.setDisplaySize(size)) { + setDirty(); + } + } + private DisplayState getDisplayState(String uniqueId, boolean createIfAbsent) { loadIfNeeded(); DisplayState state = mDisplayStates.get(uniqueId); @@ -290,6 +311,9 @@ final class PersistentDataStore { if (parser.getName().equals("display-states")) { loadDisplaysFromXml(parser); } + if (parser.getName().equals("stable-device-values")) { + mStableDeviceValues.loadFromXml(parser); + } } } @@ -363,6 +387,9 @@ final class PersistentDataStore { serializer.endTag(null, "display"); } serializer.endTag(null, "display-states"); + serializer.startTag(null, "stable-device-values"); + mStableDeviceValues.saveToXml(serializer); + serializer.endTag(null, "stable-device-values"); serializer.endTag(null, "display-manager-state"); serializer.endDocument(); } @@ -382,6 +409,8 @@ final class PersistentDataStore { pw.println(" " + i++ + ": " + entry.getKey()); entry.getValue().dump(pw, " "); } + pw.println(" StableDeviceValues:"); + mStableDeviceValues.dump(pw, " "); } private static final class DisplayState { @@ -417,8 +446,66 @@ final class PersistentDataStore { serializer.endTag(null, "color-mode"); } - private void dump(final PrintWriter pw, final String prefix) { + public void dump(final PrintWriter pw, final String prefix) { pw.println(prefix + "ColorMode=" + mColorMode); } } + + private static final class StableDeviceValues { + private int mWidth; + private int mHeight; + + private Point getDisplaySize() { + return new Point(mWidth, mHeight); + } + + public boolean setDisplaySize(Point r) { + if (mWidth != r.x || mHeight != r.y) { + mWidth = r.x; + mHeight = r.y; + return true; + } + return false; + } + + public void loadFromXml(XmlPullParser parser) throws IOException, XmlPullParserException { + final int outerDepth = parser.getDepth(); + while (XmlUtils.nextElementWithin(parser, outerDepth)) { + switch (parser.getName()) { + case "stable-display-width": + mWidth = loadIntValue(parser); + break; + case "stable-display-height": + mHeight = loadIntValue(parser); + break; + } + } + } + + private static int loadIntValue(XmlPullParser parser) + throws IOException, XmlPullParserException { + try { + String value = parser.nextText(); + return Integer.parseInt(value); + } catch (NumberFormatException nfe) { + return 0; + } + } + + public void saveToXml(XmlSerializer serializer) throws IOException { + if (mWidth > 0 && mHeight > 0) { + serializer.startTag(null, "stable-display-width"); + serializer.text(Integer.toString(mWidth)); + serializer.endTag(null, "stable-display-width"); + serializer.startTag(null, "stable-display-height"); + serializer.text(Integer.toString(mHeight)); + serializer.endTag(null, "stable-display-height"); + } + } + + public void dump(final PrintWriter pw, final String prefix) { + pw.println(prefix + "StableDisplayWidth=" + mWidth); + pw.println(prefix + "StableDisplayHeight=" + mHeight); + } + } } diff --git a/services/core/java/com/android/server/job/JobSchedulerInternal.java b/services/core/java/com/android/server/job/JobSchedulerInternal.java index bc6bd501176c..095526dc52fc 100644 --- a/services/core/java/com/android/server/job/JobSchedulerInternal.java +++ b/services/core/java/com/android/server/job/JobSchedulerInternal.java @@ -37,4 +37,45 @@ public interface JobSchedulerInternal { void addBackingUpUid(int uid); void removeBackingUpUid(int uid); void clearAllBackingUpUids(); + + JobStorePersistStats getPersistStats(); + + /** + * Stats about the first load after boot and the most recent save. + * STOPSHIP Remove it and the relevant code once b/64536115 is fixed. + */ + public class JobStorePersistStats { + public int countAllJobsLoaded = -1; + public int countSystemServerJobsLoaded = -1; + public int countSystemSyncManagerJobsLoaded = -1; + + public int countAllJobsSaved = -1; + public int countSystemServerJobsSaved = -1; + public int countSystemSyncManagerJobsSaved = -1; + + public JobStorePersistStats() { + } + + public JobStorePersistStats(JobStorePersistStats source) { + countAllJobsLoaded = source.countAllJobsLoaded; + countSystemServerJobsLoaded = source.countSystemServerJobsLoaded; + countSystemSyncManagerJobsLoaded = source.countSystemSyncManagerJobsLoaded; + + countAllJobsSaved = source.countAllJobsSaved; + countSystemServerJobsSaved = source.countSystemServerJobsSaved; + countSystemSyncManagerJobsSaved = source.countSystemSyncManagerJobsSaved; + } + + @Override + public String toString() { + return "FirstLoad: " + + countAllJobsLoaded + "/" + + countSystemServerJobsLoaded + "/" + + countSystemSyncManagerJobsLoaded + + " LastSave: " + + countAllJobsSaved + "/" + + countSystemServerJobsSaved + "/" + + countSystemSyncManagerJobsSaved; + } + } } diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index f82799117302..c6998d6a108c 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -520,11 +520,12 @@ public final class JobSchedulerService extends com.android.server.SystemService if (DEBUG) { Slog.d(TAG, "Receieved: " + action); } + final String pkgName = getPackageName(intent); + final int pkgUid = intent.getIntExtra(Intent.EXTRA_UID, -1); + if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) { // Purge the app's jobs if the whole package was just disabled. When this is // the case the component name will be a bare package name. - final String pkgName = getPackageName(intent); - final int pkgUid = intent.getIntExtra(Intent.EXTRA_UID, -1); if (pkgName != null && pkgUid != -1) { final String[] changedComponents = intent.getStringArrayExtra( Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST); @@ -544,7 +545,8 @@ public final class JobSchedulerService extends com.android.server.SystemService Slog.d(TAG, "Removing jobs for package " + pkgName + " in user " + userId); } - cancelJobsForUid(pkgUid, "app package state changed"); + cancelJobsForPackageAndUid(pkgName, pkgUid, + "app disabled"); } } catch (RemoteException|IllegalArgumentException e) { /* @@ -573,7 +575,7 @@ public final class JobSchedulerService extends com.android.server.SystemService if (DEBUG) { Slog.d(TAG, "Removing jobs for uid: " + uidRemoved); } - cancelJobsForUid(uidRemoved, "app uninstalled"); + cancelJobsForPackageAndUid(pkgName, uidRemoved, "app uninstalled"); } } else if (Intent.ACTION_USER_REMOVED.equals(action)) { final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); @@ -584,8 +586,6 @@ public final class JobSchedulerService extends com.android.server.SystemService } else if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) { // Has this package scheduled any jobs, such that we will take action // if it were to be force-stopped? - final int pkgUid = intent.getIntExtra(Intent.EXTRA_UID, -1); - final String pkgName = intent.getData().getSchemeSpecificPart(); if (pkgUid != -1) { List<JobStatus> jobsForUid; synchronized (mLock) { @@ -604,13 +604,11 @@ public final class JobSchedulerService extends com.android.server.SystemService } } else if (Intent.ACTION_PACKAGE_RESTARTED.equals(action)) { // possible force-stop - final int pkgUid = intent.getIntExtra(Intent.EXTRA_UID, -1); - final String pkgName = intent.getData().getSchemeSpecificPart(); if (pkgUid != -1) { if (DEBUG) { Slog.d(TAG, "Removing jobs for pkg " + pkgName + " at uid " + pkgUid); } - cancelJobsForPackageAndUid(pkgName, pkgUid); + cancelJobsForPackageAndUid(pkgName, pkgUid, "app force stopped"); } } } @@ -790,13 +788,17 @@ public final class JobSchedulerService extends com.android.server.SystemService } } - void cancelJobsForPackageAndUid(String pkgName, int uid) { + void cancelJobsForPackageAndUid(String pkgName, int uid, String reason) { + if ("android".equals(pkgName)) { + Slog.wtfStack(TAG, "Can't cancel all jobs for system package"); + return; + } synchronized (mLock) { final List<JobStatus> jobsForUid = mJobs.getJobsByUid(uid); for (int i = jobsForUid.size() - 1; i >= 0; i--) { final JobStatus job = jobsForUid.get(i); if (job.getSourcePackageName().equals(pkgName)) { - cancelJobImplLocked(job, null, "app force stopped"); + cancelJobImplLocked(job, null, reason); } } } @@ -810,6 +812,10 @@ public final class JobSchedulerService extends com.android.server.SystemService * */ public void cancelJobsForUid(int uid, String reason) { + if (uid == Process.SYSTEM_UID) { + Slog.wtfStack(TAG, "Can't cancel all jobs for system uid"); + return; + } synchronized (mLock) { final List<JobStatus> jobsForUid = mJobs.getJobsByUid(uid); for (int i=0; i<jobsForUid.size(); i++) { @@ -1865,6 +1871,13 @@ public final class JobSchedulerService extends com.android.server.SystemService } } } + + @Override + public JobStorePersistStats getPersistStats() { + synchronized (mLock) { + return new JobStorePersistStats(mJobs.getPersistStats()); + } + } } /** @@ -2045,7 +2058,6 @@ public final class JobSchedulerService extends com.android.server.SystemService @Override public void cancelAll() throws RemoteException { final int uid = Binder.getCallingUid(); - long ident = Binder.clearCallingIdentity(); try { JobSchedulerService.this.cancelJobsForUid(uid, "cancelAll() called by app"); @@ -2487,6 +2499,9 @@ public final class JobSchedulerService extends com.android.server.SystemService pw.print("mReportedActive="); pw.println(mReportedActive); pw.print("mMaxActiveJobs="); pw.println(mMaxActiveJobs); } + pw.println(); + pw.print("PersistStats: "); + pw.println(mJobs.getPersistStats()); } pw.println(); } diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java index 031bdd0ee39c..d3fd3a992a31 100644 --- a/services/core/java/com/android/server/job/JobServiceContext.java +++ b/services/core/java/com/android/server/job/JobServiceContext.java @@ -261,6 +261,13 @@ public final class JobServiceContext implements ServiceConnection { return mRunningJob; } + /** + * Used only for debugging. Will return <code>"<null>"</code> if there is no job running. + */ + private String getRunningJobNameLocked() { + return mRunningJob != null ? mRunningJob.toShortString() : "<null>"; + } + /** Called externally when a job that was scheduled for execution should be cancelled. */ void cancelExecutingJobLocked(int reason, String debugReason) { doCancelLocked(reason, debugReason); @@ -522,7 +529,7 @@ public final class JobServiceContext implements ServiceConnection { /** Start the job on the service. */ private void handleServiceBoundLocked() { if (DEBUG) { - Slog.d(TAG, "handleServiceBound for " + mRunningJob.toShortString()); + Slog.d(TAG, "handleServiceBound for " + getRunningJobNameLocked()); } if (mVerb != VERB_BINDING) { Slog.e(TAG, "Sending onStartJob for a job that isn't pending. " @@ -639,36 +646,34 @@ public final class JobServiceContext implements ServiceConnection { private void handleOpTimeoutLocked() { switch (mVerb) { case VERB_BINDING: - Slog.w(TAG, "Time-out while trying to bind " + mRunningJob.toShortString() + - ", dropping."); + Slog.w(TAG, "Time-out while trying to bind " + getRunningJobNameLocked() + + ", dropping."); closeAndCleanupJobLocked(false /* needsReschedule */, "timed out while binding"); break; case VERB_STARTING: // Client unresponsive - wedged or failed to respond in time. We don't really // know what happened so let's log it and notify the JobScheduler // FINISHED/NO-RETRY. - Slog.w(TAG, "No response from client for onStartJob " + - mRunningJob != null ? mRunningJob.toShortString() : "<null>"); + Slog.w(TAG, "No response from client for onStartJob " + + getRunningJobNameLocked()); closeAndCleanupJobLocked(false /* needsReschedule */, "timed out while starting"); break; case VERB_STOPPING: // At least we got somewhere, so fail but ask the JobScheduler to reschedule. - Slog.w(TAG, "No response from client for onStopJob " + - mRunningJob != null ? mRunningJob.toShortString() : "<null>"); + Slog.w(TAG, "No response from client for onStopJob " + + getRunningJobNameLocked()); closeAndCleanupJobLocked(true /* needsReschedule */, "timed out while stopping"); break; case VERB_EXECUTING: // Not an error - client ran out of time. Slog.i(TAG, "Client timed out while executing (no jobFinished received), " + - "sending onStop: " + - mRunningJob != null ? mRunningJob.toShortString() : "<null>"); + "sending onStop: " + getRunningJobNameLocked()); mParams.setStopReason(JobParameters.REASON_TIMEOUT); sendStopMessageLocked("timeout while executing"); break; default: - Slog.e(TAG, "Handling timeout for an invalid job state: " + - mRunningJob != null ? mRunningJob.toShortString() : "<null>" - + ", dropping."); + Slog.e(TAG, "Handling timeout for an invalid job state: " + + getRunningJobNameLocked() + ", dropping."); closeAndCleanupJobLocked(false /* needsReschedule */, "invalid timeout"); } } diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java index 62b06d6242ea..aa9f77c839e5 100644 --- a/services/core/java/com/android/server/job/JobStore.java +++ b/services/core/java/com/android/server/job/JobStore.java @@ -24,6 +24,7 @@ import android.content.Context; import android.os.Environment; import android.os.Handler; import android.os.PersistableBundle; +import android.os.Process; import android.os.SystemClock; import android.os.UserHandle; import android.text.format.DateUtils; @@ -38,6 +39,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastXmlSerializer; import com.android.server.IoThread; +import com.android.server.job.JobSchedulerInternal.JobStorePersistStats; import com.android.server.job.controllers.JobStatus; import java.io.ByteArrayOutputStream; @@ -89,6 +91,8 @@ public final class JobStore { private final Handler mIoHandler = IoThread.getHandler(); private static JobStore sSingleton; + private JobStorePersistStats mPersistInfo = new JobStorePersistStats(); + /** Used by the {@link JobSchedulerService} to instantiate the JobStore. */ static JobStore initAndGet(JobSchedulerService jobManagerService) { synchronized (sSingletonLock) { @@ -199,6 +203,10 @@ public final class JobStore { return mJobSet.size(); } + public JobStorePersistStats getPersistStats() { + return mPersistInfo; + } + public int countJobsForUid(int uid) { return mJobSet.countJobsForUid(uid); } @@ -336,6 +344,9 @@ public final class JobStore { } private void writeJobsMapImpl(List<JobStatus> jobList) { + int numJobs = 0; + int numSystemJobs = 0; + int numSyncJobs = 0; try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); XmlSerializer out = new FastXmlSerializer(); @@ -356,6 +367,14 @@ public final class JobStore { writeExecutionCriteriaToXml(out, jobStatus); writeBundleToXml(jobStatus.getJob().getExtras(), out); out.endTag(null, "job"); + + numJobs++; + if (jobStatus.getUid() == Process.SYSTEM_UID) { + numSystemJobs++; + if (isSyncJob(jobStatus)) { + numSyncJobs++; + } + } } out.endTag(null, "job-info"); out.endDocument(); @@ -373,6 +392,10 @@ public final class JobStore { if (DEBUG) { Slog.d(TAG, "Error persisting bundle.", e); } + } finally { + mPersistInfo.countAllJobsSaved = numJobs; + mPersistInfo.countSystemServerJobsSaved = numSystemJobs; + mPersistInfo.countSystemSyncManagerJobsSaved = numSyncJobs; } } @@ -525,6 +548,11 @@ public final class JobStore { return Pair.create(earliest, latest); } + private static boolean isSyncJob(JobStatus status) { + return com.android.server.content.SyncJobService.class.getName() + .equals(status.getServiceComponent().getClassName()); + } + /** * Runnable that reads list of persisted job from xml. This is run once at start up, so doesn't * need to go through {@link JobStore#add(com.android.server.job.controllers.JobStatus)}. @@ -544,6 +572,9 @@ public final class JobStore { @Override public void run() { + int numJobs = 0; + int numSystemJobs = 0; + int numSyncJobs = 0; try { List<JobStatus> jobs; FileInputStream fis = mJobsFile.openRead(); @@ -557,6 +588,14 @@ public final class JobStore { js.prepareLocked(am); js.enqueueTime = now; this.jobSet.add(js); + + numJobs++; + if (js.getUid() == Process.SYSTEM_UID) { + numSystemJobs++; + if (isSyncJob(js)) { + numSyncJobs++; + } + } } } } @@ -565,15 +604,16 @@ public final class JobStore { if (DEBUG) { Slog.d(TAG, "Could not find jobs file, probably there was nothing to load."); } - } catch (XmlPullParserException e) { - if (DEBUG) { - Slog.d(TAG, "Error parsing xml.", e); - } - } catch (IOException e) { - if (DEBUG) { - Slog.d(TAG, "Error parsing xml.", e); + } catch (XmlPullParserException | IOException e) { + Slog.wtf(TAG, "Error jobstore xml.", e); + } finally { + if (mPersistInfo.countAllJobsLoaded < 0) { // Only set them once. + mPersistInfo.countAllJobsLoaded = numJobs; + mPersistInfo.countSystemServerJobsLoaded = numSystemJobs; + mPersistInfo.countSystemSyncManagerJobsLoaded = numSyncJobs; } } + Slog.i(TAG, "Read " + numJobs + " jobs"); } private List<JobStatus> readJobMapImpl(FileInputStream fis, boolean rtcIsGood) diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java index 436ea3cd720a..f549a86583c0 100644 --- a/services/core/java/com/android/server/location/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/GnssLocationProvider.java @@ -461,7 +461,10 @@ public class GnssLocationProvider implements LocationProviderInterface { requestUtcTime(); } if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) { - xtraDownloadRequest(); + if (mSupportsXtra) { + // Download only if supported, (prevents an unneccesary on-boot download) + xtraDownloadRequest(); + } } // Always on, notify HAL so it can get data it needs sendMessage(UPDATE_NETWORK_STATE, 0 /*arg*/, network); @@ -2311,6 +2314,7 @@ public class GnssLocationProvider implements LocationProviderInterface { NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder(); networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); + networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_BLUETOOTH); NetworkRequest networkRequest = networkRequestBuilder.build(); mConnMgr.registerNetworkCallback(networkRequest, mNetworkConnectivityCallback); diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 83bacc2350be..a1b84568943f 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -19,6 +19,7 @@ package com.android.server.locksettings; import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE; import static android.Manifest.permission.READ_CONTACTS; import static android.content.Context.KEYGUARD_SERVICE; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT; import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_KEY; @@ -73,10 +74,12 @@ import android.security.KeyStore; import android.security.keystore.AndroidKeyStoreProvider; import android.security.keystore.KeyProperties; import android.security.keystore.KeyProtection; +import android.security.keystore.UserNotAuthenticatedException; import android.service.gatekeeper.GateKeeperResponse; import android.service.gatekeeper.IGateKeeperService; import android.text.TextUtils; import android.util.ArrayMap; +import android.util.EventLog; import android.util.Log; import android.util.Slog; @@ -501,12 +504,34 @@ public class LockSettingsService extends ILockSettings.Stub { maybeShowEncryptionNotificationForUser(userId); } + /** + * Check if profile got unlocked but the keystore is still locked. This happens on full disk + * encryption devices since the profile may not yet be running when we consider unlocking it + * during the normal flow. In this case unlock the keystore for the profile. + */ + private void ensureProfileKeystoreUnlocked(int userId) { + final KeyStore ks = KeyStore.getInstance(); + if (ks.state(userId) == KeyStore.State.LOCKED + && tiedManagedProfileReadyToUnlock(mUserManager.getUserInfo(userId))) { + Slog.i(TAG, "Managed profile got unlocked, will unlock its keystore"); + try { + // If boot took too long and the password in vold got expired, parent keystore will + // be still locked, we ignore this case since the user will be prompted to unlock + // the device after boot. + unlockChildProfile(userId, true /* ignoreUserNotAuthenticated */); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to unlock child profile"); + } + } + } + public void onUnlockUser(final int userId) { // Perform tasks which require locks in LSS on a handler, as we are callbacks from // ActivityManager.unlockUser() mHandler.post(new Runnable() { @Override public void run() { + ensureProfileKeystoreUnlocked(userId); // Hide notification first, as tie managed profile lock takes time hideEncryptionNotification(new UserHandle(userId)); @@ -559,6 +584,10 @@ public class LockSettingsService extends ILockSettings.Stub { @Override // binder interface public void systemReady() { + if (mContext.checkCallingOrSelfPermission(PERMISSION) != PERMISSION_GRANTED) { + EventLog.writeEvent(0x534e4554, "28251513", getCallingUid(), ""); // SafetyNet + } + checkWritePermission(UserHandle.USER_SYSTEM); migrateOldData(); try { getGateKeeperService(); @@ -805,6 +834,13 @@ public class LockSettingsService extends ILockSettings.Stub { mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsRead"); } + private final void checkPasswordHavePermission(int userId) { + if (mContext.checkCallingOrSelfPermission(PERMISSION) != PERMISSION_GRANTED) { + EventLog.writeEvent(0x534e4554, "28251513", getCallingUid(), ""); // SafetyNet + } + mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsHave"); + } + private final void checkReadPermission(String requestedKey, int userId) { final int callingUid = Binder.getCallingUid(); @@ -934,6 +970,7 @@ public class LockSettingsService extends ILockSettings.Stub { @Override public boolean havePassword(int userId) throws RemoteException { + checkPasswordHavePermission(userId); synchronized (mSpManager) { if (isSyntheticPasswordBasedCredentialLocked(userId)) { long handle = getSyntheticPasswordHandleLocked(userId); @@ -947,6 +984,7 @@ public class LockSettingsService extends ILockSettings.Stub { @Override public boolean havePattern(int userId) throws RemoteException { + checkPasswordHavePermission(userId); synchronized (mSpManager) { if (isSyntheticPasswordBasedCredentialLocked(userId)) { long handle = getSyntheticPasswordHandleLocked(userId); @@ -1012,7 +1050,8 @@ public class LockSettingsService extends ILockSettings.Stub { return new String(decryptionResult, StandardCharsets.UTF_8); } - private void unlockChildProfile(int profileHandle) throws RemoteException { + private void unlockChildProfile(int profileHandle, boolean ignoreUserNotAuthenticated) + throws RemoteException { try { doVerifyCredential(getDecryptedPasswordForTiedProfile(profileHandle), LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, @@ -1023,6 +1062,8 @@ public class LockSettingsService extends ILockSettings.Stub { | BadPaddingException | CertificateException | IOException e) { if (e instanceof FileNotFoundException) { Slog.i(TAG, "Child profile key not found"); + } else if (ignoreUserNotAuthenticated && e instanceof UserNotAuthenticatedException) { + Slog.i(TAG, "Parent keystore seems locked, ignoring"); } else { Slog.e(TAG, "Failed to decrypt child profile key", e); } @@ -1066,11 +1107,8 @@ public class LockSettingsService extends ILockSettings.Stub { final List<UserInfo> profiles = mUserManager.getProfiles(userId); for (UserInfo pi : profiles) { // Unlock managed profile with unified lock - if (pi.isManagedProfile() - && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id) - && mStorage.hasChildProfileLock(pi.id) - && mUserManager.isUserRunning(pi.id)) { - unlockChildProfile(pi.id); + if (tiedManagedProfileReadyToUnlock(pi)) { + unlockChildProfile(pi.id, false /* ignoreUserNotAuthenticated */); } } } @@ -1079,6 +1117,13 @@ public class LockSettingsService extends ILockSettings.Stub { } } + private boolean tiedManagedProfileReadyToUnlock(UserInfo userInfo) { + return userInfo.isManagedProfile() + && !mLockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id) + && mStorage.hasChildProfileLock(userInfo.id) + && mUserManager.isUserRunning(userInfo.id); + } + private Map<Integer, String> getDecryptedPasswordsForAllTiedProfiles(int userId) { if (mUserManager.getUserInfo(userId).isManagedProfile()) { return null; diff --git a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java index d39679dcfad0..4d2cf321b5ee 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsShellCommand.java @@ -37,6 +37,7 @@ class LockSettingsShellCommand extends ShellCommand { private static final String COMMAND_SP = "sp"; private static final String COMMAND_SET_DISABLED = "set-disabled"; private static final String COMMAND_VERIFY = "verify"; + private static final String COMMAND_GET_DISABLED = "get-disabled"; private int mCurrentUserId; private final LockPatternUtils mLockPatternUtils; @@ -80,6 +81,9 @@ class LockSettingsShellCommand extends ShellCommand { case COMMAND_VERIFY: runVerify(); break; + case COMMAND_GET_DISABLED: + runGetDisabled(); + break; default: getErrPrintWriter().println("Unknown command: " + cmd); break; @@ -156,6 +160,11 @@ class LockSettingsShellCommand extends ShellCommand { getOutPrintWriter().println("Lock screen disabled set to " + disabled); } + private void runGetDisabled() { + boolean isLockScreenDisabled = mLockPatternUtils.isLockScreenDisabled(mCurrentUserId); + getOutPrintWriter().println(isLockScreenDisabled); + } + private boolean checkCredential() throws RemoteException { final boolean havePassword = mLockPatternUtils.isLockPasswordEnabled(mCurrentUserId); final boolean havePattern = mLockPatternUtils.isLockPatternEnabled(mCurrentUserId); diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java index 922df1e3dba8..3795b7f3091c 100644 --- a/services/core/java/com/android/server/media/MediaRouterService.java +++ b/services/core/java/com/android/server/media/MediaRouterService.java @@ -18,9 +18,7 @@ package com.android.server.media; import com.android.internal.util.DumpUtils; import com.android.server.Watchdog; -import com.android.server.media.AudioPlaybackMonitor.OnAudioPlayerActiveStateChangedListener; -import android.Manifest; import android.app.ActivityManager; import android.content.BroadcastReceiver; import android.content.Context; @@ -96,9 +94,10 @@ public final class MediaRouterService extends IMediaRouterService.Stub private final ArrayMap<IBinder, ClientRecord> mAllClientRecords = new ArrayMap<IBinder, ClientRecord>(); private int mCurrentUserId = -1; - private boolean mHasBluetoothRoute = false; + private boolean mGlobalBluetoothA2dpOn = false; private final IAudioService mAudioService; private final AudioPlaybackMonitor mAudioPlaybackMonitor; + private final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo(); public MediaRouterService(Context context) { mContext = context; @@ -137,13 +136,39 @@ public final class MediaRouterService extends IMediaRouterService.Stub audioRoutes = mAudioService.startWatchingRoutes(new IAudioRoutesObserver.Stub() { @Override public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) { - mHasBluetoothRoute = newRoutes.bluetoothName != null; + synchronized (mLock) { + if (newRoutes.mainType != mCurAudioRoutesInfo.mainType) { + if ((newRoutes.mainType & (AudioRoutesInfo.MAIN_HEADSET + | AudioRoutesInfo.MAIN_HEADPHONES + | AudioRoutesInfo.MAIN_USB)) == 0) { + // headset was plugged out. + mGlobalBluetoothA2dpOn = newRoutes.bluetoothName != null; + } else { + // headset was plugged in. + mGlobalBluetoothA2dpOn = false; + } + mCurAudioRoutesInfo.mainType = newRoutes.mainType; + } + if (!TextUtils.equals( + newRoutes.bluetoothName, mCurAudioRoutesInfo.bluetoothName)) { + if (newRoutes.bluetoothName == null) { + // BT was disconnected. + mGlobalBluetoothA2dpOn = false; + } else { + // BT was connected or changed. + mGlobalBluetoothA2dpOn = true; + } + mCurAudioRoutesInfo.bluetoothName = newRoutes.bluetoothName; + } + } } }); } catch (RemoteException e) { Slog.w(TAG, "RemoteException in the audio service."); } - mHasBluetoothRoute = (audioRoutes != null && audioRoutes.bluetoothName != null); + synchronized (mLock) { + mGlobalBluetoothA2dpOn = (audioRoutes != null && audioRoutes.bluetoothName != null); + } } public void systemRunning() { @@ -246,6 +271,14 @@ public final class MediaRouterService extends IMediaRouterService.Stub // Binder call @Override + public boolean isGlobalBluetoothA2doOn() { + synchronized (mLock) { + return mGlobalBluetoothA2dpOn; + } + } + + // Binder call + @Override public void setDiscoveryRequest(IMediaRouterClient client, int routeTypes, boolean activeScan) { if (client == null) { @@ -346,7 +379,12 @@ public final class MediaRouterService extends IMediaRouterService.Stub void restoreBluetoothA2dp() { try { - mAudioService.setBluetoothA2dpOn(mHasBluetoothRoute); + boolean a2dpOn = false; + synchronized (mLock) { + a2dpOn = mGlobalBluetoothA2dpOn; + } + Slog.v(TAG, "restoreBluetoothA2dp( " + a2dpOn + ")"); + mAudioService.setBluetoothA2dpOn(a2dpOn); } catch (RemoteException e) { Slog.w(TAG, "RemoteException while calling setBluetoothA2dpOn."); } @@ -354,12 +392,14 @@ public final class MediaRouterService extends IMediaRouterService.Stub void restoreRoute(int uid) { ClientRecord clientRecord = null; - UserRecord userRecord = mUserRecords.get(UserHandle.getUserId(uid)); - if (userRecord != null && userRecord.mClientRecords != null) { - for (ClientRecord cr : userRecord.mClientRecords) { - if (validatePackageName(uid, cr.mPackageName)) { - clientRecord = cr; - break; + synchronized (mLock) { + UserRecord userRecord = mUserRecords.get(UserHandle.getUserId(uid)); + if (userRecord != null && userRecord.mClientRecords != null) { + for (ClientRecord cr : userRecord.mClientRecords) { + if (validatePackageName(uid, cr.mPackageName)) { + clientRecord = cr; + break; + } } } } diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 69efcc32740a..b224069d04f8 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -33,6 +33,7 @@ import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLE import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED; import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED; import static android.net.ConnectivityManager.TYPE_MOBILE; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkPolicy.LIMIT_DISABLED; import static android.net.NetworkPolicy.SNOOZE_NEVER; import static android.net.NetworkPolicy.WARNING_DISABLED; @@ -191,8 +192,6 @@ import com.android.server.power.BatterySaverPolicy.ServiceType; import libcore.io.IoUtils; -import com.google.android.collect.Lists; - import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlSerializer; @@ -373,8 +372,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { /** Defined network policies. */ final ArrayMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = new ArrayMap<>(); - /** Currently active network rules for ifaces. */ - final ArrayMap<NetworkPolicy, String[]> mNetworkRules = new ArrayMap<>(); /** Map from subId to subscription plans. */ final SparseArray<SubscriptionPlan[]> mSubscriptionPlans = new SparseArray<>(); @@ -927,7 +924,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { /** * Receiver that watches for {@link WifiConfiguration} to be loaded so that - * we can perform upgrade logic. + * we can perform upgrade logic. After initial upgrade logic, it updates + * {@link #mMeteredIfaces} based on configuration changes. */ final private BroadcastReceiver mWifiReceiver = new BroadcastReceiver() { @Override @@ -935,10 +933,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { synchronized (mUidRulesFirstLock) { synchronized (mNetworkPoliciesSecondLock) { upgradeWifiMeteredOverrideAL(); + updateNetworkRulesNL(); } } - // Only need to perform upgrade logic once - mContext.unregisterReceiver(this); } }; @@ -1445,6 +1442,22 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } /** + * Collect all ifaces from a {@link NetworkState} into the given set. + */ + private static void collectIfaces(ArraySet<String> ifaces, NetworkState state) { + final String baseIface = state.linkProperties.getInterfaceName(); + if (baseIface != null) { + ifaces.add(baseIface); + } + for (LinkProperties stackedLink : state.linkProperties.getStackedLinks()) { + final String stackedIface = stackedLink.getInterfaceName(); + if (stackedIface != null) { + ifaces.add(stackedIface); + } + } + } + + /** * Examine all connected {@link NetworkState}, looking for * {@link NetworkPolicy} that need to be enforced. When matches found, set * remaining quota based on usage cycle and historical stats. @@ -1462,60 +1475,33 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // First, generate identities of all connected networks so we can // quickly compare them against all defined policies below. - final ArrayList<Pair<String, NetworkIdentity>> connIdents = new ArrayList<>(states.length); - final ArraySet<String> connIfaces = new ArraySet<String>(states.length); + final ArrayMap<NetworkState, NetworkIdentity> identified = new ArrayMap<>(); for (NetworkState state : states) { if (state.networkInfo != null && state.networkInfo.isConnected()) { final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state); - - final String baseIface = state.linkProperties.getInterfaceName(); - if (baseIface != null) { - connIdents.add(Pair.create(baseIface, ident)); - } - - // Stacked interfaces are considered to have same identity as - // their parent network. - final List<LinkProperties> stackedLinks = state.linkProperties.getStackedLinks(); - for (LinkProperties stackedLink : stackedLinks) { - final String stackedIface = stackedLink.getInterfaceName(); - if (stackedIface != null) { - connIdents.add(Pair.create(stackedIface, ident)); - } - } + identified.put(state, ident); } } - // Apply policies against all connected interfaces found above - mNetworkRules.clear(); - final ArrayList<String> ifaceList = Lists.newArrayList(); + final ArraySet<String> newMeteredIfaces = new ArraySet<>(); + long lowestRule = Long.MAX_VALUE; + + // For every well-defined policy, compute remaining data based on + // current cycle and historical stats, and push to kernel. + final ArraySet<String> matchingIfaces = new ArraySet<>(); for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) { - final NetworkPolicy policy = mNetworkPolicy.valueAt(i); + final NetworkPolicy policy = mNetworkPolicy.valueAt(i); - ifaceList.clear(); - for (int j = connIdents.size() - 1; j >= 0; j--) { - final Pair<String, NetworkIdentity> ident = connIdents.get(j); - if (policy.template.matches(ident.second)) { - ifaceList.add(ident.first); + // Collect all ifaces that match this policy + matchingIfaces.clear(); + for (int j = identified.size() - 1; j >= 0; j--) { + if (policy.template.matches(identified.valueAt(j))) { + collectIfaces(matchingIfaces, identified.keyAt(j)); } } - if (ifaceList.size() > 0) { - final String[] ifaces = ifaceList.toArray(new String[ifaceList.size()]); - mNetworkRules.put(policy, ifaces); - } - } - - long lowestRule = Long.MAX_VALUE; - final ArraySet<String> newMeteredIfaces = new ArraySet<String>(states.length); - - // apply each policy that we found ifaces for; compute remaining data - // based on current cycle and historical stats, and push to kernel. - for (int i = mNetworkRules.size()-1; i >= 0; i--) { - final NetworkPolicy policy = mNetworkRules.keyAt(i); - final String[] ifaces = mNetworkRules.valueAt(i); - if (LOGD) { - Slog.d(TAG, "applying policy " + policy + " to ifaces " + Arrays.toString(ifaces)); + Slog.d(TAG, "Applying " + policy + " to ifaces " + matchingIfaces); } final boolean hasWarning = policy.warningBytes != LIMIT_DISABLED; @@ -1545,16 +1531,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { quotaBytes = Long.MAX_VALUE; } - if (ifaces.length > 1) { + if (matchingIfaces.size() > 1) { // TODO: switch to shared quota once NMS supports Slog.w(TAG, "shared quota unsupported; generating rule for each iface"); } - for (String iface : ifaces) { - // long quotaBytes split up into two ints to fit in message - mHandler.obtainMessage(MSG_UPDATE_INTERFACE_QUOTA, - (int) (quotaBytes >> 32), (int) (quotaBytes & 0xFFFFFFFF), iface) - .sendToTarget(); + for (int j = matchingIfaces.size() - 1; j >= 0; j--) { + final String iface = matchingIfaces.valueAt(j); + setInterfaceQuotaAsync(iface, quotaBytes); newMeteredIfaces.add(iface); } } @@ -1568,29 +1552,36 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } - for (int i = connIfaces.size()-1; i >= 0; i--) { - String iface = connIfaces.valueAt(i); - // long quotaBytes split up into two ints to fit in message - mHandler.obtainMessage(MSG_UPDATE_INTERFACE_QUOTA, - (int) (Long.MAX_VALUE >> 32), (int) (Long.MAX_VALUE & 0xFFFFFFFF), iface) - .sendToTarget(); - newMeteredIfaces.add(iface); + // One final pass to catch any metered ifaces that don't have explicitly + // defined policies; typically Wi-Fi networks. + for (NetworkState state : states) { + if (state.networkInfo != null && state.networkInfo.isConnected() + && !state.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)) { + matchingIfaces.clear(); + collectIfaces(matchingIfaces, state); + for (int j = matchingIfaces.size() - 1; j >= 0; j--) { + final String iface = matchingIfaces.valueAt(j); + if (!newMeteredIfaces.contains(iface)) { + setInterfaceQuotaAsync(iface, Long.MAX_VALUE); + newMeteredIfaces.add(iface); + } + } + } } - mHandler.obtainMessage(MSG_ADVISE_PERSIST_THRESHOLD, lowestRule).sendToTarget(); - - // remove quota on any trailing interfaces + // Remove quota from any interfaces that are no longer metered. for (int i = mMeteredIfaces.size() - 1; i >= 0; i--) { final String iface = mMeteredIfaces.valueAt(i); if (!newMeteredIfaces.contains(iface)) { - mHandler.obtainMessage(MSG_REMOVE_INTERFACE_QUOTA, iface) - .sendToTarget(); + removeInterfaceQuotaAsync(iface); } } mMeteredIfaces = newMeteredIfaces; final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]); mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget(); + + mHandler.obtainMessage(MSG_ADVISE_PERSIST_THRESHOLD, lowestRule).sendToTarget(); } /** @@ -3000,9 +2991,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { updateRestrictBackgroundRulesOnUidStatusChangedUL(uid, oldUidState, uidState); if (isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState) != isProcStateAllowedWhileIdleOrPowerSaveMode(uidState) ) { - if (isUidIdle(uid)) { - updateRuleForAppIdleUL(uid); - } + updateRuleForAppIdleUL(uid); if (mDeviceIdleMode) { updateRuleForDeviceIdleUL(uid); } @@ -3975,6 +3964,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + private void setInterfaceQuotaAsync(String iface, long quotaBytes) { + // long quotaBytes split up into two ints to fit in message + mHandler.obtainMessage(MSG_UPDATE_INTERFACE_QUOTA, (int) (quotaBytes >> 32), + (int) (quotaBytes & 0xFFFFFFFF), iface).sendToTarget(); + } + private void setInterfaceQuota(String iface, long quotaBytes) { try { mNetworkManager.setInterfaceQuota(iface, quotaBytes); @@ -3985,6 +3980,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + private void removeInterfaceQuotaAsync(String iface) { + mHandler.obtainMessage(MSG_REMOVE_INTERFACE_QUOTA, iface).sendToTarget(); + } + private void removeInterfaceQuota(String iface) { try { mNetworkManager.removeInterfaceQuota(iface); diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 03543007c80e..8837c157aebe 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -28,6 +28,8 @@ import static android.net.NetworkStats.UID_ALL; import static android.net.TrafficStats.UID_REMOVED; import static android.text.format.DateUtils.WEEK_IN_MILLIS; +import static com.android.server.net.NetworkStatsService.TAG; + import android.net.NetworkIdentity; import android.net.NetworkStats; import android.net.NetworkStatsHistory; @@ -37,20 +39,24 @@ import android.os.Binder; import android.service.NetworkStatsCollectionKeyProto; import android.service.NetworkStatsCollectionProto; import android.service.NetworkStatsCollectionStatsProto; +import android.telephony.SubscriptionPlan; import android.util.ArrayMap; import android.util.AtomicFile; import android.util.IntArray; +import android.util.Pair; +import android.util.Slog; import android.util.proto.ProtoOutputStream; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; +import libcore.io.IoUtils; + import com.google.android.collect.Lists; import com.google.android.collect.Maps; -import libcore.io.IoUtils; - import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -60,9 +66,11 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.net.ProtocolException; +import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.Objects; /** @@ -140,6 +148,35 @@ public class NetworkStatsCollection implements FileRotator.Reader { return mStartMillis == Long.MAX_VALUE && mEndMillis == Long.MIN_VALUE; } + @VisibleForTesting + public long roundUp(long time) { + if (time == Long.MIN_VALUE || time == Long.MAX_VALUE + || time == SubscriptionPlan.TIME_UNKNOWN) { + return time; + } else { + final long mod = time % mBucketDuration; + if (mod > 0) { + time -= mod; + time += mBucketDuration; + } + return time; + } + } + + @VisibleForTesting + public long roundDown(long time) { + if (time == Long.MIN_VALUE || time == Long.MAX_VALUE + || time == SubscriptionPlan.TIME_UNKNOWN) { + return time; + } else { + final long mod = time % mBucketDuration; + if (mod > 0) { + time -= mod; + } + return time; + } + } + public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel) { return getRelevantUids(accessLevel, Binder.getCallingUid()); } @@ -165,60 +202,110 @@ public class NetworkStatsCollection implements FileRotator.Reader { * Combine all {@link NetworkStatsHistory} in this collection which match * the requested parameters. */ - public NetworkStatsHistory getHistory( - NetworkTemplate template, int uid, int set, int tag, int fields, - @NetworkStatsAccess.Level int accessLevel) { - return getHistory(template, uid, set, tag, fields, Long.MIN_VALUE, Long.MAX_VALUE, - accessLevel); - } - - /** - * Combine all {@link NetworkStatsHistory} in this collection which match - * the requested parameters. - */ - public NetworkStatsHistory getHistory( - NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end, - @NetworkStatsAccess.Level int accessLevel) { - return getHistory(template, uid, set, tag, fields, start, end, accessLevel, - Binder.getCallingUid()); - } - - /** - * Combine all {@link NetworkStatsHistory} in this collection which match - * the requested parameters. - */ - public NetworkStatsHistory getHistory( - NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end, + public NetworkStatsHistory getHistory(NetworkTemplate template, SubscriptionPlan augmentPlan, + int uid, int set, int tag, int fields, long start, long end, @NetworkStatsAccess.Level int accessLevel, int callerUid) { if (!NetworkStatsAccess.isAccessibleToUser(uid, callerUid, accessLevel)) { throw new SecurityException("Network stats history of uid " + uid + " is forbidden for caller " + callerUid); } + final int bucketEstimate = (int) ((end - start) / mBucketDuration); final NetworkStatsHistory combined = new NetworkStatsHistory( - mBucketDuration, start == end ? 1 : estimateBuckets(), fields); + mBucketDuration, bucketEstimate, fields); // shortcut when we know stats will be empty if (start == end) return combined; + // Figure out the window of time that we should be augmenting (if any) + long augmentStart = SubscriptionPlan.TIME_UNKNOWN; + long augmentEnd = (augmentPlan != null) ? augmentPlan.getDataUsageTime() + : SubscriptionPlan.TIME_UNKNOWN; + // And if augmenting, we might need to collect more data to adjust with + long collectStart = start; + long collectEnd = end; + + if (augmentEnd != SubscriptionPlan.TIME_UNKNOWN) { + final Iterator<Pair<ZonedDateTime, ZonedDateTime>> it = augmentPlan.cycleIterator(); + while (it.hasNext()) { + final Pair<ZonedDateTime, ZonedDateTime> cycle = it.next(); + final long cycleStart = cycle.first.toInstant().toEpochMilli(); + final long cycleEnd = cycle.second.toInstant().toEpochMilli(); + if (cycleStart <= augmentEnd && augmentEnd < cycleEnd) { + augmentStart = cycleStart; + collectStart = Long.min(collectStart, augmentStart); + collectEnd = Long.max(collectEnd, augmentEnd); + break; + } + } + } + + if (augmentStart != SubscriptionPlan.TIME_UNKNOWN) { + // Shrink augmentation window so we don't risk undercounting. + augmentStart = roundUp(augmentStart); + augmentEnd = roundDown(augmentEnd); + // Grow collection window so we get all the stats needed. + collectStart = roundDown(collectStart); + collectEnd = roundUp(collectEnd); + } + for (int i = 0; i < mStats.size(); i++) { final Key key = mStats.keyAt(i); if (key.uid == uid && NetworkStats.setMatches(set, key.set) && key.tag == tag && templateMatches(template, key.ident)) { final NetworkStatsHistory value = mStats.valueAt(i); - combined.recordHistory(value, start, end); + combined.recordHistory(value, collectStart, collectEnd); } } - return combined; - } - /** - * Summarize all {@link NetworkStatsHistory} in this collection which match - * the requested parameters. - */ - public NetworkStats getSummary(NetworkTemplate template, long start, long end, - @NetworkStatsAccess.Level int accessLevel) { - return getSummary(template, start, end, accessLevel, Binder.getCallingUid()); + if (augmentStart != SubscriptionPlan.TIME_UNKNOWN) { + final NetworkStatsHistory.Entry entry = combined.getValues( + augmentStart, augmentEnd, null); + + // If we don't have any recorded data for this time period, give + // ourselves something to scale with. + if (entry.rxBytes == 0 || entry.txBytes == 0) { + combined.recordData(augmentStart, augmentEnd, + new NetworkStats.Entry(1, 0, 1, 0, 0)); + combined.getValues(augmentStart, augmentEnd, entry); + } + + final long rawBytes = entry.rxBytes + entry.txBytes; + final long rawRxBytes = entry.rxBytes; + final long rawTxBytes = entry.txBytes; + final long targetBytes = augmentPlan.getDataUsageBytes(); + final long targetRxBytes = (rawRxBytes * targetBytes) / rawBytes; + final long targetTxBytes = (rawTxBytes * targetBytes) / rawBytes; + + // Scale all matching buckets to reach anchor target + final long beforeTotal = combined.getTotalBytes(); + for (int i = 0; i < combined.size(); i++) { + combined.getValues(i, entry); + if (entry.bucketStart >= augmentStart + && entry.bucketStart + entry.bucketDuration <= augmentEnd) { + entry.rxBytes = (entry.rxBytes * targetRxBytes) / rawRxBytes; + entry.txBytes = (entry.txBytes * targetTxBytes) / rawTxBytes; + // We purposefully clear out packet counters to indicate + // that this data has been augmented. + entry.rxPackets = 0; + entry.txPackets = 0; + combined.setValues(i, entry); + } + } + + final long deltaTotal = combined.getTotalBytes() - beforeTotal; + if (deltaTotal != 0) { + Slog.d(TAG, "Augmented network usage by " + deltaTotal + " bytes"); + } + + // Finally we can slice data as originally requested + final NetworkStatsHistory sliced = new NetworkStatsHistory( + mBucketDuration, bucketEstimate, fields); + sliced.recordHistory(combined, start, end); + return sliced; + } else { + return combined; + } } /** @@ -230,6 +317,7 @@ public class NetworkStatsCollection implements FileRotator.Reader { final long now = System.currentTimeMillis(); final NetworkStats stats = new NetworkStats(end - start, 24); + // shortcut when we know stats will be empty if (start == end) return stats; diff --git a/services/core/java/com/android/server/net/NetworkStatsObservers.java b/services/core/java/com/android/server/net/NetworkStatsObservers.java index a256cbcf9030..741c2062bd57 100644 --- a/services/core/java/com/android/server/net/NetworkStatsObservers.java +++ b/services/core/java/com/android/server/net/NetworkStatsObservers.java @@ -17,28 +17,26 @@ package com.android.server.net; import static android.net.TrafficStats.MB_IN_BYTES; + import static com.android.internal.util.Preconditions.checkArgument; import android.app.usage.NetworkStatsManager; import android.net.DataUsageRequest; import android.net.NetworkStats; -import android.net.NetworkStats.NonMonotonicObserver; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; -import android.os.Binder; import android.os.Bundle; -import android.os.Looper; -import android.os.Message; -import android.os.Messenger; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.Messenger; import android.os.Process; import android.os.RemoteException; import android.util.ArrayMap; -import android.util.IntArray; -import android.util.SparseArray; import android.util.Slog; +import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.net.VpnInfo; @@ -410,7 +408,7 @@ class NetworkStatsObservers { */ private long getTotalBytesForNetworkUid(NetworkTemplate template, int uid) { try { - NetworkStatsHistory history = mCollection.getHistory(template, uid, + NetworkStatsHistory history = mCollection.getHistory(template, null, uid, NetworkStats.SET_ALL, NetworkStats.TAG_NONE, NetworkStatsHistory.FIELD_ALL, Long.MIN_VALUE /* start */, Long.MAX_VALUE /* end */, diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index 80309e19eb42..4bee55ef8b22 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -20,6 +20,7 @@ import static android.net.NetworkStats.TAG_NONE; import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.text.format.DateUtils.YEAR_IN_MILLIS; + import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.Nullable; @@ -28,6 +29,7 @@ import android.net.NetworkStats.NonMonotonicObserver; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TrafficStats; +import android.os.Binder; import android.os.DropBoxManager; import android.service.NetworkStatsRecorderProto; import android.util.Log; @@ -38,6 +40,9 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.net.VpnInfo; import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; + +import libcore.io.IoUtils; + import com.google.android.collect.Sets; import java.io.ByteArrayOutputStream; @@ -52,8 +57,6 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Map; -import libcore.io.IoUtils; - /** * Logic to record deltas between periodic {@link NetworkStats} snapshots into * {@link NetworkStatsHistory} that belong to {@link NetworkStatsCollection}. @@ -150,7 +153,7 @@ public class NetworkStatsRecorder { public NetworkStats.Entry getTotalSinceBootLocked(NetworkTemplate template) { return mSinceBoot.getSummary(template, Long.MIN_VALUE, Long.MAX_VALUE, - NetworkStatsAccess.Level.DEVICE).getTotal(null); + NetworkStatsAccess.Level.DEVICE, Binder.getCallingUid()).getTotal(null); } public NetworkStatsCollection getSinceBoot() { diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 8209adeb8947..4bd927d4970e 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -26,15 +26,21 @@ import static android.content.Intent.EXTRA_UID; import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; import static android.net.ConnectivityManager.isNetworkTypeMobile; import static android.net.NetworkStats.IFACE_ALL; +import static android.net.NetworkStats.METERED_ALL; +import static android.net.NetworkStats.ROAMING_ALL; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_FOREGROUND; +import static android.net.NetworkStats.STATS_PER_IFACE; +import static android.net.NetworkStats.STATS_PER_UID; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; +import static android.net.NetworkStatsHistory.FIELD_ALL; import static android.net.NetworkTemplate.buildTemplateMobileWildcard; import static android.net.NetworkTemplate.buildTemplateWifiWildcard; import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; +import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED; import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION; import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE; import static android.provider.Settings.Global.NETSTATS_DEV_PERSIST_BYTES; @@ -63,6 +69,7 @@ import static com.android.server.NetworkManagementSocketTagger.setKernelCounterS import android.app.AlarmManager; import android.app.PendingIntent; +import android.app.usage.NetworkStatsManager; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; @@ -102,6 +109,8 @@ import android.provider.Settings; import android.provider.Settings.Global; import android.service.NetworkInterfaceProto; import android.service.NetworkStatsServiceDumpProto; +import android.telephony.SubscriptionManager; +import android.telephony.SubscriptionPlan; import android.telephony.TelephonyManager; import android.text.format.DateUtils; import android.util.ArrayMap; @@ -137,8 +146,8 @@ import java.util.List; * other system services. */ public class NetworkStatsService extends INetworkStatsService.Stub { - private static final String TAG = "NetworkStats"; - private static final boolean LOGV = false; + static final String TAG = "NetworkStats"; + static final boolean LOGV = false; private static final int MSG_PERFORM_POLL = 1; private static final int MSG_UPDATE_IFACES = 2; @@ -192,6 +201,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public long getPollInterval(); public long getTimeCacheMaxAge(); public boolean getSampleEnabled(); + public boolean getAugmentEnabled(); public static class Config { public final long bucketDuration; @@ -464,18 +474,20 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public INetworkStatsSession openSession() { - return createSession(null, /* poll on create */ false); + // NOTE: if callers want to get non-augmented data, they should go + // through the public API + return openSessionInternal(NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, null); } @Override - public INetworkStatsSession openSessionForUsageStats(final String callingPackage) { - return createSession(callingPackage, /* poll on create */ true); + public INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage) { + return openSessionInternal(flags, callingPackage); } - private INetworkStatsSession createSession(final String callingPackage, boolean pollOnCreate) { + private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) { assertBandwidthControlEnabled(); - if (pollOnCreate) { + if ((flags & NetworkStatsManager.FLAG_POLL_ON_OPEN) != 0) { final long ident = Binder.clearCallingIdentity(); try { performPoll(FLAG_PERSIST_ALL); @@ -488,9 +500,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // for its lifetime; when caller closes only weak references remain. return new INetworkStatsSession.Stub() { + private final int mCallingUid = Binder.getCallingUid(); + private final String mCallingPackage = callingPackage; + private final @NetworkStatsAccess.Level int mAccessLevel = checkAccessLevel( + callingPackage); + private NetworkStatsCollection mUidComplete; private NetworkStatsCollection mUidTagComplete; - private String mCallingPackage = callingPackage; private NetworkStatsCollection getUidComplete() { synchronized (mStatsLock) { @@ -512,55 +528,38 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public int[] getRelevantUids() { - return getUidComplete().getRelevantUids(checkAccessLevel(mCallingPackage)); + return getUidComplete().getRelevantUids(mAccessLevel); } @Override - public NetworkStats getDeviceSummaryForNetwork(NetworkTemplate template, long start, - long end) { - @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage); - if (accessLevel < NetworkStatsAccess.Level.DEVICESUMMARY) { - throw new SecurityException("Calling package " + mCallingPackage - + " cannot access device summary network stats"); - } - NetworkStats result = new NetworkStats(end - start, 1); - final long ident = Binder.clearCallingIdentity(); - try { - // Using access level higher than the one we checked for above. - // Reason is that we are combining usage data in a way that is not PII - // anymore. - result.combineAllValues( - internalGetSummaryForNetwork(template, start, end, - NetworkStatsAccess.Level.DEVICE)); - } finally { - Binder.restoreCallingIdentity(ident); - } - return result; + public NetworkStats getDeviceSummaryForNetwork( + NetworkTemplate template, long start, long end) { + return internalGetSummaryForNetwork(template, flags, start, end, mAccessLevel, + mCallingUid); } @Override public NetworkStats getSummaryForNetwork( NetworkTemplate template, long start, long end) { - @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage); - return internalGetSummaryForNetwork(template, start, end, accessLevel); + return internalGetSummaryForNetwork(template, flags, start, end, mAccessLevel, + mCallingUid); } @Override public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) { - @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage); - return internalGetHistoryForNetwork(template, fields, accessLevel); + return internalGetHistoryForNetwork(template, flags, fields, mAccessLevel, + mCallingUid); } @Override public NetworkStats getSummaryForAllUid( NetworkTemplate template, long start, long end, boolean includeTags) { try { - @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage); - final NetworkStats stats = - getUidComplete().getSummary(template, start, end, accessLevel); + final NetworkStats stats = getUidComplete() + .getSummary(template, start, end, mAccessLevel, mCallingUid); if (includeTags) { final NetworkStats tagStats = getUidTagComplete() - .getSummary(template, start, end, accessLevel); + .getSummary(template, start, end, mAccessLevel, mCallingUid); stats.combineAllValues(tagStats); } return stats; @@ -574,13 +573,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public NetworkStatsHistory getHistoryForUid( NetworkTemplate template, int uid, int set, int tag, int fields) { - @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage); + // NOTE: We don't augment UID-level statistics if (tag == TAG_NONE) { - return getUidComplete().getHistory(template, uid, set, tag, fields, - accessLevel); + return getUidComplete().getHistory(template, null, uid, set, tag, fields, + Long.MIN_VALUE, Long.MAX_VALUE, mAccessLevel, mCallingUid); } else { - return getUidTagComplete().getHistory(template, uid, set, tag, fields, - accessLevel); + return getUidTagComplete().getHistory(template, null, uid, set, tag, fields, + Long.MIN_VALUE, Long.MAX_VALUE, mAccessLevel, mCallingUid); } } @@ -588,13 +587,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public NetworkStatsHistory getHistoryIntervalForUid( NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end) { - @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage); + // NOTE: We don't augment UID-level statistics if (tag == TAG_NONE) { - return getUidComplete().getHistory(template, uid, set, tag, fields, start, end, - accessLevel); + return getUidComplete().getHistory(template, null, uid, set, tag, fields, + start, end, mAccessLevel, mCallingUid); } else if (uid == Binder.getCallingUid()) { - return getUidTagComplete().getHistory(template, uid, set, tag, fields, - start, end, accessLevel); + return getUidTagComplete().getHistory(template, null, uid, set, tag, fields, + start, end, mAccessLevel, mCallingUid); } else { throw new SecurityException("Calling package " + mCallingPackage + " cannot access tag information from a different uid"); @@ -615,36 +614,84 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } /** + * Find the most relevant {@link SubscriptionPlan} for the given + * {@link NetworkTemplate} and flags. This is typically used to augment + * local measurement results to match a known anchor from the carrier. + */ + private SubscriptionPlan resolveSubscriptionPlan(NetworkTemplate template, int flags) { + SubscriptionPlan plan = null; + if ((flags & NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN) != 0 + && (template.getMatchRule() == NetworkTemplate.MATCH_MOBILE_ALL) + && mSettings.getAugmentEnabled()) { + Slog.d(TAG, "Resolving plan for " + template); + final long token = Binder.clearCallingIdentity(); + try { + final SubscriptionManager sm = mContext.getSystemService(SubscriptionManager.class); + final TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); + for (int subId : sm.getActiveSubscriptionIdList()) { + if (template.matchesSubscriberId(tm.getSubscriberId(subId))) { + Slog.d(TAG, "Found active matching subId " + subId); + final List<SubscriptionPlan> plans = sm.getSubscriptionPlans(subId); + if (!plans.isEmpty()) { + plan = plans.get(0); + } + } + } + } finally { + Binder.restoreCallingIdentity(token); + } + Slog.d(TAG, "Resolved to plan " + plan); + } + return plan; + } + + /** * Return network summary, splicing between DEV and XT stats when * appropriate. */ - private NetworkStats internalGetSummaryForNetwork( - NetworkTemplate template, long start, long end, - @NetworkStatsAccess.Level int accessLevel) { + private NetworkStats internalGetSummaryForNetwork(NetworkTemplate template, int flags, + long start, long end, @NetworkStatsAccess.Level int accessLevel, int callingUid) { // We've been using pure XT stats long enough that we no longer need to // splice DEV and XT together. - return mXtStatsCached.getSummary(template, start, end, accessLevel); + final NetworkStatsHistory history = internalGetHistoryForNetwork(template, flags, FIELD_ALL, + accessLevel, callingUid); + + final long now = System.currentTimeMillis(); + final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null); + + final NetworkStats stats = new NetworkStats(end - start, 1); + stats.addValues(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, + ROAMING_ALL, entry.rxBytes, entry.rxPackets, entry.txBytes, entry.txPackets, + entry.operations)); + return stats; } /** * Return network history, splicing between DEV and XT stats when * appropriate. */ - private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate template, int fields, - @NetworkStatsAccess.Level int accessLevel) { + private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate template, + int flags, int fields, @NetworkStatsAccess.Level int accessLevel, int callingUid) { // We've been using pure XT stats long enough that we no longer need to // splice DEV and XT together. - return mXtStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields, accessLevel); + return mXtStatsCached.getHistory(template, resolveSubscriptionPlan(template, flags), + UID_ALL, SET_ALL, TAG_NONE, fields, Long.MIN_VALUE, Long.MAX_VALUE, + accessLevel, callingUid); } @Override public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) { - // Special case - since this is for internal use only, don't worry about a full access level - // check and just require the signature/privileged permission. + // Special case - since this is for internal use only, don't worry about + // a full access level check and just require the signature/privileged + // permission. mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); assertBandwidthControlEnabled(); - return internalGetSummaryForNetwork(template, start, end, NetworkStatsAccess.Level.DEVICE) - .getTotalBytes(); + + // NOTE: if callers want to get non-augmented data, they should go + // through the public API + return internalGetSummaryForNetwork(template, + NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, start, end, + NetworkStatsAccess.Level.DEVICE, Binder.getCallingUid()).getTotalBytes(); } @Override @@ -1041,6 +1088,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats xtSnapshot = getNetworkStatsXt(); final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev(); + // Tethering snapshot for dev and xt stats. Counts per-interface data from tethering stats + // providers that isn't already counted by dev and XT stats. + final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_IFACE); + xtSnapshot.combineAllValues(tetherSnapshot); + devSnapshot.combineAllValues(tetherSnapshot); // For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic // can't be reattributed to responsible apps. @@ -1371,14 +1423,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL); // fold tethering stats and operations into uid snapshot - final NetworkStats tetherSnapshot = getNetworkStatsTethering(); + final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID); uidSnapshot.combineAllValues(tetherSnapshot); final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService( Context.TELEPHONY_SERVICE); // fold video calling data usage stats into uid snapshot - final NetworkStats vtStats = telephonyManager.getVtDataUsage(true); + final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID); if (vtStats != null) { uidSnapshot.combineAllValues(vtStats); } @@ -1397,7 +1449,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { Context.TELEPHONY_SERVICE); // Merge video calling data usage into XT - final NetworkStats vtSnapshot = telephonyManager.getVtDataUsage(false); + final NetworkStats vtSnapshot = telephonyManager.getVtDataUsage(STATS_PER_IFACE); if (vtSnapshot != null) { xtSnapshot.combineAllValues(vtSnapshot); } @@ -1409,9 +1461,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * Return snapshot of current tethering statistics. Will return empty * {@link NetworkStats} if any problems are encountered. */ - private NetworkStats getNetworkStatsTethering() throws RemoteException { + private NetworkStats getNetworkStatsTethering(int how) throws RemoteException { try { - return mNetworkManager.getNetworkStatsTethering(); + return mNetworkManager.getNetworkStatsTethering(how); } catch (IllegalStateException e) { Log.wtf(TAG, "problem reading network stats", e); return new NetworkStats(0L, 10); @@ -1523,6 +1575,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return getGlobalBoolean(NETSTATS_SAMPLE_ENABLED, true); } @Override + public boolean getAugmentEnabled() { + return getGlobalBoolean(NETSTATS_AUGMENT_ENABLED, true); + } + @Override public Config getDevConfig() { return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS), getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS), diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index 80878131ae44..34f1bfaf996f 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -212,12 +212,25 @@ abstract public class ManagedServices { } } - protected void onSettingRestored(String element, String value, int userId) { + protected void onSettingRestored(String element, String value, int backupSdkInt, int userId) { if (!mUseXml) { Slog.d(TAG, "Restored managed service setting: " + element); if (mConfig.secureSettingName.equals(element) || (mConfig.secondarySettingName != null && mConfig.secondarySettingName.equals(element))) { + if (backupSdkInt < Build.VERSION_CODES.O) { + // automatic system grants were added in O, so append the approved apps + // rather than wiping out the setting + String currentSetting = + getApproved(userId, mConfig.secureSettingName.equals(element)); + if (!TextUtils.isEmpty(currentSetting)) { + if (!TextUtils.isEmpty(value)) { + value = value + ENABLED_SERVICES_SEPARATOR + currentSetting; + } else { + value = currentSetting; + } + } + } Settings.Secure.putStringForUser( mContext.getContentResolver(), element, value, userId); loadAllowedComponentsFromSettings(); @@ -370,6 +383,13 @@ abstract public class ManagedServices { } } + protected String getApproved(int userId, boolean primary) { + final ArrayMap<Boolean, ArraySet<String>> allowedByType = + mApproved.getOrDefault(userId, new ArrayMap<>()); + ArraySet<String> approved = allowedByType.getOrDefault(primary, new ArraySet<>()); + return String.join(ENABLED_SERVICES_SEPARATOR, approved); + } + protected List<ComponentName> getAllowedComponents(int userId) { final List<ComponentName> allowedComponents = new ArrayList<>(); final ArrayMap<Boolean, ArraySet<String>> allowedByType = @@ -435,6 +455,11 @@ abstract public class ManagedServices { } } + public void onUserRemoved(int user) { + mApproved.remove(user); + rebindServices(true); + } + public void onUserSwitched(int user) { if (DEBUG) Slog.d(TAG, "onUserSwitched u=" + user); if (Arrays.equals(mLastSeenProfileIds, mUserProfiles.getCurrentProfileIds())) { @@ -857,6 +882,7 @@ abstract public class ManagedServices { @Override public void onServiceDisconnected(ComponentName name) { + mServicesBinding.remove(servicesBindingTag); Slog.v(TAG, getCaption() + " connection lost: " + name); } }; @@ -869,6 +895,7 @@ abstract public class ManagedServices { return; } } catch (SecurityException ex) { + mServicesBinding.remove(servicesBindingTag); Slog.e(TAG, "Unable to bind " + getCaption() + " service: " + intent, ex); } } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 186243c31c97..9a76294cdd9e 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -157,6 +157,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.internal.os.BackgroundThread; import com.android.internal.statusbar.NotificationVisibility; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; @@ -803,6 +804,7 @@ public class NotificationManagerService extends SystemService { public void onReceive(Context context, Intent intent) { if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) { mZenModeHelper.updateDefaultZenRules(); + mRankingHelper.onLocaleChanged(context, ActivityManager.getCurrentUser()); } } }; @@ -816,8 +818,10 @@ public class NotificationManagerService extends SystemService { String newValue = intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE); int restoredFromSdkInt = intent.getIntExtra( Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT, 0); - mListeners.onSettingRestored(element, newValue, getSendingUserId()); - mConditionProviders.onSettingRestored(element, newValue, getSendingUserId()); + mListeners.onSettingRestored( + element, newValue, restoredFromSdkInt, getSendingUserId()); + mConditionProviders.onSettingRestored( + element, newValue, restoredFromSdkInt, getSendingUserId()); } catch (Exception e) { Slog.wtf(TAG, "Cannot restore managed services from settings", e); } @@ -981,12 +985,17 @@ public class NotificationManagerService extends SystemService { final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL); if (userId != USER_NULL) { mUserProfiles.updateCache(context); - readDefaultApprovedServices(userId); + if (!mUserProfiles.isManagedProfile(userId)) { + readDefaultApprovedServices(userId); + } } } else if (action.equals(Intent.ACTION_USER_REMOVED)) { final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL); mZenModeHelper.onUserRemoved(user); mRankingHelper.onUserRemoved(user); + mListeners.onUserRemoved(user); + mConditionProviders.onUserRemoved(user); + mAssistants.onUserRemoved(user); savePolicyFile(); } else if (action.equals(Intent.ACTION_USER_UNLOCKED)) { final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL); @@ -3101,7 +3110,7 @@ public class NotificationManagerService extends SystemService { } } if (summaryRecord != null && checkDisqualifyingFeatures(userId, MY_UID, - summaryRecord.sbn.getId(), summaryRecord.sbn.getTag(), summaryRecord)) { + summaryRecord.sbn.getId(), summaryRecord.sbn.getTag(), summaryRecord, true)) { mHandler.post(new EnqueueNotificationRunnable(userId, summaryRecord)); } } @@ -3446,7 +3455,8 @@ public class NotificationManagerService extends SystemService { user, null, System.currentTimeMillis()); final NotificationRecord r = new NotificationRecord(getContext(), n, channel); - if (!checkDisqualifyingFeatures(userId, notificationUid, id, tag, r)) { + if (!checkDisqualifyingFeatures(userId, notificationUid, id, tag, r, + r.sbn.getOverrideGroupKey() != null)) { return; } @@ -3501,7 +3511,7 @@ public class NotificationManagerService extends SystemService { * Has side effects. */ private boolean checkDisqualifyingFeatures(int userId, int callingUid, int id, String tag, - NotificationRecord r) { + NotificationRecord r, boolean isAutogroup) { final String pkg = r.sbn.getPackageName(); final boolean isSystemNotification = isUidSystemOrPhone(callingUid) || ("android".equals(pkg)); @@ -3522,7 +3532,8 @@ public class NotificationManagerService extends SystemService { // rate limit updates that aren't completed progress notifications if (mNotificationsByKey.get(r.sbn.getKey()) != null - && !r.getNotification().hasCompletedProgress()) { + && !r.getNotification().hasCompletedProgress() + && !isAutogroup) { final float appEnqueueRate = mUsageStats.getAppEnqueueRate(pkg); if (appEnqueueRate > mMaxPackageEnqueueRate) { @@ -3530,7 +3541,7 @@ public class NotificationManagerService extends SystemService { final long now = SystemClock.elapsedRealtime(); if ((now - mLastOverRateLogTime) > MIN_PACKAGE_OVERRATE_LOG_INTERVAL) { Slog.e(TAG, "Package enqueue rate is " + appEnqueueRate - + ". Shedding events. package=" + pkg); + + ". Shedding " + r.sbn.getKey() + ". package=" + pkg); mLastOverRateLogTime = now; } return false; @@ -5562,13 +5573,10 @@ public class NotificationManagerService extends SystemService { continue; } - mHandler.post(new Runnable() { - @Override - public void run() { - if (hasCompanionDevice(serviceInfo)) { - notifyNotificationChannelChanged( - serviceInfo, pkg, user, channel, modificationType); - } + BackgroundThread.getHandler().post(() -> { + if (hasCompanionDevice(serviceInfo)) { + notifyNotificationChannelChanged( + serviceInfo, pkg, user, channel, modificationType); } }); } @@ -5585,13 +5593,10 @@ public class NotificationManagerService extends SystemService { continue; } - mHandler.post(new Runnable() { - @Override - public void run() { - if (hasCompanionDevice(serviceInfo)) { - notifyNotificationChannelGroupChanged( - serviceInfo, pkg, user, group, modificationType); - } + BackgroundThread.getHandler().post(() -> { + if (hasCompanionDevice(serviceInfo)) { + notifyNotificationChannelGroupChanged( + serviceInfo, pkg, user, group, modificationType); } }); } diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java index 9622a24a2d4d..3386fe832e0f 100644 --- a/services/core/java/com/android/server/notification/RankingHelper.java +++ b/services/core/java/com/android/server/notification/RankingHelper.java @@ -1073,6 +1073,22 @@ public class RankingHelper implements RankingConfig { } } + protected void onLocaleChanged(Context context, int userId) { + synchronized (mRecords) { + int N = mRecords.size(); + for (int i = 0; i < N; i++) { + Record record = mRecords.valueAt(i); + if (UserHandle.getUserId(record.uid) == userId) { + if (record.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) { + record.channels.get(NotificationChannel.DEFAULT_CHANNEL_ID).setName( + context.getResources().getString( + R.string.default_notification_channel_label)); + } + } + } + } + } + public void onPackagesChanged(boolean removingPackage, int changeUserId, String[] pkgList, int[] uidList) { if (pkgList == null || pkgList.length == 0) { diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java index 04d91f882d04..807c343d0d10 100644 --- a/services/core/java/com/android/server/om/IdmapManager.java +++ b/services/core/java/com/android/server/om/IdmapManager.java @@ -92,26 +92,10 @@ class IdmapManager { return new File(getIdmapPath(overlayPackage.applicationInfo.getBaseCodePath())).isFile(); } - boolean isDangerous(@NonNull final PackageInfo overlayPackage, final int userId) { - // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible - return isDangerous(getIdmapPath(overlayPackage.applicationInfo.getBaseCodePath())); - } - private String getIdmapPath(@NonNull final String baseCodePath) { final StringBuilder sb = new StringBuilder("/data/resource-cache/"); sb.append(baseCodePath.substring(1).replace('/', '@')); sb.append("@idmap"); return sb.toString(); } - - private boolean isDangerous(@NonNull final String idmapPath) { - try (DataInputStream dis = new DataInputStream(new FileInputStream(idmapPath))) { - final int magic = dis.readInt(); - final int version = dis.readInt(); - final int dangerous = dis.readInt(); - return dangerous != 0; - } catch (IOException e) { - return true; - } - } } diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java index db6e9749535b..c3957f432f4c 100644 --- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java @@ -169,8 +169,9 @@ final class OverlayManagerServiceImpl { } final PackageInfo targetPackage = mPackageManager.getPackageInfo(packageName, userId); - updateAllOverlaysForTarget(packageName, userId, targetPackage); - mListener.onOverlaysChanged(packageName, userId); + if (updateAllOverlaysForTarget(packageName, userId, targetPackage)) { + mListener.onOverlaysChanged(packageName, userId); + } } void onTargetPackageChanged(@NonNull final String packageName, final int userId) { @@ -210,7 +211,9 @@ final class OverlayManagerServiceImpl { Slog.d(TAG, "onTargetPackageRemoved packageName=" + packageName + " userId=" + userId); } - updateAllOverlaysForTarget(packageName, userId, null); + if (updateAllOverlaysForTarget(packageName, userId, null)) { + mListener.onOverlaysChanged(packageName, userId); + } } /** diff --git a/services/core/java/com/android/server/pm/BasePermission.java b/services/core/java/com/android/server/pm/BasePermission.java index 21000388e746..30fda1e5665e 100644 --- a/services/core/java/com/android/server/pm/BasePermission.java +++ b/services/core/java/com/android/server/pm/BasePermission.java @@ -96,7 +96,7 @@ final class BasePermission { } public boolean isInstant() { - return (protectionLevel & PermissionInfo.PROTECTION_FLAG_EPHEMERAL) != 0; + return (protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0; } public boolean isRuntimeOnly() { diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java index b217677479cd..1082eae7df84 100644 --- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java @@ -624,14 +624,25 @@ final class DefaultPermissionGrantPolicy { grantRuntimePermissionsLPw(musicPackage, STORAGE_PERMISSIONS, userId); } + // Home + Intent homeIntent = new Intent(Intent.ACTION_MAIN); + homeIntent.addCategory(Intent.CATEGORY_HOME); + homeIntent.addCategory(Intent.CATEGORY_LAUNCHER_APP); + PackageParser.Package homePackage = getDefaultSystemHandlerActivityPackageLPr( + homeIntent, userId); + if (homePackage != null + && doesPackageSupportRuntimePermissions(homePackage)) { + grantRuntimePermissionsLPw(homePackage, LOCATION_PERMISSIONS, false, userId); + } + // Watches if (mService.hasSystemFeature(PackageManager.FEATURE_WATCH, 0)) { // Home application on watches - Intent homeIntent = new Intent(Intent.ACTION_MAIN); - homeIntent.addCategory(Intent.CATEGORY_HOME_MAIN); + Intent wearHomeIntent = new Intent(Intent.ACTION_MAIN); + wearHomeIntent.addCategory(Intent.CATEGORY_HOME_MAIN); PackageParser.Package wearHomePackage = getDefaultSystemHandlerActivityPackageLPr( - homeIntent, userId); + wearHomeIntent, userId); if (wearHomePackage != null && doesPackageSupportRuntimePermissions(wearHomePackage)) { diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java index 211a1c9f3edf..e1e5b3555335 100644 --- a/services/core/java/com/android/server/pm/InstantAppRegistry.java +++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java @@ -293,14 +293,35 @@ class InstantAppRegistry { if (currentCookieFile == null) { continue; } - File expectedCookeFile = computeInstantCookieFile(pkg, userId); - if (!currentCookieFile.equals(expectedCookeFile)) { - Slog.i(LOG_TAG, "Signature for package " + pkg.packageName - + " changed - dropping cookie"); - // Make sure a pending write for the old signed app is cancelled - mCookiePersistence.cancelPendingPersistLPw(pkg, userId); - currentCookieFile.delete(); + + // Before we used only the first signature to compute the SHA 256 but some + // apps could be singed by multiple certs and the cert order is undefined. + // We prefer the modern computation procedure where all certs are taken + // into account but also allow the value from the old computation to avoid + // data loss. + final String[] signaturesSha256Digests = PackageUtils.computeSignaturesSha256Digests( + pkg.mSignatures); + final String signaturesSha256Digest = PackageUtils.computeSignaturesSha256Digest( + signaturesSha256Digests); + + // We prefer a match based on all signatures + if (currentCookieFile.equals(computeInstantCookieFile(pkg.packageName, + signaturesSha256Digest, userId))) { + return; } + + // For backwards compatibility we accept match based on first signature + if (pkg.mSignatures.length > 1 && currentCookieFile.equals(computeInstantCookieFile( + pkg.packageName, signaturesSha256Digests[0], userId))) { + return; + } + + // Sorry, you are out of luck - different signatures - nuke data + Slog.i(LOG_TAG, "Signature for package " + pkg.packageName + + " changed - dropping cookie"); + // Make sure a pending write for the old signed app is cancelled + mCookiePersistence.cancelPendingPersistLPw(pkg, userId); + currentCookieFile.delete(); } } @@ -504,6 +525,11 @@ class InstantAppRegistry { } } + boolean hasInstantApplicationMetadataLPr(String packageName, int userId) { + return hasUninstalledInstantAppStateLPr(packageName, userId) + || hasInstantAppMetadataLPr(packageName, userId); + } + public void deleteInstantApplicationMetadataLPw(@NonNull String packageName, @UserIdInt int userId) { removeUninstalledInstantAppStateLPw((UninstalledInstantAppState state) -> @@ -547,6 +573,33 @@ class InstantAppRegistry { } } + private boolean hasUninstalledInstantAppStateLPr(String packageName, @UserIdInt int userId) { + if (mUninstalledInstantApps == null) { + return false; + } + final List<UninstalledInstantAppState> uninstalledAppStates = + mUninstalledInstantApps.get(userId); + if (uninstalledAppStates == null) { + return false; + } + final int appCount = uninstalledAppStates.size(); + for (int i = 0; i < appCount; i++) { + final UninstalledInstantAppState uninstalledAppState = uninstalledAppStates.get(i); + if (packageName.equals(uninstalledAppState.mInstantAppInfo.getPackageName())) { + return true; + } + } + return false; + } + + private boolean hasInstantAppMetadataLPr(String packageName, @UserIdInt int userId) { + final File instantAppDir = getInstantApplicationDir(packageName, userId); + return new File(instantAppDir, INSTANT_APP_METADATA_FILE).exists() + || new File(instantAppDir, INSTANT_APP_ICON_FILE).exists() + || new File(instantAppDir, INSTANT_APP_ANDROID_ID_FILE).exists() + || peekInstantCookieFile(packageName, userId) != null; + } + void pruneInstantApps() { final long maxInstalledCacheDuration = Settings.Global.getLong( mService.mContext.getContentResolver(), @@ -936,11 +989,11 @@ class InstantAppRegistry { } } - private static @NonNull File computeInstantCookieFile(@NonNull PackageParser.Package pkg, - @UserIdInt int userId) { - File appDir = getInstantApplicationDir(pkg.packageName, userId); - String cookieFile = INSTANT_APP_COOKIE_FILE_PREFIX + PackageUtils.computeSha256Digest( - pkg.mSignatures[0].toByteArray()) + INSTANT_APP_COOKIE_FILE_SIFFIX; + private static @NonNull File computeInstantCookieFile(@NonNull String packageName, + @NonNull String sha256Digest, @UserIdInt int userId) { + final File appDir = getInstantApplicationDir(packageName, userId); + final String cookieFile = INSTANT_APP_COOKIE_FILE_PREFIX + + sha256Digest + INSTANT_APP_COOKIE_FILE_SIFFIX; return new File(appDir, cookieFile); } @@ -1071,7 +1124,7 @@ class InstantAppRegistry { } private static @NonNull File getInstantApplicationDir(String packageName, int userId) { - return new File (getInstantApplicationsDir(userId), packageName); + return new File(getInstantApplicationsDir(userId), packageName); } private static void deleteDir(@NonNull File dir) { @@ -1115,9 +1168,20 @@ class InstantAppRegistry { public void schedulePersistLPw(@UserIdInt int userId, @NonNull PackageParser.Package pkg, @NonNull byte[] cookie) { - File cookieFile = computeInstantCookieFile(pkg, userId); + // Before we used only the first signature to compute the SHA 256 but some + // apps could be singed by multiple certs and the cert order is undefined. + // We prefer the modern computation procedure where all certs are taken + // into account and delete the file derived via the legacy hash computation. + File newCookieFile = computeInstantCookieFile(pkg.packageName, + PackageUtils.computeSignaturesSha256Digest(pkg.mSignatures), userId); + if (pkg.mSignatures.length > 0) { + File oldCookieFile = peekInstantCookieFile(pkg.packageName, userId); + if (oldCookieFile != null && !newCookieFile.equals(oldCookieFile)) { + oldCookieFile.delete(); + } + } cancelPendingPersistLPw(pkg, userId); - addPendingPersistCookieLPw(userId, pkg, cookie, cookieFile); + addPendingPersistCookieLPw(userId, pkg, cookie, newCookieFile); sendMessageDelayed(obtainMessage(userId, pkg), PERSIST_COOKIE_DELAY_MILLIS); } diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java index f50d0d7564a1..5f54c67a35a1 100644 --- a/services/core/java/com/android/server/pm/InstantAppResolver.java +++ b/services/core/java/com/android/server/pm/InstantAppResolver.java @@ -122,7 +122,7 @@ public abstract class InstantAppResolver { } } // Only log successful instant application resolution - if (resolutionStatus == RESOLUTION_SUCCESS) { + if (requestObj.resolveForStart && resolutionStatus == RESOLUTION_SUCCESS) { logMetrics(ACTION_INSTANT_APP_RESOLUTION_PHASE_ONE, startTime, token, resolutionStatus); } diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 0ecb4e1e80bd..69db49b57bc6 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -41,6 +41,7 @@ import static com.android.server.pm.PackageInstallerService.prepareStageDir; import android.Manifest; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.Intent; @@ -312,9 +313,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { return false; } - final boolean isPermissionGranted = + final boolean isInstallPermissionGranted = (mPm.checkUidPermission(android.Manifest.permission.INSTALL_PACKAGES, mInstallerUid) == PackageManager.PERMISSION_GRANTED); + final boolean isSelfUpdatePermissionGranted = + (mPm.checkUidPermission(android.Manifest.permission.INSTALL_SELF_UPDATES, + mInstallerUid) == PackageManager.PERMISSION_GRANTED); + final boolean isPermissionGranted = isInstallPermissionGranted + || (isSelfUpdatePermissionGranted + && mPm.getPackageUid(mPackageName, 0, userId) == mInstallerUid); final boolean isInstallerRoot = (mInstallerUid == Process.ROOT_UID); final boolean forcePermissionPrompt = (params.installFlags & PackageManager.INSTALL_FORCE_PERMISSION_PROMPT) != 0; @@ -731,7 +738,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { * * @param pkgInfo The package info for {@link #params}.packagename */ - private void sealAndValidateLocked(PackageInfo pkgInfo) + private void sealAndValidateLocked(@Nullable PackageInfo pkgInfo) throws PackageManagerException { assertNoWriteFileTransfersOpenLocked(); @@ -923,7 +930,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { * Note that upgrade compatibility is still performed by * {@link PackageManagerService}. */ - private void validateInstallLocked(PackageInfo pkgInfo) throws PackageManagerException { + private void validateInstallLocked(@Nullable PackageInfo pkgInfo) + throws PackageManagerException { mPackageName = null; mVersionCode = -1; mSignatures = null; @@ -1004,6 +1012,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } if (removeSplitList.size() > 0) { + if (pkgInfo == null) { + throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, + "Missing existing base package for " + mPackageName); + } + // validate split names marked for removal for (String splitName : removeSplitList) { if (!ArrayUtils.contains(pkgInfo.splitNames, splitName)) { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 5dcd5f3e547e..1db99a54c6a4 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -85,6 +85,8 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.pm.PackageParser.PARSE_IS_PRIVILEGED; import static android.content.pm.PackageParser.isApkFile; import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; +import static android.os.storage.StorageManager.FLAG_STORAGE_CE; +import static android.os.storage.StorageManager.FLAG_STORAGE_DE; import static android.system.OsConstants.O_CREAT; import static android.system.OsConstants.O_RDWR; @@ -227,7 +229,7 @@ import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Base64; -import android.util.BootTimingsTraceLog; +import android.util.TimingsTraceLog; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.ExceptionUtils; @@ -456,6 +458,8 @@ public class PackageManagerService extends IPackageManager.Stub private static final String STATIC_SHARED_LIB_DELIMITER = "_"; /** Extension of the compressed packages */ private final static String COMPRESSED_EXTENSION = ".gz"; + /** Suffix of stub packages on the system partition */ + private final static String STUB_SUFFIX = "-Stub"; private static final int[] EMPTY_INT_ARRAY = new int[0]; @@ -1926,8 +1930,12 @@ public class PackageManagerService extends IPackageManager.Stub final boolean update = res.removedInfo != null && res.removedInfo.removedPackage != null; - final String origInstallerPackageName = res.removedInfo != null - ? res.removedInfo.installerPackageName : null; + final String installerPackageName = + res.installerPackageName != null + ? res.installerPackageName + : res.removedInfo != null + ? res.removedInfo.installerPackageName + : null; // If this is the first time we have child packages for a disabled privileged // app that had no children, we grant requested runtime permissions to the new @@ -1992,10 +2000,10 @@ public class PackageManagerService extends IPackageManager.Stub sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras, 0 /*flags*/, null /*targetPackage*/, null /*finishedReceiver*/, updateUsers); - if (origInstallerPackageName != null) { + if (installerPackageName != null) { sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras, 0 /*flags*/, - origInstallerPackageName, null /*finishedReceiver*/, updateUsers); + installerPackageName, null /*finishedReceiver*/, updateUsers); } // Send replaced for users that don't see the package for the first time @@ -2004,10 +2012,10 @@ public class PackageManagerService extends IPackageManager.Stub packageName, extras, 0 /*flags*/, null /*targetPackage*/, null /*finishedReceiver*/, updateUsers); - if (origInstallerPackageName != null) { + if (installerPackageName != null) { sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras, 0 /*flags*/, - origInstallerPackageName, null /*finishedReceiver*/, updateUsers); + installerPackageName, null /*finishedReceiver*/, updateUsers); } sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null /*package*/, null /*extras*/, 0 /*flags*/, @@ -2940,7 +2948,7 @@ public class PackageManagerService extends IPackageManager.Stub UserHandle.USER_SYSTEM, storageFlags, true /* migrateAppData */, true /* onlyCoreApps */); mPrepareAppDataFuture = SystemServerInitThreadPool.get().submit(() -> { - BootTimingsTraceLog traceLog = new BootTimingsTraceLog("SystemServerTimingAsync", + TimingsTraceLog traceLog = new TimingsTraceLog("SystemServerTimingAsync", Trace.TRACE_TAG_PACKAGE_MANAGER); traceLog.traceBegin("AppDataFixup"); try { @@ -3191,12 +3199,46 @@ public class PackageManagerService extends IPackageManager.Stub } private File[] getCompressedFiles(String codePath) { - return new File(codePath).listFiles(new FilenameFilter() { + final File stubCodePath = new File(codePath); + final String stubName = stubCodePath.getName(); + + // The layout of a compressed package on a given partition is as follows : + // + // Compressed artifacts: + // + // /partition/ModuleName/foo.gz + // /partation/ModuleName/bar.gz + // + // Stub artifact: + // + // /partition/ModuleName-Stub/ModuleName-Stub.apk + // + // In other words, stub is on the same partition as the compressed artifacts + // and in a directory that's suffixed with "-Stub". + int idx = stubName.lastIndexOf(STUB_SUFFIX); + if (idx < 0 || (stubName.length() != (idx + STUB_SUFFIX.length()))) { + return null; + } + + final File stubParentDir = stubCodePath.getParentFile(); + if (stubParentDir == null) { + Slog.e(TAG, "Unable to determine stub parent dir for codePath: " + codePath); + return null; + } + + final File compressedPath = new File(stubParentDir, stubName.substring(0, idx)); + final File[] files = compressedPath.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.toLowerCase().endsWith(COMPRESSED_EXTENSION); } }); + + if (DEBUG_COMPRESSION && files != null && files.length > 0) { + Slog.i(TAG, "getCompressedFiles[" + codePath + "]: " + Arrays.toString(files)); + } + + return files; } private boolean compressedFileExists(String codePath) { @@ -3213,7 +3255,7 @@ public class PackageManagerService extends IPackageManager.Stub final File[] compressedFiles = getCompressedFiles(pkg.codePath); if (compressedFiles == null || compressedFiles.length == 0) { if (DEBUG_COMPRESSION) { - Slog.i(TAG, "No files to decompress"); + Slog.i(TAG, "No files to decompress: " + pkg.baseCodePath); } return null; } @@ -3848,8 +3890,7 @@ public class PackageManagerService extends IPackageManager.Stub throw new SecurityException("Package " + packageName + " is currently frozen!"); } - if (!userKeyUnlocked && !(ps.pkg.applicationInfo.isDirectBootAware() - || ps.pkg.applicationInfo.isPartiallyDirectBootAware())) { + if (!userKeyUnlocked && !ps.pkg.applicationInfo.isEncryptionAware()) { throw new SecurityException("Package " + packageName + " is not encryption aware!"); } } @@ -4246,10 +4287,17 @@ public class PackageManagerService extends IPackageManager.Stub return null; } // If the caller is an app that targets pre 26 SDK drop protection flags. - final PermissionInfo permissionInfo = generatePermissionInfo(p, flags); + PermissionInfo permissionInfo = generatePermissionInfo(p, flags); if (permissionInfo != null) { - permissionInfo.protectionLevel = adjustPermissionProtectionFlagsLPr( + final int protectionLevel = adjustPermissionProtectionFlagsLPr( permissionInfo.protectionLevel, packageName, callingUid); + if (permissionInfo.protectionLevel != protectionLevel) { + // If we return different protection level, don't use the cached info + if (p.perm != null && p.perm.info == permissionInfo) { + permissionInfo = new PermissionInfo(permissionInfo); + } + permissionInfo.protectionLevel = protectionLevel; + } } return permissionInfo; } @@ -6730,7 +6778,7 @@ public class PackageManagerService extends IPackageManager.Stub Bundle verificationBundle, int userId) { final Message msg = mHandler.obtainMessage(INSTANT_APP_RESOLUTION_PHASE_TWO, new InstantAppRequest(responseObj, origIntent, resolvedType, - callingPackage, userId, verificationBundle)); + callingPackage, userId, verificationBundle, false /*resolveForStart*/)); mHandler.sendMessage(msg); } @@ -7314,7 +7362,8 @@ public class PackageManagerService extends IPackageManager.Stub } } if (addEphemeral) { - result = maybeAddInstantAppInstaller(result, intent, resolvedType, flags, userId); + result = maybeAddInstantAppInstaller( + result, intent, resolvedType, flags, userId, resolveForStart); } if (sortResult) { Collections.sort(result, mResolvePrioritySorter); @@ -7324,7 +7373,7 @@ public class PackageManagerService extends IPackageManager.Stub } private List<ResolveInfo> maybeAddInstantAppInstaller(List<ResolveInfo> result, Intent intent, - String resolvedType, int flags, int userId) { + String resolvedType, int flags, int userId, boolean resolveForStart) { // first, check to see if we've got an instant app already installed final boolean alreadyResolvedLocally = (flags & PackageManager.MATCH_INSTANT) != 0; ResolveInfo localInstantApp = null; @@ -7373,7 +7422,8 @@ public class PackageManagerService extends IPackageManager.Stub Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveEphemeral"); final InstantAppRequest requestObject = new InstantAppRequest( null /*responseObj*/, intent /*origIntent*/, resolvedType, - null /*callingPackage*/, userId, null /*verificationBundle*/); + null /*callingPackage*/, userId, null /*verificationBundle*/, + resolveForStart); auxiliaryResponse = InstantAppResolver.doInstantAppResolutionPhaseOne( mContext, mInstantAppResolverConnection, requestObject); @@ -9383,6 +9433,15 @@ public class PackageManagerService extends IPackageManager.Stub // throw an exception if we have an update to a system application, but, it's not more // recent than the package we've already scanned if (isUpdatedSystemPkg && !isUpdatedPkgBetter) { + // Set CPU Abis to application info. + if ((scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0) { + final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, updatedPkg); + derivePackageAbi(pkg, scanFile, cpuAbiOverride, false, mAppLib32InstallDir); + } else { + pkg.applicationInfo.primaryCpuAbi = updatedPkg.primaryCpuAbiString; + pkg.applicationInfo.secondaryCpuAbi = updatedPkg.secondaryCpuAbiString; + } + throw new PackageManagerException(Log.WARN, "Package " + ps.name + " at " + scanFile + " ignored: updated version " + ps.versionCode + " better than this " + pkg.mVersionCode); @@ -10335,16 +10394,19 @@ public class PackageManagerService extends IPackageManager.Stub ArraySet<String> usesLibraryFiles = null; if (pkg.usesLibraries != null) { usesLibraryFiles = addSharedLibrariesLPw(pkg.usesLibraries, - null, null, pkg.packageName, changingLib, true, null); + null, null, pkg.packageName, changingLib, true, + pkg.applicationInfo.targetSdkVersion, null); } if (pkg.usesStaticLibraries != null) { usesLibraryFiles = addSharedLibrariesLPw(pkg.usesStaticLibraries, pkg.usesStaticLibrariesVersions, pkg.usesStaticLibrariesCertDigests, - pkg.packageName, changingLib, true, usesLibraryFiles); + pkg.packageName, changingLib, true, + pkg.applicationInfo.targetSdkVersion, usesLibraryFiles); } if (pkg.usesOptionalLibraries != null) { usesLibraryFiles = addSharedLibrariesLPw(pkg.usesOptionalLibraries, - null, null, pkg.packageName, changingLib, false, usesLibraryFiles); + null, null, pkg.packageName, changingLib, false, + pkg.applicationInfo.targetSdkVersion, usesLibraryFiles); } if (!ArrayUtils.isEmpty(usesLibraryFiles)) { pkg.usesLibraryFiles = usesLibraryFiles.toArray(new String[usesLibraryFiles.size()]); @@ -10354,9 +10416,9 @@ public class PackageManagerService extends IPackageManager.Stub } private ArraySet<String> addSharedLibrariesLPw(@NonNull List<String> requestedLibraries, - @Nullable int[] requiredVersions, @Nullable String[] requiredCertDigests, + @Nullable int[] requiredVersions, @Nullable String[][] requiredCertDigests, @NonNull String packageName, @Nullable PackageParser.Package changingLib, - boolean required, @Nullable ArraySet<String> outUsedLibraries) + boolean required, int targetSdk, @Nullable ArraySet<String> outUsedLibraries) throws PackageManagerException { final int libCount = requestedLibraries.size(); for (int i = 0; i < libCount; i++) { @@ -10390,13 +10452,34 @@ public class PackageManagerService extends IPackageManager.Stub + " library; failing!"); } - String expectedCertDigest = requiredCertDigests[i]; - String libCertDigest = PackageUtils.computeCertSha256Digest( - libPkg.mSignatures[0]); - if (!libCertDigest.equalsIgnoreCase(expectedCertDigest)) { + final String[] expectedCertDigests = requiredCertDigests[i]; + // For apps targeting O MR1 we require explicit enumeration of all certs. + final String[] libCertDigests = (targetSdk > Build.VERSION_CODES.O) + ? PackageUtils.computeSignaturesSha256Digests(libPkg.mSignatures) + : PackageUtils.computeSignaturesSha256Digests( + new Signature[]{libPkg.mSignatures[0]}); + + // Take a shortcut if sizes don't match. Note that if an app doesn't + // target O we don't parse the "additional-certificate" tags similarly + // how we only consider all certs only for apps targeting O (see above). + // Therefore, the size check is safe to make. + if (expectedCertDigests.length != libCertDigests.length) { throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY, "Package " + packageName + " requires differently signed" + - " static shared library; failing!"); + " static sDexLoadReporter.java:45.19hared library; failing!"); + } + + // Use a predictable order as signature order may vary + Arrays.sort(libCertDigests); + Arrays.sort(expectedCertDigests); + + final int certCount = libCertDigests.length; + for (int j = 0; j < certCount; j++) { + if (!libCertDigests[j].equalsIgnoreCase(expectedCertDigests[j])) { + throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY, + "Package " + packageName + " requires differently signed" + + " static shared library; failing!"); + } } } @@ -11072,7 +11155,7 @@ public class PackageManagerService extends IPackageManager.Stub r.info.encryptionAware = r.info.directBootAware = true; } } - if (compressedFileExists(pkg.baseCodePath)) { + if (compressedFileExists(pkg.codePath)) { pkg.isStub = true; } } else { @@ -13170,10 +13253,19 @@ public class PackageManagerService extends IPackageManager.Stub + pkg.packageName + " - not in privapp-permissions whitelist"); // Only report violations for apps on system image if (!mSystemReady && !pkg.isUpdatedSystemApp()) { - if (mPrivappPermissionsViolations == null) { - mPrivappPermissionsViolations = new ArraySet<>(); + // it's only a reportable violation if the permission isn't explicitly denied + final ArraySet<String> deniedPermissions = SystemConfig.getInstance() + .getPrivAppDenyPermissions(pkg.packageName); + final boolean permissionViolation = + deniedPermissions == null || !deniedPermissions.contains(perm); + if (permissionViolation) { + if (mPrivappPermissionsViolations == null) { + mPrivappPermissionsViolations = new ArraySet<>(); + } + mPrivappPermissionsViolations.add(pkg.packageName + ": " + perm); + } else { + return false; } - mPrivappPermissionsViolations.add(pkg.packageName + ": " + perm); } if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) { return false; @@ -14368,7 +14460,7 @@ public class PackageManagerService extends IPackageManager.Stub } if (savedInfo.second == info) { // circled back to the highest ordered item; remove from order list - mOrderResult.remove(savedInfo); + mOrderResult.remove(packageName); if (mOrderResult.size() == 0) { // no more ordered items break; @@ -17367,6 +17459,7 @@ public class PackageManagerService extends IPackageManager.Stub PackageParser.Package pkg; int returnCode; String returnMsg; + String installerPackageName; PackageRemovedInfo removedInfo; ArrayMap<String, PackageInstalledInfo> addedChildPackages; @@ -18287,6 +18380,7 @@ public class PackageManagerService extends IPackageManager.Stub // Result object to be returned res.setReturnCode(PackageManager.INSTALL_SUCCEEDED); + res.installerPackageName = installerPackageName; if (DEBUG_INSTALL) Slog.d(TAG, "installPackageLI: path=" + tmpPackageFile); @@ -18529,12 +18623,12 @@ public class PackageManagerService extends IPackageManager.Stub BasePermission bp = mSettings.mPermissions.get(perm.info.name); // Don't allow anyone but the system to define ephemeral permissions. - if ((perm.info.protectionLevel & PermissionInfo.PROTECTION_FLAG_EPHEMERAL) != 0 + if ((perm.info.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0 && !systemApp) { Slog.w(TAG, "Non-System package " + pkg.packageName + " attempting to delcare ephemeral permission " + perm.info.name + "; Removing ephemeral."); - perm.info.protectionLevel &= ~PermissionInfo.PROTECTION_FLAG_EPHEMERAL; + perm.info.protectionLevel &= ~PermissionInfo.PROTECTION_FLAG_INSTANT; } // Check whether the newly-scanned package wants to define an already-defined perm if (bp != null) { @@ -19720,6 +19814,10 @@ public class PackageManagerService extends IPackageManager.Stub // writer synchronized (mPackages) { + // NOTE: The system package always needs to be enabled; even if it's for + // a compressed stub. If we don't, installing the system package fails + // during scan [scanning checks the disabled packages]. We will reverse + // this later, after we've "installed" the stub. // Reinstate the old system package enableSystemPackageLPw(disabledPs.pkg); // Remove any native libraries from the upgraded package. @@ -19728,23 +19826,38 @@ public class PackageManagerService extends IPackageManager.Stub // Install the system package if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs); + try { + installPackageFromSystemLIF(disabledPs.codePath, false /*isPrivileged*/, allUserHandles, + outInfo.origUsers, deletedPs.getPermissionsState(), writeSettings); + } catch (PackageManagerException e) { + Slog.w(TAG, "Failed to restore system package:" + deletedPkg.packageName + ": " + + e.getMessage()); + return false; + } finally { + if (disabledPs.pkg.isStub) { + mSettings.disableSystemPackageLPw(disabledPs.name, true /*replaced*/); + } + } + return true; + } + + /** + * Installs a package that's already on the system partition. + */ + private PackageParser.Package installPackageFromSystemLIF(@NonNull File codePath, + boolean isPrivileged, @Nullable int[] allUserHandles, @Nullable int[] origUserHandles, + @Nullable PermissionsState origPermissionState, boolean writeSettings) + throws PackageManagerException { int parseFlags = mDefParseFlags | PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR; - if (locationIsPrivileged(disabledPs.codePath)) { + if (isPrivileged || locationIsPrivileged(codePath)) { parseFlags |= PackageParser.PARSE_IS_PRIVILEGED; } - final PackageParser.Package newPkg; - try { - newPkg = scanPackageTracedLI(disabledPs.codePath, parseFlags, 0 /* scanFlags */, - 0 /* currentTime */, null); - } catch (PackageManagerException e) { - Slog.w(TAG, "Failed to restore system package:" + deletedPkg.packageName + ": " - + e.getMessage()); - return false; - } + final PackageParser.Package newPkg = + scanPackageTracedLI(codePath, parseFlags, 0 /*scanFlags*/, 0 /*currentTime*/, null); try { // update shared libraries for the newly re-installed system package @@ -19762,17 +19875,21 @@ public class PackageManagerService extends IPackageManager.Stub // Propagate the permissions state as we do not want to drop on the floor // runtime permissions. The update permissions method below will take // care of removing obsolete permissions and grant install permissions. - ps.getPermissionsState().copyFrom(deletedPs.getPermissionsState()); + if (origPermissionState != null) { + ps.getPermissionsState().copyFrom(origPermissionState); + } updatePermissionsLPw(newPkg.packageName, newPkg, UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG); + final boolean applyUserRestrictions + = (allUserHandles != null) && (origUserHandles != null); if (applyUserRestrictions) { boolean installedStateChanged = false; if (DEBUG_REMOVE) { Slog.d(TAG, "Propagating install state across reinstall"); } for (int userId : allUserHandles) { - final boolean installed = ArrayUtils.contains(outInfo.origUsers, userId); + final boolean installed = ArrayUtils.contains(origUserHandles, userId); if (DEBUG_REMOVE) { Slog.d(TAG, " user " + userId + " => " + installed); } @@ -19795,7 +19912,7 @@ public class PackageManagerService extends IPackageManager.Stub mSettings.writeLPr(); } } - return true; + return newPkg; } private boolean deleteInstalledPackageLIF(PackageSetting ps, @@ -20243,10 +20360,8 @@ public class PackageManagerService extends IPackageManager.Stub true /* requireFullPermission */, false /* checkShell */, "clear application data"); final PackageSetting ps = mSettings.getPackageLPr(packageName); - if (ps != null && filterAppAccessLPr(ps, callingUid, userId)) { - return; - } - if (mProtectedPackages.isPackageDataProtected(userId, packageName)) { + final boolean filterApp = (ps != null && filterAppAccessLPr(ps, callingUid, userId)); + if (!filterApp && mProtectedPackages.isPackageDataProtected(userId, packageName)) { throw new SecurityException("Cannot clear data for a protected package: " + packageName); } @@ -20255,26 +20370,30 @@ public class PackageManagerService extends IPackageManager.Stub public void run() { mHandler.removeCallbacks(this); final boolean succeeded; - try (PackageFreezer freezer = freezePackage(packageName, - "clearApplicationUserData")) { - synchronized (mInstallLock) { - succeeded = clearApplicationUserDataLIF(packageName, userId); - } - clearExternalStorageDataSync(packageName, userId, true); - synchronized (mPackages) { - mInstantAppRegistry.deleteInstantApplicationMetadataLPw( - packageName, userId); + if (!filterApp) { + try (PackageFreezer freezer = freezePackage(packageName, + "clearApplicationUserData")) { + synchronized (mInstallLock) { + succeeded = clearApplicationUserDataLIF(packageName, userId); + } + clearExternalStorageDataSync(packageName, userId, true); + synchronized (mPackages) { + mInstantAppRegistry.deleteInstantApplicationMetadataLPw( + packageName, userId); + } } - } - if (succeeded) { - // invoke DeviceStorageMonitor's update method to clear any notifications - DeviceStorageMonitorInternal dsm = LocalServices - .getService(DeviceStorageMonitorInternal.class); - if (dsm != null) { - dsm.checkMemory(); + if (succeeded) { + // invoke DeviceStorageMonitor's update method to clear any notifications + DeviceStorageMonitorInternal dsm = LocalServices + .getService(DeviceStorageMonitorInternal.class); + if (dsm != null) { + dsm.checkMemory(); + } } + } else { + succeeded = false; } - if(observer != null) { + if (observer != null) { try { observer.onRemoveCompleted(packageName, succeeded); } catch (RemoteException e) { @@ -21733,35 +21852,147 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); // unless it is a test package. int oldState = pkgSetting.getEnabled(userId); if (className == null - && - (oldState == COMPONENT_ENABLED_STATE_DISABLED_USER - || oldState == COMPONENT_ENABLED_STATE_DEFAULT - || oldState == COMPONENT_ENABLED_STATE_ENABLED) - && - (newState == COMPONENT_ENABLED_STATE_DISABLED_USER - || newState == COMPONENT_ENABLED_STATE_DEFAULT - || newState == COMPONENT_ENABLED_STATE_ENABLED)) { + && + (oldState == COMPONENT_ENABLED_STATE_DISABLED_USER + || oldState == COMPONENT_ENABLED_STATE_DEFAULT + || oldState == COMPONENT_ENABLED_STATE_ENABLED) + && + (newState == COMPONENT_ENABLED_STATE_DISABLED_USER + || newState == COMPONENT_ENABLED_STATE_DEFAULT + || newState == COMPONENT_ENABLED_STATE_ENABLED)) { // ok } else { throw new SecurityException( "Shell cannot change component state for " + packageName + "/" - + className + " to " + newState); + + className + " to " + newState); } } - if (className == null) { - // We're dealing with an application/package level state change + } + if (className == null) { + // We're dealing with an application/package level state change + synchronized (mPackages) { if (pkgSetting.getEnabled(userId) == newState) { // Nothing to do return; } - if (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT - || newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) { - // Don't care about who enables an app. - callingPackage = null; + } + // If we're enabling a system stub, there's a little more work to do. + // Prior to enabling the package, we need to decompress the APK(s) to the + // data partition and then replace the version on the system partition. + final PackageParser.Package deletedPkg = pkgSetting.pkg; + final boolean isSystemStub = deletedPkg.isStub + && deletedPkg.isSystemApp(); + if (isSystemStub + && (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT + || newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED)) { + final File codePath = decompressPackage(deletedPkg); + if (codePath == null) { + Slog.e(TAG, "couldn't decompress pkg: " + pkgSetting.name); + return; + } + // TODO remove direct parsing of the package object during internal cleanup + // of scan package + // We need to call parse directly here for no other reason than we need + // the new package in order to disable the old one [we use the information + // for some internal optimization to optionally create a new package setting + // object on replace]. However, we can't get the package from the scan + // because the scan modifies live structures and we need to remove the + // old [system] package from the system before a scan can be attempted. + // Once scan is indempotent we can remove this parse and use the package + // object we scanned, prior to adding it to package settings. + final PackageParser pp = new PackageParser(); + pp.setSeparateProcesses(mSeparateProcesses); + pp.setDisplayMetrics(mMetrics); + pp.setCallback(mPackageParserCallback); + final PackageParser.Package tmpPkg; + try { + final int parseFlags = mDefParseFlags + | PackageParser.PARSE_MUST_BE_APK + | PackageParser.PARSE_IS_SYSTEM + | PackageParser.PARSE_IS_SYSTEM_DIR; + tmpPkg = pp.parsePackage(codePath, parseFlags); + } catch (PackageParserException e) { + Slog.w(TAG, "Failed to parse compressed system package:" + pkgSetting.name, e); + return; } + synchronized (mInstallLock) { + // Disable the stub and remove any package entries + removePackageLI(deletedPkg, true); + synchronized (mPackages) { + disableSystemPackageLPw(deletedPkg, tmpPkg); + } + final PackageParser.Package newPkg; + try (PackageFreezer freezer = + freezePackage(deletedPkg.packageName, "setEnabledSetting")) { + final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY + | PackageParser.PARSE_ENFORCE_CODE; + newPkg = scanPackageTracedLI(codePath, parseFlags, 0 /*scanFlags*/, + 0 /*currentTime*/, null /*user*/); + prepareAppDataAfterInstallLIF(newPkg); + synchronized (mPackages) { + try { + updateSharedLibrariesLPr(newPkg, null); + } catch (PackageManagerException e) { + Slog.e(TAG, "updateAllSharedLibrariesLPw failed: ", e); + } + updatePermissionsLPw(newPkg.packageName, newPkg, + UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG); + mSettings.writeLPr(); + } + } catch (PackageManagerException e) { + // Whoops! Something went wrong; try to roll back to the stub + Slog.w(TAG, "Failed to install compressed system package:" + + pkgSetting.name, e); + // Remove the failed install + removeCodePathLI(codePath); + + // Install the system package + try (PackageFreezer freezer = + freezePackage(deletedPkg.packageName, "setEnabledSetting")) { + synchronized (mPackages) { + // NOTE: The system package always needs to be enabled; even + // if it's for a compressed stub. If we don't, installing the + // system package fails during scan [scanning checks the disabled + // packages]. We will reverse this later, after we've "installed" + // the stub. + // This leaves us in a fragile state; the stub should never be + // enabled, so, cross your fingers and hope nothing goes wrong + // until we can disable the package later. + enableSystemPackageLPw(deletedPkg); + } + installPackageFromSystemLIF(new File(deletedPkg.codePath), + false /*isPrivileged*/, null /*allUserHandles*/, + null /*origUserHandles*/, null /*origPermissionsState*/, + true /*writeSettings*/); + } catch (PackageManagerException pme) { + Slog.w(TAG, "Failed to restore system package:" + + deletedPkg.packageName, pme); + } finally { + synchronized (mPackages) { + mSettings.disableSystemPackageLPw( + deletedPkg.packageName, true /*replaced*/); + mSettings.writeLPr(); + } + } + return; + } + clearAppDataLIF(newPkg, UserHandle.USER_ALL, FLAG_STORAGE_DE + | FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); + clearAppProfilesLIF(newPkg, UserHandle.USER_ALL); + mDexManager.notifyPackageUpdated(newPkg.packageName, + newPkg.baseCodePath, newPkg.splitCodePaths); + } + } + if (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT + || newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) { + // Don't care about who enables an app. + callingPackage = null; + } + synchronized (mPackages) { pkgSetting.setEnabled(newState, userId, callingPackage); - // pkgSetting.pkg.mSetEnabled = newState; - } else { + } + } else { + synchronized (mPackages) { // We're dealing with a component level state change // First, verify that this is a valid class name. PackageParser.Package pkg = pkgSetting.pkg; @@ -21777,26 +22008,28 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); } } switch (newState) { - case COMPONENT_ENABLED_STATE_ENABLED: - if (!pkgSetting.enableComponentLPw(className, userId)) { - return; - } - break; - case COMPONENT_ENABLED_STATE_DISABLED: - if (!pkgSetting.disableComponentLPw(className, userId)) { - return; - } - break; - case COMPONENT_ENABLED_STATE_DEFAULT: - if (!pkgSetting.restoreComponentLPw(className, userId)) { + case COMPONENT_ENABLED_STATE_ENABLED: + if (!pkgSetting.enableComponentLPw(className, userId)) { + return; + } + break; + case COMPONENT_ENABLED_STATE_DISABLED: + if (!pkgSetting.disableComponentLPw(className, userId)) { + return; + } + break; + case COMPONENT_ENABLED_STATE_DEFAULT: + if (!pkgSetting.restoreComponentLPw(className, userId)) { + return; + } + break; + default: + Slog.e(TAG, "Invalid new component state: " + newState); return; - } - break; - default: - Slog.e(TAG, "Invalid new component state: " + newState); - return; } } + } + synchronized (mPackages) { scheduleWritePackageRestrictionsLocked(userId); updateSequenceNumberLP(pkgSetting, new int[] { userId }); final long callingId = Binder.clearCallingIdentity(); @@ -25276,6 +25509,13 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); public boolean canAccessInstantApps(int callingUid, int userId) { return PackageManagerService.this.canViewInstantApps(callingUid, userId); } + + @Override + public boolean hasInstantApplicationMetadata(String packageName, int userId) { + synchronized (mPackages) { + return mInstantAppRegistry.hasInstantApplicationMetadataLPr(packageName, userId); + } + } } @Override diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index 46e21dbc98bd..909ffabfd2db 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -148,6 +148,8 @@ class PackageManagerShellCommand extends ShellCommand { return runSetHomeActivity(); case "get-privapp-permissions": return runGetPrivappPermissions(); + case "get-privapp-deny-permissions": + return runGetPrivappDenyPermissions(); case "get-instantapp-resolver": return runGetInstantAppResolver(); case "has-feature": @@ -1293,6 +1295,19 @@ class PackageManagerShellCommand extends ShellCommand { return 0; } + private int runGetPrivappDenyPermissions() { + final String pkg = getNextArg(); + if (pkg == null) { + System.err.println("Error: no package specified."); + return 1; + } + ArraySet<String> privAppDenyPermissions = + SystemConfig.getInstance().getPrivAppDenyPermissions(pkg); + getOutPrintWriter().println(privAppDenyPermissions == null + ? "{}" : privAppDenyPermissions.toString()); + return 0; + } + private int runGetInstantAppResolver() { final PrintWriter pw = getOutPrintWriter(); try { diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index d99408f592d1..56835f69a3c7 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -4867,7 +4867,7 @@ final class Settings { pw.print(" enabled="); pw.print(ps.getEnabled(user.id)); pw.print(" instant="); - pw.println(ps.getInstantApp(user.id)); + pw.print(ps.getInstantApp(user.id)); pw.print(" virtual="); pw.println(ps.getVirtulalPreload(user.id)); diff --git a/services/core/java/com/android/server/policy/AccessibilityShortcutController.java b/services/core/java/com/android/server/policy/AccessibilityShortcutController.java index 0a8635d7210f..55c582ed47b4 100644 --- a/services/core/java/com/android/server/policy/AccessibilityShortcutController.java +++ b/services/core/java/com/android/server/policy/AccessibilityShortcutController.java @@ -24,6 +24,7 @@ import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; +import android.content.pm.PackageManager; import android.database.ContentObserver; import android.media.AudioAttributes; import android.media.Ringtone; @@ -138,13 +139,18 @@ public class AccessibilityShortcutController { final int userId = ActivityManager.getCurrentUser(); final int dialogAlreadyShown = Settings.Secure.getIntForUser( cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0, userId); + // Use USAGE_ASSISTANCE_ACCESSIBILITY for TVs to ensure that TVs play the ringtone as they + // have less ways of providing feedback like vibration. + final int audioAttributesUsage = hasFeatureLeanback() + ? AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY + : AudioAttributes.USAGE_NOTIFICATION_EVENT; // Play a notification tone final Ringtone tone = RingtoneManager.getRingtone(mContext, Settings.System.DEFAULT_NOTIFICATION_URI); if (tone != null) { tone.setAudioAttributes(new AudioAttributes.Builder() - .setUsage(AudioAttributes.USAGE_NOTIFICATION_EVENT) + .setUsage(audioAttributesUsage) .build()); tone.play(); } @@ -254,6 +260,10 @@ public class AccessibilityShortcutController { AccessibilityServiceInfo.FEEDBACK_ALL_MASK).contains(serviceInfo); } + private boolean hasFeatureLeanback() { + return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK); + } + // Class to allow mocking of static framework calls public static class FrameworkObjectProvider { public AccessibilityManager getAccessibilityManagerInstance(Context context) { diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index ae78d7c551c1..68913c3a887a 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -26,8 +26,8 @@ import static android.app.AppOpsManager.OP_TOAST_WINDOW; import static android.content.Context.CONTEXT_RESTRICTED; import static android.content.Context.DISPLAY_SERVICE; import static android.content.Context.WINDOW_SERVICE; -import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE; import static android.content.pm.PackageManager.FEATURE_LEANBACK; +import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE; import static android.content.pm.PackageManager.FEATURE_WATCH; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.res.Configuration.EMPTY; @@ -35,6 +35,8 @@ import static android.content.res.Configuration.UI_MODE_TYPE_CAR; import static android.content.res.Configuration.UI_MODE_TYPE_MASK; import static android.os.Build.VERSION_CODES.M; import static android.os.Build.VERSION_CODES.O; +import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.Display.STATE_OFF; import static android.view.WindowManager.DOCKED_LEFT; import static android.view.WindowManager.DOCKED_RIGHT; import static android.view.WindowManager.DOCKED_TOP; @@ -57,6 +59,7 @@ import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_SYSTEM_WINDOW; import static android.view.WindowManager.LayoutParams.MATCH_PARENT; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; @@ -70,8 +73,8 @@ import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; -import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS; import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; @@ -115,11 +118,14 @@ import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT; import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED; import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN; +import static com.android.server.wm.proto.WindowManagerPolicyProto.STABLE_BOUNDS; + import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManager.StackId; import android.app.ActivityManagerInternal; import android.app.ActivityManagerInternal.SleepToken; +import android.app.ActivityThread; import android.app.AppOpsManager; import android.app.IUiModeManager; import android.app.ProgressDialog; @@ -177,8 +183,8 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.os.UEventObserver; import android.os.UserHandle; -import android.os.Vibrator; import android.os.VibrationEffect; +import android.os.Vibrator; import android.provider.MediaStore; import android.provider.Settings; import android.service.dreams.DreamManagerInternal; @@ -194,6 +200,7 @@ import android.util.LongSparseArray; import android.util.MutableBoolean; import android.util.Slog; import android.util.SparseArray; +import android.util.proto.ProtoOutputStream; import android.view.Display; import android.view.Gravity; import android.view.HapticFeedbackConstants; @@ -226,6 +233,7 @@ import android.view.autofill.AutofillManagerInternal; import android.view.inputmethod.InputMethodManagerInternal; import com.android.internal.R; +import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; import com.android.internal.policy.IKeyguardDismissCallback; import com.android.internal.policy.IShortcutService; @@ -240,8 +248,8 @@ import com.android.server.policy.keyguard.KeyguardServiceDelegate; import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener; import com.android.server.policy.keyguard.KeyguardStateMonitor.StateCallback; import com.android.server.statusbar.StatusBarManagerInternal; -import com.android.server.wm.AppTransition; import com.android.server.vr.VrManagerInternal; +import com.android.server.wm.AppTransition; import java.io.File; import java.io.FileReader; @@ -676,6 +684,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { private boolean mLastShowingDream; boolean mDreamingLockscreen; boolean mDreamingSleepTokenNeeded; + private boolean mWindowSleepTokenNeeded; + private boolean mLastWindowSleepTokenNeeded; + + @GuardedBy("mHandler") + private SleepToken mWindowSleepToken; + SleepToken mDreamingSleepToken; SleepToken mScreenOffSleepToken; volatile boolean mKeyguardOccluded; @@ -1036,6 +1050,22 @@ public class PhoneWindowManager implements WindowManagerPolicy { } }; + private final Runnable mAcquireSleepTokenRunnable = () -> { + if (mWindowSleepToken != null) { + return; + } + mWindowSleepToken = mActivityManagerInternal.acquireSleepToken("WindowSleepToken", + DEFAULT_DISPLAY); + }; + + private final Runnable mReleaseSleepTokenRunnable = () -> { + if (mWindowSleepToken == null) { + return; + } + mWindowSleepToken.release(); + mWindowSleepToken = null; + }; + private ImmersiveModeConfirmation mImmersiveModeConfirmation; private SystemGesturesPointerEventListener mSystemGestures; @@ -2148,7 +2178,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // This method might be called before the policy has been fully initialized // or for other displays we don't care about. // TODO(multi-display): Define policy for secondary displays. - if (mContext == null || display.getDisplayId() != Display.DEFAULT_DISPLAY) { + if (mContext == null || display.getDisplayId() != DEFAULT_DISPLAY) { return; } mDisplay = display; @@ -2244,7 +2274,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) { // TODO(multi-display): Define policy for secondary displays. - if (display.getDisplayId() == Display.DEFAULT_DISPLAY) { + if (display.getDisplayId() == DEFAULT_DISPLAY) { mOverscanLeft = left; mOverscanTop = top; mOverscanRight = right; @@ -2642,7 +2672,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public void onConfigurationChanged() { // TODO(multi-display): Define policy for secondary displays. - final Resources res = mContext.getResources(); + Context uiContext = ActivityThread.currentActivityThread().getSystemUiContext(); + final Resources res = uiContext.getResources(); mStatusBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); @@ -2699,7 +2730,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode, int displayId) { // TODO(multi-display): Support navigation bar on secondary displays. - if (displayId == Display.DEFAULT_DISPLAY && mHasNavigationBar) { + if (displayId == DEFAULT_DISPLAY && mHasNavigationBar) { // For a basic navigation bar, when we are in landscape mode we place // the navigation bar to the side. if (mNavigationBarCanMove && fullWidth > fullHeight) { @@ -2721,7 +2752,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode, int displayId) { // TODO(multi-display): Support navigation bar on secondary displays. - if (displayId == Display.DEFAULT_DISPLAY && mHasNavigationBar) { + if (displayId == DEFAULT_DISPLAY && mHasNavigationBar) { // For a basic navigation bar, when we are in portrait mode we place // the navigation bar to the bottom. if (!mNavigationBarCanMove || fullWidth < fullHeight) { @@ -2745,7 +2776,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // we do want to exclude it since applications can't generally use that part // of the screen. // TODO(multi-display): Support status bars on secondary displays. - if (displayId == Display.DEFAULT_DISPLAY) { + if (displayId == DEFAULT_DISPLAY) { return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation, uiMode, displayId) - mStatusBarHeight; } @@ -2797,7 +2828,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean keyguardLocked = isKeyguardLocked(); boolean hideDockDivider = attrs.type == TYPE_DOCK_DIVIDER && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID); - return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == Display.DEFAULT_DISPLAY) + return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == DEFAULT_DISPLAY) || hideDockDivider; } @@ -2967,7 +2998,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** Obtain proper context for showing splash screen on the provided display. */ private Context getDisplayContext(Context context, int displayId) { - if (displayId == Display.DEFAULT_DISPLAY) { + if (displayId == DEFAULT_DISPLAY) { // The default context fits. return context; } @@ -3370,11 +3401,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (!down) { cancelPreloadRecentApps(); - if (mHasFeatureLeanback) { - // Clear flags - mAccessibilityTvKey2Pressed = down; - } - mHomePressed = false; if (mHomeConsumed) { mHomeConsumed = false; @@ -3429,13 +3455,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { preloadRecentApps(); } } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { - if (mHasFeatureLeanback) { - mAccessibilityTvKey2Pressed = down; - if (interceptAccessibilityGestureTv()) { - return -1; - } - } - if (!keyguardOn) { handleLongPressOnHome(event.getDeviceId()); } @@ -3602,11 +3621,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { return 0; } else if (mHasFeatureLeanback && interceptBugreportGestureTv(keyCode, down)) { return -1; - } else if (mHasFeatureLeanback && keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { - mAccessibilityTvKey1Pressed = down; - if (interceptAccessibilityGestureTv()) { - return -1; - } + } else if (mHasFeatureLeanback && interceptAccessibilityGestureTv(keyCode, down)) { + return -1; } // Toggle Caps Lock on META-ALT. @@ -3827,20 +3843,28 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** * TV only: recognizes a remote control gesture as Accessibility shortcut. - * Shortcut: Long press (HOME + DPAD_CENTER) + * Shortcut: Long press (BACK + DPAD_DOWN) */ - private boolean interceptAccessibilityGestureTv() { + private boolean interceptAccessibilityGestureTv(int keyCode, boolean down) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + mAccessibilityTvKey1Pressed = down; + } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { + mAccessibilityTvKey2Pressed = down; + } + if (mAccessibilityTvKey1Pressed && mAccessibilityTvKey2Pressed) { if (!mAccessibilityTvScheduled) { mAccessibilityTvScheduled = true; Message msg = Message.obtain(mHandler, MSG_ACCESSIBILITY_TV); msg.setAsynchronous(true); - mHandler.sendMessage(msg); + mHandler.sendMessageDelayed(msg, + ViewConfiguration.get(mContext).getAccessibilityShortcutKeyTimeout()); } } else if (mAccessibilityTvScheduled) { mHandler.removeMessages(MSG_ACCESSIBILITY_TV); mAccessibilityTvScheduled = false; } + return mAccessibilityTvScheduled; } @@ -5365,6 +5389,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mAllowLockscreenWhenOn = false; mShowingDream = false; + mWindowSleepTokenNeeded = false; } /** {@inheritDoc} */ @@ -5462,6 +5487,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { && stackId == DOCKED_STACK_ID) { mTopDockedOpaqueOrDimmingWindowState = win; } + + // Take note if a window wants to acquire a sleep token. + if (win.isVisibleLw() && (attrs.privateFlags & PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN) != 0 + && win.canAcquireSleepToken()) { + mWindowSleepTokenNeeded = true; + } } private void applyKeyguardPolicyLw(WindowState win, WindowState imeTarget) { @@ -5517,6 +5548,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs(); boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT && statusBarAttrs.width == MATCH_PARENT; + boolean topAppHidesStatusBar = topAppHidesStatusBar(); if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent || statusBarExpanded) { if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced"); @@ -5537,16 +5569,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } } else if (mTopFullscreenOpaqueWindowState != null) { - final int fl = PolicyControl.getWindowFlags(null, lp); - if (localLOGV) { - Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw() - + " shown position: " - + mTopFullscreenOpaqueWindowState.getShownPositionLw()); - Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs() - + " lp.flags=0x" + Integer.toHexString(fl)); - } - topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0 - || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; + topIsFullscreen = topAppHidesStatusBar; // The subtle difference between the window for mTopFullscreenOpaqueWindowState // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the @@ -5569,8 +5592,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mStatusBarController.setBarShowingLw(true)) { changes |= FINISH_LAYOUT_REDO_LAYOUT; } + topAppHidesStatusBar = false; } } + mStatusBarController.setTopAppHidesStatusBar(topAppHidesStatusBar); } if (mTopIsFullscreen != topIsFullscreen) { @@ -5592,11 +5617,45 @@ public class PhoneWindowManager implements WindowManagerPolicy { mWindowManagerFuncs.notifyShowingDreamChanged(); } + updateWindowSleepToken(); + // update since mAllowLockscreenWhenOn might have changed updateLockScreenTimeout(); return changes; } + private void updateWindowSleepToken() { + if (mWindowSleepTokenNeeded && !mLastWindowSleepTokenNeeded) { + mHandler.removeCallbacks(mReleaseSleepTokenRunnable); + mHandler.post(mAcquireSleepTokenRunnable); + } else if (!mWindowSleepTokenNeeded && mLastWindowSleepTokenNeeded) { + mHandler.removeCallbacks(mAcquireSleepTokenRunnable); + mHandler.post(mReleaseSleepTokenRunnable); + } + mLastWindowSleepTokenNeeded = mWindowSleepTokenNeeded; + } + + /** + * @return Whether the top app should hide the statusbar based on the top fullscreen opaque + * window. + */ + private boolean topAppHidesStatusBar() { + if (mTopFullscreenOpaqueWindowState == null) { + return false; + } + final int fl = PolicyControl.getWindowFlags(null, + mTopFullscreenOpaqueWindowState.getAttrs()); + if (localLOGV) { + Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw() + + " shown position: " + + mTopFullscreenOpaqueWindowState.getShownPositionLw()); + Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs() + + " lp.flags=0x" + Integer.toHexString(fl)); + } + return (fl & LayoutParams.FLAG_FULLSCREEN) != 0 + || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; + } + /** * Updates the occluded state of the Keyguard. * @@ -6330,7 +6389,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) { - final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF); + final boolean displayOff = (mDisplay == null || mDisplay.getState() == STATE_OFF); if (displayOff && !mHasFeatureWatch) { return false; @@ -7466,10 +7525,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + // TODO (multidisplay): Support multiple displays in WindowManagerPolicy. private void updateDreamingSleepToken(boolean acquire) { if (acquire) { if (mDreamingSleepToken == null) { - mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream"); + mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken( + "Dream", DEFAULT_DISPLAY); } } else { if (mDreamingSleepToken != null) { @@ -7479,10 +7540,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + // TODO (multidisplay): Support multiple displays in WindowManagerPolicy. private void updateScreenOffSleepToken(boolean acquire) { if (acquire) { if (mScreenOffSleepToken == null) { - mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff"); + mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken( + "ScreenOff", DEFAULT_DISPLAY); } } else { if (mScreenOffSleepToken != null) { @@ -7741,13 +7804,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { private VibrationEffect getVibrationEffect(int effectId) { long[] pattern; switch (effectId) { - case HapticFeedbackConstants.VIRTUAL_KEY: - return VibrationEffect.get(VibrationEffect.EFFECT_CLICK); case HapticFeedbackConstants.LONG_PRESS: pattern = mLongPressVibePattern; break; - case HapticFeedbackConstants.KEYBOARD_TAP: - return VibrationEffect.get(VibrationEffect.EFFECT_CLICK); case HapticFeedbackConstants.CLOCK_TICK: return VibrationEffect.get(VibrationEffect.EFFECT_TICK); case HapticFeedbackConstants.CALENDAR_DATE: @@ -7758,10 +7817,16 @@ public class PhoneWindowManager implements WindowManagerPolicy { break; case HapticFeedbackConstants.CONTEXT_CLICK: return VibrationEffect.get(VibrationEffect.EFFECT_TICK); + case HapticFeedbackConstants.VIRTUAL_KEY: + return VibrationEffect.get(VibrationEffect.EFFECT_CLICK); case HapticFeedbackConstants.VIRTUAL_KEY_RELEASE: - return VibrationEffect.get(VibrationEffect.EFFECT_TICK); + return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false); + case HapticFeedbackConstants.KEYBOARD_PRESS: // == HapticFeedbackConstants.KEYBOARD_TAP + return VibrationEffect.get(VibrationEffect.EFFECT_CLICK); + case HapticFeedbackConstants.KEYBOARD_RELEASE: + return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false); case HapticFeedbackConstants.TEXT_HANDLE_MOVE: - return VibrationEffect.get(VibrationEffect.EFFECT_TICK); + return VibrationEffect.get(VibrationEffect.EFFECT_TICK, false); default: return null; } @@ -8218,6 +8283,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { } @Override + public void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + new Rect(mStableLeft, mStableTop, mStableRight, mStableBottom).writeToProto(proto, + STABLE_BOUNDS); + proto.end(token); + } + + @Override public void dump(String prefix, PrintWriter pw, String[] args) { pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode); pw.print(" mSystemReady="); pw.print(mSystemReady); diff --git a/services/core/java/com/android/server/policy/StatusBarController.java b/services/core/java/com/android/server/policy/StatusBarController.java index 7d67b60a9e9f..ecc88b50a37c 100644 --- a/services/core/java/com/android/server/policy/StatusBarController.java +++ b/services/core/java/com/android/server/policy/StatusBarController.java @@ -112,6 +112,14 @@ public class StatusBarController extends BarController { View.STATUS_BAR_TRANSPARENT); } + + public void setTopAppHidesStatusBar(boolean hidesStatusBar) { + StatusBarManagerInternal statusbar = getStatusBarInternal(); + if (statusbar != null) { + statusbar.setTopAppHidesStatusBar(hidesStatusBar); + } + } + @Override protected boolean skipAnimation() { return mWin.getAttrs().height == MATCH_PARENT; diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 0c72326095a6..3b701302aae1 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -204,8 +204,8 @@ public final class PowerManagerService extends SystemService // Possible reasons for shutting down for use in data/misc/reboot/last_shutdown_reason private static final String REASON_SHUTDOWN = "shutdown"; private static final String REASON_REBOOT = "reboot"; - private static final String REASON_USERREQUESTED = "userrequested"; - private static final String REASON_THERMAL_SHUTDOWN = "thermal-shutdown"; + private static final String REASON_USERREQUESTED = "shutdown,userrequested"; + private static final String REASON_THERMAL_SHUTDOWN = "shutdown,thermal"; private static final String TRACE_SCREEN_ON = "Screen turning on"; @@ -220,8 +220,8 @@ public final class PowerManagerService extends SystemService private static final int HALT_MODE_REBOOT = 1; private static final int HALT_MODE_REBOOT_SAFE_MODE = 2; - // File location for last reboot reason - private static final String LAST_REBOOT_LOCATION = "/data/misc/reboot/last_reboot_reason"; + // Persistent property for last reboot reason + private static final String LAST_REBOOT_PROPERTY = "persist.sys.boot.reason"; private final Context mContext; private final ServiceThread mHandlerThread; @@ -4390,7 +4390,7 @@ public final class PowerManagerService extends SystemService final long ident = Binder.clearCallingIdentity(); try { - return getLastShutdownReasonInternal(new File(LAST_REBOOT_LOCATION)); + return getLastShutdownReasonInternal(LAST_REBOOT_PROPERTY); } finally { Binder.restoreCallingIdentity(ident); } @@ -4624,13 +4624,9 @@ public final class PowerManagerService extends SystemService } @VisibleForTesting - int getLastShutdownReasonInternal(File lastRebootReason) { - String line = ""; - try (BufferedReader bufferedReader = new BufferedReader(new FileReader(lastRebootReason))){ - line = bufferedReader.readLine(); - } catch (IOException e) { - Slog.e(TAG, "Failed to read last_reboot_reason file", e); - } + // lastRebootReasonProperty argument to permit testing + int getLastShutdownReasonInternal(String lastRebootReasonProperty) { + String line = SystemProperties.get(lastRebootReasonProperty); if (line == null) { return PowerManager.SHUTDOWN_REASON_UNKNOWN; } diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java index d0ca57a5073f..853e1b269c92 100644 --- a/services/core/java/com/android/server/power/ShutdownThread.java +++ b/services/core/java/com/android/server/power/ShutdownThread.java @@ -45,16 +45,16 @@ import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; import android.os.SystemVibrator; +import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.os.Vibrator; import android.os.storage.IStorageManager; import android.os.storage.IStorageShutdownObserver; +import android.util.ArrayMap; import android.util.Log; -import android.view.ViewGroup; +import android.util.TimingsTraceLog; import android.view.WindowManager; -import android.widget.ProgressBar; -import android.widget.TextView; import com.android.internal.telephony.ITelephony; import com.android.server.RescueParty; @@ -63,7 +63,9 @@ import com.android.server.pm.PackageManagerService; import com.android.server.statusbar.StatusBarManagerInternal; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; +import java.nio.charset.StandardCharsets; public final class ShutdownThread extends Thread { // constants @@ -108,6 +110,23 @@ public final class ShutdownThread extends Thread { .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) .build(); + // Metrics that will be reported to tron after reboot + private static final ArrayMap<String, Long> TRON_METRICS = new ArrayMap<>(); + + // File to use for save metrics + private static final String METRICS_FILE_BASENAME = "/data/system/shutdown-metrics"; + + // Metrics names to be persisted in shutdown-metrics file + private static String METRIC_SYSTEM_SERVER = "shutdown_system_server"; + private static String METRIC_SEND_BROADCAST = "shutdown_send_shutdown_broadcast"; + private static String METRIC_AM = "shutdown_activity_manager"; + private static String METRIC_PM = "shutdown_package_manager"; + private static String METRIC_RADIOS = "shutdown_radios"; + private static String METRIC_BT = "shutdown_bt"; + private static String METRIC_RADIO = "shutdown_radio"; + private static String METRIC_NFC = "shutdown_nfc"; + private static String METRIC_SM = "shutdown_storage_manager"; + private final Object mActionDoneSync = new Object(); private boolean mActionDone; private Context mContext; @@ -402,6 +421,10 @@ public final class ShutdownThread extends Thread { * Shuts off power regardless of radio and bluetooth state if the alloted time has passed. */ public void run() { + TimingsTraceLog shutdownTimingLog = newTimingsLog(); + shutdownTimingLog.traceBegin("SystemServerShutdown"); + metricStarted(METRIC_SYSTEM_SERVER); + BroadcastReceiver br = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // We don't allow apps to cancel this, so ignore the result. @@ -427,6 +450,8 @@ public final class ShutdownThread extends Thread { SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1"); } + metricStarted(METRIC_SEND_BROADCAST); + shutdownTimingLog.traceBegin("SendShutdownBroadcast"); Log.i(TAG, "Sending shutdown broadcast..."); // First send the high-level shut down broadcast. @@ -458,8 +483,12 @@ public final class ShutdownThread extends Thread { if (mRebootHasProgressBar) { sInstance.setRebootProgress(BROADCAST_STOP_PERCENT, null); } + shutdownTimingLog.traceEnd(); // SendShutdownBroadcast + metricEnded(METRIC_SEND_BROADCAST); Log.i(TAG, "Shutting down activity manager..."); + shutdownTimingLog.traceBegin("ShutdownActivityManager"); + metricStarted(METRIC_AM); final IActivityManager am = IActivityManager.Stub.asInterface(ServiceManager.checkService("activity")); @@ -472,8 +501,12 @@ public final class ShutdownThread extends Thread { if (mRebootHasProgressBar) { sInstance.setRebootProgress(ACTIVITY_MANAGER_STOP_PERCENT, null); } + shutdownTimingLog.traceEnd();// ShutdownActivityManager + metricEnded(METRIC_AM); Log.i(TAG, "Shutting down package manager..."); + shutdownTimingLog.traceBegin("ShutdownPackageManager"); + metricStarted(METRIC_PM); final PackageManagerService pm = (PackageManagerService) ServiceManager.getService("package"); @@ -483,12 +516,18 @@ public final class ShutdownThread extends Thread { if (mRebootHasProgressBar) { sInstance.setRebootProgress(PACKAGE_MANAGER_STOP_PERCENT, null); } + shutdownTimingLog.traceEnd(); // ShutdownPackageManager + metricEnded(METRIC_PM); // Shutdown radios. + shutdownTimingLog.traceBegin("ShutdownRadios"); + metricStarted(METRIC_RADIOS); shutdownRadios(MAX_RADIO_WAIT_TIME); if (mRebootHasProgressBar) { sInstance.setRebootProgress(RADIO_STOP_PERCENT, null); } + shutdownTimingLog.traceEnd(); // ShutdownRadios + metricEnded(METRIC_RADIOS); // Shutdown StorageManagerService to ensure media is in a safe state IStorageShutdownObserver observer = new IStorageShutdownObserver.Stub() { @@ -499,6 +538,8 @@ public final class ShutdownThread extends Thread { }; Log.i(TAG, "Shutting down StorageManagerService"); + shutdownTimingLog.traceBegin("ShutdownStorageManager"); + metricStarted(METRIC_SM); // Set initial variables and time out time. mActionDone = false; @@ -518,7 +559,7 @@ public final class ShutdownThread extends Thread { while (!mActionDone) { long delay = endShutTime - SystemClock.elapsedRealtime(); if (delay <= 0) { - Log.w(TAG, "Shutdown wait timed out"); + Log.w(TAG, "StorageManager shutdown wait timed out"); break; } else if (mRebootHasProgressBar) { int status = (int)((MAX_SHUTDOWN_WAIT_TIME - delay) * 1.0 * @@ -533,6 +574,9 @@ public final class ShutdownThread extends Thread { } } } + shutdownTimingLog.traceEnd(); // ShutdownStorageManager + metricEnded(METRIC_SM); + if (mRebootHasProgressBar) { sInstance.setRebootProgress(MOUNT_SERVICE_STOP_PERCENT, null); @@ -541,9 +585,29 @@ public final class ShutdownThread extends Thread { uncrypt(); } + shutdownTimingLog.traceEnd(); // SystemServerShutdown + metricEnded(METRIC_SYSTEM_SERVER); + saveMetrics(mReboot); rebootOrShutdown(mContext, mReboot, mReason); } + private static TimingsTraceLog newTimingsLog() { + return new TimingsTraceLog("ShutdownTiming", Trace.TRACE_TAG_SYSTEM_SERVER); + } + + private static void metricStarted(String metricKey) { + synchronized (TRON_METRICS) { + TRON_METRICS.put(metricKey, -1 * SystemClock.elapsedRealtime()); + } + } + + private static void metricEnded(String metricKey) { + synchronized (TRON_METRICS) { + TRON_METRICS + .put(metricKey, SystemClock.elapsedRealtime() + TRON_METRICS.get(metricKey)); + } + } + private void setRebootProgress(final int progress, final CharSequence message) { mHandler.post(new Runnable() { @Override @@ -565,6 +629,7 @@ public final class ShutdownThread extends Thread { final boolean[] done = new boolean[1]; Thread t = new Thread() { public void run() { + TimingsTraceLog shutdownTimingsTraceLog = newTimingsLog(); boolean nfcOff; boolean bluetoothReadyForShutdown; boolean radioOff; @@ -576,12 +641,12 @@ public final class ShutdownThread extends Thread { final IBluetoothManager bluetooth = IBluetoothManager.Stub.asInterface(ServiceManager.checkService( BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE)); - try { nfcOff = nfc == null || nfc.getState() == NfcAdapter.STATE_OFF; if (!nfcOff) { Log.w(TAG, "Turning off NFC..."); + metricStarted(METRIC_NFC); nfc.disable(false); // Don't persist new state } } catch (RemoteException ex) { @@ -594,6 +659,7 @@ public final class ShutdownThread extends Thread { bluetooth.getState() == BluetoothAdapter.STATE_OFF; if (!bluetoothReadyForShutdown) { Log.w(TAG, "Disabling Bluetooth..."); + metricStarted(METRIC_BT); bluetooth.disable(mContext.getPackageName(), false); // disable but don't persist new state } } catch (RemoteException ex) { @@ -605,6 +671,7 @@ public final class ShutdownThread extends Thread { radioOff = phone == null || !phone.needMobileRadioShutdown(); if (!radioOff) { Log.w(TAG, "Turning off cellular radios..."); + metricStarted(METRIC_RADIO); phone.shutdownMobileRadios(); } } catch (RemoteException ex) { @@ -637,6 +704,9 @@ public final class ShutdownThread extends Thread { } if (bluetoothReadyForShutdown) { Log.i(TAG, "Bluetooth turned off."); + metricEnded(METRIC_BT); + shutdownTimingsTraceLog + .logDuration("ShutdownBt", TRON_METRICS.get(METRIC_BT)); } } if (!radioOff) { @@ -648,6 +718,9 @@ public final class ShutdownThread extends Thread { } if (radioOff) { Log.i(TAG, "Radio turned off."); + metricEnded(METRIC_RADIO); + shutdownTimingsTraceLog + .logDuration("ShutdownRadio", TRON_METRICS.get(METRIC_RADIO)); } } if (!nfcOff) { @@ -659,6 +732,9 @@ public final class ShutdownThread extends Thread { } if (nfcOff) { Log.i(TAG, "NFC turned off."); + metricEnded(METRIC_NFC); + shutdownTimingsTraceLog + .logDuration("ShutdownNfc", TRON_METRICS.get(METRIC_NFC)); } } @@ -686,7 +762,7 @@ public final class ShutdownThread extends Thread { /** * Do not call this directly. Use {@link #reboot(Context, String, boolean)} - * or {@link #shutdown(Context, boolean)} instead. + * or {@link #shutdown(Context, String, boolean)} instead. * * @param context Context used to vibrate or null without vibration * @param reboot true to reboot or false to shutdown @@ -714,12 +790,38 @@ public final class ShutdownThread extends Thread { } catch (InterruptedException unused) { } } - // Shutdown power Log.i(TAG, "Performing low-level shutdown..."); PowerManagerService.lowLevelShutdown(reason); } + private static void saveMetrics(boolean reboot) { + StringBuilder metricValue = new StringBuilder(); + metricValue.append("reboot:"); + metricValue.append(reboot ? "y" : "n"); + final int metricsSize = TRON_METRICS.size(); + for (int i = 0; i < metricsSize; i++) { + final String name = TRON_METRICS.keyAt(i); + final long value = TRON_METRICS.valueAt(i); + if (value < 0) { + Log.e(TAG, "metricEnded wasn't called for " + name); + continue; + } + metricValue.append(',').append(name).append(':').append(value); + } + File tmp = new File(METRICS_FILE_BASENAME + ".tmp"); + boolean saved = false; + try (FileOutputStream fos = new FileOutputStream(tmp)) { + fos.write(metricValue.toString().getBytes(StandardCharsets.UTF_8)); + saved = true; + } catch (IOException e) { + Log.e(TAG,"Cannot save shutdown metrics", e); + } + if (saved) { + tmp.renameTo(new File(METRICS_FILE_BASENAME + ".txt")); + } + } + private void uncrypt() { Log.i(TAG, "Calling uncrypt and monitoring the progress..."); diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java index 866fdadc54d7..0884678478f6 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java @@ -80,6 +80,13 @@ public interface StatusBarManagerInternal { void setGlobalActionsListener(GlobalActionsListener listener); void showGlobalActions(); + /** + * Set whether the top app currently hides the statusbar. + * + * @param hidesStatusBar whether it is being hidden + */ + void setTopAppHidesStatusBar(boolean hidesStatusBar); + boolean showShutdownUi(boolean isReboot, String requestString); public interface GlobalActionsListener { diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index d31c2304f460..34ac645c4cf2 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -332,6 +332,15 @@ public class StatusBarManagerService extends IStatusBarService.Stub { } @Override + public void setTopAppHidesStatusBar(boolean hidesStatusBar) { + if (mBar != null) { + try { + mBar.setTopAppHidesStatusBar(hidesStatusBar); + } catch (RemoteException ex) {} + } + } + + @Override public boolean showShutdownUi(boolean isReboot, String reason) { if (!mContext.getResources().getBoolean(R.bool.config_showSysuiShutdown)) { return false; diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java index b6b964b050e3..1f0b2f000be1 100644 --- a/services/core/java/com/android/server/vr/VrManagerService.java +++ b/services/core/java/com/android/server/vr/VrManagerService.java @@ -74,6 +74,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.StringBuilder; import java.text.SimpleDateFormat; +import java.util.Arrays; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; @@ -414,7 +415,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC @Override public void registerListener(IVrStateCallbacks cb) { - enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER); + enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER, + Manifest.permission.ACCESS_VR_STATE); if (cb == null) { throw new IllegalArgumentException("Callback binder object is null."); } @@ -424,7 +426,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC @Override public void unregisterListener(IVrStateCallbacks cb) { - enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER); + enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER, + Manifest.permission.ACCESS_VR_STATE); if (cb == null) { throw new IllegalArgumentException("Callback binder object is null."); } @@ -434,7 +437,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC @Override public void registerPersistentVrStateListener(IPersistentVrStateCallbacks cb) { - enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER); + enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER, + Manifest.permission.ACCESS_VR_STATE); if (cb == null) { throw new IllegalArgumentException("Callback binder object is null."); } @@ -444,7 +448,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC @Override public void unregisterPersistentVrStateListener(IPersistentVrStateCallbacks cb) { - enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER); + enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER, + Manifest.permission.ACCESS_VR_STATE); if (cb == null) { throw new IllegalArgumentException("Callback binder object is null."); } @@ -454,19 +459,28 @@ public class VrManagerService extends SystemService implements EnabledComponentC @Override public boolean getVrModeState() { + enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER, + Manifest.permission.ACCESS_VR_STATE); return VrManagerService.this.getVrMode(); } @Override + public boolean getPersistentVrModeEnabled() { + enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER, + Manifest.permission.ACCESS_VR_STATE); + return VrManagerService.this.getPersistentVrMode(); + } + + @Override public void setPersistentVrModeEnabled(boolean enabled) { - enforceCallerPermission(Manifest.permission.RESTRICTED_VR_ACCESS); + enforceCallerPermissionAnyOf(Manifest.permission.RESTRICTED_VR_ACCESS); VrManagerService.this.setPersistentVrModeEnabled(enabled); } @Override public void setVr2dDisplayProperties( Vr2dDisplayProperties vr2dDisplayProp) { - enforceCallerPermission(Manifest.permission.RESTRICTED_VR_ACCESS); + enforceCallerPermissionAnyOf(Manifest.permission.RESTRICTED_VR_ACCESS); VrManagerService.this.setVr2dDisplayProperties(vr2dDisplayProp); } @@ -530,11 +544,21 @@ public class VrManagerService extends SystemService implements EnabledComponentC }; - private void enforceCallerPermission(String permission) { - if (mContext.checkCallingOrSelfPermission(permission) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Caller does not hold the permission " + permission); + /** + * Enforces that at lease one of the specified permissions is held by the caller. + * Throws SecurityException if none of the specified permissions are held. + * + * @param permissions One or more permissions to check against. + */ + private void enforceCallerPermissionAnyOf(String... permissions) { + for (String permission : permissions) { + if (mContext.checkCallingOrSelfPermission(permission) + == PackageManager.PERMISSION_GRANTED) { + return; + } } + throw new SecurityException("Caller does not hold at least one of the permissions: " + + Arrays.toString(permissions)); } /** @@ -1204,4 +1228,10 @@ public class VrManagerService extends SystemService implements EnabledComponentC return mVrModeEnabled; } } + + private boolean getPersistentVrMode() { + synchronized (mLock) { + return mPersistentVrModeEnabled; + } + } } diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index 2fad7b1a4a72..b963561dfd3c 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -280,14 +280,6 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { Slog.v(TAG, "Crop done; invoking completion callback"); } wallpaper.imageWallpaperPending = false; - if (wallpaper.setComplete != null) { - try { - wallpaper.setComplete.onWallpaperChanged(); - } catch (RemoteException e) { - // if this fails we don't really care; the setting app may just - // have crashed and that sort of thing is a fact of life. - } - } if (sysWallpaperChanged) { // If this was the system wallpaper, rebind... bindWallpaperComponentLocked(mImageWallpaper, true, @@ -311,6 +303,16 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { } saveSettingsLocked(wallpaper.userId); + + // Publish completion *after* we've persisted the changes + if (wallpaper.setComplete != null) { + try { + wallpaper.setComplete.onWallpaperChanged(); + } catch (RemoteException e) { + // if this fails we don't really care; the setting app may just + // have crashed and that sort of thing is a fact of life. + } + } } } } @@ -1606,8 +1608,12 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { @Override public ParcelFileDescriptor getWallpaper(String callingPkg, IWallpaperManagerCallback cb, final int which, Bundle outParams, int wallpaperUserId) { - enforceCallingOrSelfPermissionAndAppOp(android.Manifest.permission.READ_EXTERNAL_STORAGE, - callingPkg, Binder.getCallingUid(), "read wallpaper"); + final int hasPrivilege = mContext.checkCallingOrSelfPermission( + android.Manifest.permission.READ_WALLPAPER_INTERNAL); + if (hasPrivilege != PackageManager.PERMISSION_GRANTED) { + enforceCallingOrSelfPermissionAndAppOp(android.Manifest.permission.READ_EXTERNAL_STORAGE, + callingPkg, Binder.getCallingUid(), "read wallpaper"); + } wallpaperUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), wallpaperUserId, false, true, "getWallpaper", null); diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index 805250ad96d4..6484a13d8c3e 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -429,6 +429,8 @@ final class AccessibilityController { } public void getMagnificationRegionLocked(Region outMagnificationRegion) { + // Make sure we're working with the most current bounds + mMagnifedViewport.recomputeBoundsLocked(); mMagnifedViewport.getMagnificationRegionLocked(outMagnificationRegion); } diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index cda3efdf886f..c19ede0c0f4c 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -47,6 +47,8 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM; +import static com.android.server.wm.proto.AppTransitionProto.APP_TRANSITION_STATE; +import static com.android.server.wm.proto.AppTransitionProto.LAST_USED_APP_TRANSITION; import android.annotation.Nullable; import android.app.ActivityManager; @@ -65,6 +67,7 @@ import android.os.SystemProperties; import android.util.ArraySet; import android.util.Slog; import android.util.SparseArray; +import android.util.proto.ProtoOutputStream; import android.view.AppTransitionAnimationSpec; import android.view.IAppTransitionAnimationSpecsFuture; import android.view.WindowManager; @@ -1975,6 +1978,13 @@ public class AppTransition implements Dump { } } + void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + proto.write(APP_TRANSITION_STATE, mAppTransitionState); + proto.write(LAST_USED_APP_TRANSITION, mLastUsedAppTransition); + proto.end(token); + } + @Override public void dump(PrintWriter pw, String prefix) { pw.print(prefix); pw.println(this); diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java index ddbbde1eb421..c76b90593ab3 100644 --- a/services/core/java/com/android/server/wm/AppWindowAnimator.java +++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java @@ -16,8 +16,8 @@ package com.android.server.wm; +import static android.view.Display.INVALID_DISPLAY; import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; - import static com.android.server.wm.AppTransition.TRANSIT_UNSET; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; @@ -148,7 +148,7 @@ public class AppWindowAnimator { } // Start out animation gone if window is gone, or visible if window is visible. transformation.clear(); - transformation.setAlpha(mAppToken.hasContentToDisplay() ? 1 : 0); + transformation.setAlpha(mAppToken.isVisible() ? 1 : 0); hasTransformation = true; mStackClip = stackClip; @@ -172,7 +172,7 @@ public class AppWindowAnimator { animation = sDummyAnimation; hasTransformation = true; transformation.clear(); - transformation.setAlpha(mAppToken.hasContentToDisplay() ? 1 : 0); + transformation.setAlpha(mAppToken.isVisible() ? 1 : 0); } void setNullAnimation() { @@ -358,7 +358,7 @@ public class AppWindowAnimator { // This must be called while inside a transaction. boolean stepAnimationLocked(long currentTime) { - if (mService.okToAnimate()) { + if (mAppToken.okToAnimate()) { // We will run animations as long as the display isn't frozen. if (animation == sDummyAnimation) { @@ -423,8 +423,8 @@ public class AppWindowAnimator { if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + mAppToken + ": reportedVisible=" + mAppToken.reportedVisible - + " okToDisplay=" + mService.okToDisplay() - + " okToAnimate=" + mService.okToAnimate() + + " okToDisplay=" + mAppToken.okToDisplay() + + " okToAnimate=" + mAppToken.okToAnimate() + " startingDisplayed=" + mAppToken.startingDisplayed); transformation.clear(); @@ -450,7 +450,7 @@ public class AppWindowAnimator { return isAnimating; } - void dump(PrintWriter pw, String prefix, boolean dumpAll) { + void dump(PrintWriter pw, String prefix) { pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken); pw.print(prefix); pw.print("mAnimator="); pw.println(mAnimator); pw.print(prefix); pw.print("freezingScreen="); pw.print(freezingScreen); diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java index e9696d2ab46f..66e0a152e09b 100644 --- a/services/core/java/com/android/server/wm/AppWindowContainerController.java +++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java @@ -17,6 +17,7 @@ package com.android.server.wm; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; +import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import static com.android.server.wm.AppTransition.TRANSIT_DOCK_TASK_FROM_RECENTS; @@ -364,8 +365,6 @@ public class AppWindowContainerController // Now that the app is going invisible, we can remove it. It will be restarted // if made visible again. wtoken.removeDeadWindows(); - wtoken.setVisibleBeforeClientHidden(); - mService.mUnknownAppVisibilityController.appRemovedOrHidden(wtoken); } else { if (!mService.mAppTransition.isTransitionSet() && mService.mAppTransition.isReady()) { @@ -401,7 +400,7 @@ public class AppWindowContainerController // If we are preparing an app transition, then delay changing // the visibility of this token until we execute that transition. - if (mService.okToAnimate() && mService.mAppTransition.isTransitionSet()) { + if (wtoken.okToAnimate() && mService.mAppTransition.isTransitionSet()) { // A dummy animation is a placeholder animation which informs others that an // animation is going on (in this case an application transition). If the animation // was transferred from another application/animator, no dummy animator should be @@ -478,7 +477,7 @@ public class AppWindowContainerController // If the display is frozen, we won't do anything until the actual window is // displayed so there is no reason to put in the starting window. - if (!mService.okToDisplay()) { + if (!mContainer.okToDisplay()) { return false; } @@ -631,9 +630,12 @@ public class AppWindowContainerController mContainer.startingSurface = null; mContainer.startingWindow = null; mContainer.startingDisplayed = false; - if (surface == null && DEBUG_STARTING_WINDOW) { - Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't " - + "remove"); + if (surface == null) { + if (DEBUG_STARTING_WINDOW) { + Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't " + + "remove"); + } + return; } } else { if (DEBUG_STARTING_WINDOW) { @@ -699,16 +701,17 @@ public class AppWindowContainerController public void startFreezingScreen(int configChanges) { synchronized(mWindowMap) { - if (configChanges == 0 && mService.okToDisplay()) { - if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Skipping set freeze of " + mToken); - return; - } - if (mContainer == null) { Slog.w(TAG_WM, "Attempted to freeze screen with non-existing app token: " + mContainer); return; } + + if (configChanges == 0 && mContainer.okToDisplay()) { + if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Skipping set freeze of " + mToken); + return; + } + mContainer.startFreezingScreen(); } } @@ -724,35 +727,6 @@ public class AppWindowContainerController } } - /** - * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. - * In portrait mode, it grabs the full screenshot. - * - * @param displayId the Display to take a screenshot of. - * @param width the width of the target bitmap - * @param height the height of the target bitmap - * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1 - */ - public Bitmap screenshotApplications(int displayId, int width, int height, float frameScale) { - try { - Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotApplications"); - final DisplayContent dc; - synchronized(mWindowMap) { - dc = mRoot.getDisplayContentOrCreate(displayId); - if (dc == null) { - if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + mToken - + ": returning null. No Display for displayId=" + displayId); - return null; - } - } - return dc.screenshotApplications(mToken.asBinder(), width, height, - false /* includeFullDisplay */, frameScale, Bitmap.Config.RGB_565, - false /* wallpaperOnly */, false /* includeDecor */); - } finally { - Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); - } - } - void reportStartingWindowDrawn() { mHandler.sendMessage(mHandler.obtainMessage(H.NOTIFY_STARTING_WINDOW_DRAWN)); } diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 2e4de8c58650..f70035ca9c92 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -22,6 +22,7 @@ import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION; import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; +import static android.os.Build.VERSION_CODES.O_MR1; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD; import static android.view.WindowManager.LayoutParams.FLAG_SECURE; @@ -49,6 +50,8 @@ import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; import static com.android.server.wm.WindowManagerService.logWithStack; +import static com.android.server.wm.proto.AppWindowTokenProto.NAME; +import static com.android.server.wm.proto.AppWindowTokenProto.WINDOW_TOKEN; import android.annotation.NonNull; import android.app.Activity; @@ -57,11 +60,14 @@ import android.graphics.Rect; import android.os.Binder; import android.os.Debug; import android.os.IBinder; +import android.os.RemoteException; import android.os.SystemClock; import android.util.Slog; +import android.util.proto.ProtoOutputStream; import android.view.IApplicationToken; import android.view.SurfaceControl; import android.view.WindowManager; +import android.view.WindowManager.LayoutParams; import android.view.WindowManagerPolicy.StartingSurface; import com.android.internal.util.ToBooleanFunction; @@ -72,8 +78,6 @@ import java.io.PrintWriter; import java.util.ArrayDeque; import java.util.ArrayList; -import static android.os.Build.VERSION_CODES.O; - class AppTokenList extends ArrayList<AppWindowToken> { } @@ -120,14 +124,6 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree // case do not clear allDrawn until the animation completes. boolean deferClearAllDrawn; - /** - * These are to track the app's real drawing status if there were no saved surfaces. - * @see #updateDrawnWindowStates - */ - boolean allDrawnExcludingSaved; - private int mNumInterestingWindowsExcludingSaved; - private int mNumDrawnWindowsExcludingSaved; - // Is this window's surface needed? This is almost like hidden, except // it will sometimes be true a little earlier: when the token has // been shown, but is still waiting for its app transition to execute @@ -366,10 +362,10 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree boolean runningAppAnimation = false; + if (mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { + mAppAnimator.setNullAnimation(); + } if (transit != AppTransition.TRANSIT_UNSET) { - if (mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { - mAppAnimator.setNullAnimation(); - } if (mService.applyAnimationLocked(this, lp, transit, visible, isVoiceInteraction)) { delayed = runningAppAnimation = true; } @@ -470,6 +466,20 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree return delayed; } + /** + * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns + * true. + */ + WindowState getTopFullscreenWindow() { + for (int i = mChildren.size() - 1; i >= 0; i--) { + final WindowState win = mChildren.get(i); + if (win != null && win.mAttrs.isFullscreen()) { + return win; + } + } + return null; + } + WindowState findMainWindow() { WindowState candidate = null; int j = mChildren.size(); @@ -494,7 +504,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } boolean windowsAreFocusable() { - return StackId.canReceiveKeys(getTask().mStack.mStackId) || mAlwaysFocusable; + return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable; } AppWindowContainerController getController() { @@ -670,107 +680,9 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } } - /** - * Checks whether we should save surfaces for this app. - * - * @return true if the surfaces should be saved, false otherwise. - */ - boolean shouldSaveSurface() { - // We want to save surface if the app's windows are "allDrawn". - // (If we started entering animation early with saved surfaces, allDrawn - // should have been restored to true. So we'll save again in that case - // even if app didn't actually finish drawing.) - return allDrawn; - } - - private boolean canRestoreSurfaces() { - for (int i = mChildren.size() -1; i >= 0; i--) { - final WindowState w = mChildren.get(i); - if (w.canRestoreSurface()) { - return true; - } - } - return false; - } - - private void clearWasVisibleBeforeClientHidden() { - for (int i = mChildren.size() - 1; i >= 0; i--) { - final WindowState w = mChildren.get(i); - w.clearWasVisibleBeforeClientHidden(); - } - } - - /** - * Whether the app has some window that is invisible in layout, but - * animating with saved surface. - */ - boolean isAnimatingInvisibleWithSavedSurface() { - for (int i = mChildren.size() - 1; i >= 0; i--) { - final WindowState w = mChildren.get(i); - if (w.isAnimatingInvisibleWithSavedSurface()) { - return true; - } - } - return false; - } - - /** - * Hide all window surfaces that's still invisible in layout but animating - * with a saved surface, and mark them destroying. - */ - void stopUsingSavedSurfaceLocked() { - for (int i = mChildren.size() - 1; i >= 0; i--) { - final WindowState w = mChildren.get(i); - w.stopUsingSavedSurface(); - } - destroySurfaces(); - } - - void markSavedSurfaceExiting() { - for (int i = mChildren.size() - 1; i >= 0; i--) { - final WindowState w = mChildren.get(i); - w.markSavedSurfaceExiting(); - } - } - - void restoreSavedSurfaceForInterestingWindows() { - if (!canRestoreSurfaces()) { - clearWasVisibleBeforeClientHidden(); - return; - } - - // Check if all interesting windows are drawn and we can mark allDrawn=true. - int interestingNotDrawn = -1; - - for (int i = mChildren.size() - 1; i >= 0; i--) { - final WindowState w = mChildren.get(i); - interestingNotDrawn = w.restoreSavedSurfaceForInterestingWindow(); - } - - if (!allDrawn) { - allDrawn = (interestingNotDrawn == 0); - if (allDrawn) { - mService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget(); - } - } - clearWasVisibleBeforeClientHidden(); - - if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.d(TAG, - "restoreSavedSurfaceForInterestingWindows: " + this + " allDrawn=" + allDrawn - + " interestingNotDrawn=" + interestingNotDrawn); - } - - void destroySavedSurfaces() { - for (int i = mChildren.size() - 1; i >= 0; i--) { - final WindowState win = mChildren.get(i); - win.destroySavedSurface(); - } - } - void clearAllDrawn() { allDrawn = false; deferClearAllDrawn = false; - allDrawnExcludingSaved = false; } Task getTask() { @@ -1293,11 +1205,11 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree */ @Override int getOrientation(int candidate) { - // We do not allow non-fullscreen apps to influence orientation beyond O. While we do - // throw an exception in {@link Activity#onCreate} and + // We do not allow non-fullscreen apps to influence orientation starting in O-MR1. While we + // do throw an exception in {@link Activity#onCreate} and // {@link Activity#setRequestedOrientation}, we also ignore the orientation here so that // other calculations aren't affected. - if (!fillsParent() && mTargetSdk > O) { + if (!fillsParent() && mTargetSdk >= O_MR1) { // Can't specify orientation if app doesn't fill parent. return SCREEN_ORIENTATION_UNSET; } @@ -1368,8 +1280,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree private boolean allDrawnStatesConsidered() { for (int i = mChildren.size() - 1; i >= 0; --i) { final WindowState child = mChildren.get(i); - if (child.mightAffectAllDrawn(false /*visibleOnly*/ ) - && !child.getDrawnStateEvaluated()) { + if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) { return false; } } @@ -1409,23 +1320,6 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } } } - - if (!allDrawnExcludingSaved) { - int numInteresting = mNumInterestingWindowsExcludingSaved; - if (numInteresting > 0 && mNumDrawnWindowsExcludingSaved >= numInteresting) { - if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawnExcludingSaved: " + this - + " interesting=" + numInteresting - + " drawn=" + mNumDrawnWindowsExcludingSaved); - allDrawnExcludingSaved = true; - if (mDisplayContent != null) { - mDisplayContent.setLayoutNeeded(); - } - if (isAnimatingInvisibleWithSavedSurface() - && !mService.mFinishedEarlyAnim.contains(this)) { - mService.mFinishedEarlyAnim.add(this); - } - } - } } /** @@ -1442,15 +1336,13 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree + " allDrawn=" + allDrawn + " freezingScreen=" + mAppAnimator.freezingScreen); } - if (allDrawn && allDrawnExcludingSaved && !mAppAnimator.freezingScreen) { + if (allDrawn && !mAppAnimator.freezingScreen) { return false; } if (mLastTransactionSequence != mService.mTransactionSequence) { mLastTransactionSequence = mService.mTransactionSequence; mNumInterestingWindows = mNumDrawnWindows = 0; - mNumInterestingWindowsExcludingSaved = 0; - mNumDrawnWindowsExcludingSaved = 0; startingDisplayed = false; } @@ -1458,7 +1350,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree boolean isInterestingAndDrawn = false; - if (!allDrawn && w.mightAffectAllDrawn(false /* visibleOnly */)) { + if (!allDrawn && w.mightAffectAllDrawn()) { if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) { Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() + ", isAnimationSet=" + winAnimator.isAnimationSet()); @@ -1493,23 +1385,6 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } } - if (!allDrawnExcludingSaved && w.mightAffectAllDrawn(true /* visibleOnly */)) { - if (w != startingWindow && w.isInteresting()) { - mNumInterestingWindowsExcludingSaved++; - if (w.isDrawnLw() && !w.isAnimatingWithSavedSurface()) { - mNumDrawnWindowsExcludingSaved++; - - if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG, - "tokenMayBeDrawnExcludingSaved: " + this + " w=" + w - + " numInteresting=" + mNumInterestingWindowsExcludingSaved - + " freezingScreen=" + mAppAnimator.freezingScreen - + " mAppFreezing=" + w.mAppFreezing); - - isInterestingAndDrawn = true; - } - } - } - return isInterestingAndDrawn; } @@ -1743,6 +1618,29 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree if (mRemovingFromDisplay) { pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay); } + if (mAppAnimator.isAnimating()) { + mAppAnimator.dump(pw, prefix + " "); + } + } + + @Override + void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + writeNameToProto(proto, NAME); + super.writeToProto(proto, WINDOW_TOKEN); + proto.end(token); + } + + void writeNameToProto(ProtoOutputStream proto, long fieldId) { + if (appToken == null) { + return; + } + try { + proto.write(fieldId, appToken.getName()); + } catch (RemoteException e) { + // This shouldn't happen, but in this case fall back to outputting nothing + Slog.e(TAG, e.toString()); + } } @Override diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java index cff2fadd7649..7953ee430934 100644 --- a/services/core/java/com/android/server/wm/BoundsAnimationController.java +++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java @@ -21,7 +21,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.animation.AnimationHandler; -import android.animation.AnimationHandler.AnimationFrameCallbackProvider; import android.animation.Animator; import android.animation.ValueAnimator; import android.annotation.IntDef; @@ -32,13 +31,11 @@ import android.os.IBinder; import android.os.Debug; import android.util.ArrayMap; import android.util.Slog; -import android.view.Choreographer; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; import android.view.WindowManagerInternal; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -142,9 +139,6 @@ public class BoundsAnimationController { // True if this this animation was canceled and will be replaced the another animation from // the same {@link #BoundsAnimationTarget} target. private boolean mSkipFinalResize; - // True if this animation replaced a previous animation of the same - // {@link #BoundsAnimationTarget} target. - private final boolean mSkipAnimationStart; // True if this animation was canceled by the user, not as a part of a replacing animation private boolean mSkipAnimationEnd; @@ -159,6 +153,7 @@ public class BoundsAnimationController { // Whether to schedule PiP mode changes on animation start/end private @SchedulePipModeChangedState int mSchedulePipModeChangedState; + private @SchedulePipModeChangedState int mPrevSchedulePipModeChangedState; // Depending on whether we are animating from // a smaller to a larger size @@ -171,14 +166,14 @@ public class BoundsAnimationController { BoundsAnimator(BoundsAnimationTarget target, Rect from, Rect to, @SchedulePipModeChangedState int schedulePipModeChangedState, - boolean moveFromFullscreen, boolean moveToFullscreen, - boolean replacingExistingAnimation) { + @SchedulePipModeChangedState int prevShedulePipModeChangedState, + boolean moveFromFullscreen, boolean moveToFullscreen) { super(); mTarget = target; mFrom.set(from); mTo.set(to); - mSkipAnimationStart = replacingExistingAnimation; mSchedulePipModeChangedState = schedulePipModeChangedState; + mPrevSchedulePipModeChangedState = prevShedulePipModeChangedState; mMoveFromFullscreen = moveFromFullscreen; mMoveToFullscreen = moveToFullscreen; addUpdateListener(this); @@ -200,7 +195,7 @@ public class BoundsAnimationController { @Override public void onAnimationStart(Animator animation) { if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget - + " mSkipAnimationStart=" + mSkipAnimationStart + + " mPrevSchedulePipModeChangedState=" + mPrevSchedulePipModeChangedState + " mSchedulePipModeChangedState=" + mSchedulePipModeChangedState); mFinishAnimationAfterTransition = false; mTmpRect.set(mFrom.left, mFrom.top, mFrom.left + mFrozenTaskWidth, @@ -210,18 +205,26 @@ public class BoundsAnimationController { // running updateBooster(); - // Ensure that we have prepared the target for animation before - // we trigger any size changes, so it can swap surfaces - // in to appropriate modes, or do as it wishes otherwise. - if (!mSkipAnimationStart) { + // Ensure that we have prepared the target for animation before we trigger any size + // changes, so it can swap surfaces in to appropriate modes, or do as it wishes + // otherwise. + if (mPrevSchedulePipModeChangedState == NO_PIP_MODE_CHANGED_CALLBACKS) { mTarget.onAnimationStart(mSchedulePipModeChangedState == - SCHEDULE_PIP_MODE_CHANGED_ON_START); + SCHEDULE_PIP_MODE_CHANGED_ON_START, false /* forceUpdate */); // When starting an animation from fullscreen, pause here and wait for the // windows-drawn signal before we start the rest of the transition down into PiP. if (mMoveFromFullscreen) { pause(); } + } else if (mPrevSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_END && + mSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_START) { + // We are replacing a running animation into PiP, but since it hasn't completed, the + // client will not currently receive any picture-in-picture mode change callbacks. + // However, we still need to report to them that they are leaving PiP, so this will + // force an update via a mode changed callback. + mTarget.onAnimationStart(true /* schedulePipModeChangedCallback */, + true /* forceUpdate */); } // Immediately update the task bounds if they have to become larger, but preserve @@ -388,6 +391,8 @@ public class BoundsAnimationController { boolean moveFromFullscreen, boolean moveToFullscreen) { final BoundsAnimator existing = mRunningAnimations.get(target); final boolean replacing = existing != null; + @SchedulePipModeChangedState int prevSchedulePipModeChangedState = + NO_PIP_MODE_CHANGED_CALLBACKS; if (DEBUG) Slog.d(TAG, "animateBounds: target=" + target + " from=" + from + " to=" + to + " schedulePipModeChangedState=" + schedulePipModeChangedState @@ -403,6 +408,9 @@ public class BoundsAnimationController { return existing; } + // Save the previous state + prevSchedulePipModeChangedState = existing.mSchedulePipModeChangedState; + // Update the PiP callback states if we are replacing the animation if (existing.mSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_START) { if (schedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_START) { @@ -428,7 +436,8 @@ public class BoundsAnimationController { existing.cancel(); } final BoundsAnimator animator = new BoundsAnimator(target, from, to, - schedulePipModeChangedState, moveFromFullscreen, moveToFullscreen, replacing); + schedulePipModeChangedState, prevSchedulePipModeChangedState, + moveFromFullscreen, moveToFullscreen); mRunningAnimations.put(target, animator); animator.setFloatValues(0f, 1f); animator.setDuration((animationDuration != -1 ? animationDuration diff --git a/services/core/java/com/android/server/wm/BoundsAnimationTarget.java b/services/core/java/com/android/server/wm/BoundsAnimationTarget.java index 8b1bf7bf77dc..647a2d6deac6 100644 --- a/services/core/java/com/android/server/wm/BoundsAnimationTarget.java +++ b/services/core/java/com/android/server/wm/BoundsAnimationTarget.java @@ -31,7 +31,7 @@ interface BoundsAnimationTarget { * @param schedulePipModeChangedCallback whether or not to schedule the PiP mode changed * callbacks */ - void onAnimationStart(boolean schedulePipModeChangedCallback); + void onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate); /** * Sets the size of the target (without any intermediate steps, like scheduling animation) diff --git a/services/core/java/com/android/server/am/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java index 3d60681cfd71..21b67f1f9821 100644 --- a/services/core/java/com/android/server/am/ConfigurationContainer.java +++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 The Android Open Source Project + * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,17 +14,23 @@ * limitations under the License */ -package com.android.server.am; +package com.android.server.wm; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import static android.app.WindowConfiguration.activityTypeToString; + +import android.app.WindowConfiguration; import android.content.res.Configuration; /** * Contains common logic for classes that have override configurations and are organized in a * hierarchy. */ -// TODO(b/36505427): Move to wm package and have WindowContainer use this instead of having its own -// implementation for merging configuration. -abstract class ConfigurationContainer<E extends ConfigurationContainer> { +public abstract class ConfigurationContainer<E extends ConfigurationContainer> { /** Contains override configuration settings applied to this configuration container. */ private Configuration mOverrideConfiguration = new Configuration(); @@ -42,12 +48,15 @@ abstract class ConfigurationContainer<E extends ConfigurationContainer> { */ private Configuration mMergedOverrideConfiguration = new Configuration(); + // TODO: Can't have ag/2592611 soon enough! + private final Configuration mTmpConfig = new Configuration(); + /** * Returns full configuration applied to this configuration container. * This method should be used for getting settings applied in each particular level of the * hierarchy. */ - Configuration getConfiguration() { + public Configuration getConfiguration() { return mFullConfiguration; } @@ -55,7 +64,7 @@ abstract class ConfigurationContainer<E extends ConfigurationContainer> { * Notify that parent config changed and we need to update full configuration. * @see #mFullConfiguration */ - void onConfigurationChanged(Configuration newParentConfig) { + public void onConfigurationChanged(Configuration newParentConfig) { mFullConfiguration.setTo(newParentConfig); mFullConfiguration.updateFrom(mOverrideConfiguration); for (int i = getChildCount() - 1; i >= 0; --i) { @@ -65,7 +74,7 @@ abstract class ConfigurationContainer<E extends ConfigurationContainer> { } /** Returns override configuration applied to this configuration container. */ - Configuration getOverrideConfiguration() { + public Configuration getOverrideConfiguration() { return mOverrideConfiguration; } @@ -74,7 +83,7 @@ abstract class ConfigurationContainer<E extends ConfigurationContainer> { * @see #mOverrideConfiguration * @see #mFullConfiguration */ - void onOverrideConfigurationChanged(Configuration overrideConfiguration) { + public void onOverrideConfigurationChanged(Configuration overrideConfiguration) { mOverrideConfiguration.setTo(overrideConfiguration); // Update full configuration of this container and all its children. final ConfigurationContainer parent = getParent(); @@ -87,7 +96,7 @@ abstract class ConfigurationContainer<E extends ConfigurationContainer> { * Get merged override configuration from the top of the hierarchy down to this particular * instance. This should be reported to client as override config. */ - Configuration getMergedOverrideConfiguration() { + public Configuration getMergedOverrideConfiguration() { return mMergedOverrideConfiguration; } @@ -97,7 +106,7 @@ abstract class ConfigurationContainer<E extends ConfigurationContainer> { * override config. * @see #mMergedOverrideConfiguration */ - private void onMergedOverrideConfigurationChanged() { + void onMergedOverrideConfigurationChanged() { final ConfigurationContainer parent = getParent(); if (parent != null) { mMergedOverrideConfiguration.setTo(parent.getMergedOverrideConfiguration()); @@ -111,10 +120,72 @@ abstract class ConfigurationContainer<E extends ConfigurationContainer> { } } + public WindowConfiguration getWindowConfiguration() { + return mFullConfiguration.windowConfiguration; + } + + /** Returns the windowing mode the configuration container is currently in. */ + public int getWindowingMode() { + return mFullConfiguration.windowConfiguration.getWindowingMode(); + } + + /** Sets the windowing mode for the configuration container. */ + public void setWindowingMode(/*@WindowConfiguration.WindowingMode*/ int windowingMode) { + mTmpConfig.setTo(getOverrideConfiguration()); + mTmpConfig.windowConfiguration.setWindowingMode(windowingMode); + onOverrideConfigurationChanged(mTmpConfig); + } + + /** Returns the activity type associated with the the configuration container. */ + /*@WindowConfiguration.ActivityType*/ + public int getActivityType() { + return mFullConfiguration.windowConfiguration.getActivityType(); + } + + /** Sets the activity type to associate with the configuration container. */ + public void setActivityType(/*@WindowConfiguration.ActivityType*/ int activityType) { + int currentActivityType = getActivityType(); + if (currentActivityType == activityType) { + return; + } + if (currentActivityType != ACTIVITY_TYPE_UNDEFINED) { + throw new IllegalStateException("Can't change activity type once set: " + this + + " activityType=" + activityTypeToString(activityType)); + } + mTmpConfig.setTo(getOverrideConfiguration()); + mTmpConfig.windowConfiguration.setActivityType(activityType); + onOverrideConfigurationChanged(mTmpConfig); + } + + public boolean isActivityTypeHome() { + return getActivityType() == ACTIVITY_TYPE_HOME; + } + + public boolean isActivityTypeRecents() { + return getActivityType() == ACTIVITY_TYPE_RECENTS; + } + + public boolean isActivityTypeAssistant() { + return getActivityType() == ACTIVITY_TYPE_ASSISTANT; + } + + public boolean isActivityTypeStandard() { + return getActivityType() == ACTIVITY_TYPE_STANDARD; + } + + public boolean hasCompatibleActivityType(ConfigurationContainer other) { + /*@WindowConfiguration.ActivityType*/ int thisType = getActivityType(); + /*@WindowConfiguration.ActivityType*/ int otherType = other.getActivityType(); + + return thisType == otherType + || thisType == ACTIVITY_TYPE_UNDEFINED + || otherType == ACTIVITY_TYPE_UNDEFINED; + } + /** * Must be called when new parent for the container was set. */ - void onParentChanged() { + protected void onParentChanged() { final ConfigurationContainer parent = getParent(); // Removing parent usually means that we've detached this entity to destroy it or to attach // to another parent. In both cases we don't need to update the configuration now. diff --git a/services/core/java/com/android/server/wm/DimLayerController.java b/services/core/java/com/android/server/wm/DimLayerController.java index 741492815bd7..6f9e45a66909 100644 --- a/services/core/java/com/android/server/wm/DimLayerController.java +++ b/services/core/java/com/android/server/wm/DimLayerController.java @@ -290,7 +290,7 @@ class DimLayerController { state.dimLayer.setLayer(dimLayer); } if (state.dimLayer.isAnimating()) { - if (!mDisplayContent.mService.okToAnimate()) { + if (!mDisplayContent.okToAnimate()) { // Jump to the end of the animation. state.dimLayer.show(); } else { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 5bc4a6b23392..d74e48253132 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -20,9 +20,12 @@ import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; import static android.app.ActivityManager.StackId.HOME_STACK_ID; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; +import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; +import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.FLAG_PRIVATE; import static android.view.Surface.ROTATION_0; @@ -57,6 +60,7 @@ import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; +import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_UNOCCLUDE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; @@ -97,9 +101,21 @@ import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP; import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING; import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW; import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE; +import static com.android.server.wm.proto.DisplayProto.ABOVE_APP_WINDOWS; +import static com.android.server.wm.proto.DisplayProto.BELOW_APP_WINDOWS; +import static com.android.server.wm.proto.DisplayProto.DISPLAY_INFO; +import static com.android.server.wm.proto.DisplayProto.DOCKED_STACK_DIVIDER_CONTROLLER; +import static com.android.server.wm.proto.DisplayProto.DPI; +import static com.android.server.wm.proto.DisplayProto.ID; +import static com.android.server.wm.proto.DisplayProto.IME_WINDOWS; +import static com.android.server.wm.proto.DisplayProto.PINNED_STACK_CONTROLLER; +import static com.android.server.wm.proto.DisplayProto.ROTATION; +import static com.android.server.wm.proto.DisplayProto.SCREEN_ROTATION_ANIMATION; +import static com.android.server.wm.proto.DisplayProto.STACKS; import android.annotation.NonNull; import android.app.ActivityManager.StackId; +import android.app.WindowConfiguration; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.Bitmap; @@ -118,6 +134,7 @@ import android.os.SystemClock; import android.util.DisplayMetrics; import android.util.MutableBoolean; import android.util.Slog; +import android.util.proto.ProtoOutputStream; import android.view.Display; import android.view.DisplayInfo; import android.view.InputDevice; @@ -1067,10 +1084,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } forAllWindows(w -> { - // Discard surface after orientation change, these can't be reused. - if (w.mAppToken != null) { - w.mAppToken.destroySavedSurfaces(); - } if (w.mHasSurface && !rotateSeamlessly) { if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w); w.setOrientationChanging(true); @@ -1181,8 +1194,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo final int dw = displayInfo.logicalWidth; final int dh = displayInfo.logicalHeight; - config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : - Configuration.ORIENTATION_LANDSCAPE; + config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE; + // TODO: Probably best to set this based on some setting in the display content object, + // so the display can be configured for things like fullscreen. + config.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN); config.screenWidthDp = (int)(mService.mPolicy.getConfigDisplayWidth(dw, dh, displayInfo.rotation, @@ -1195,8 +1210,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo final int leftInset = mTmpRect.left; final int topInset = mTmpRect.top; // appBounds at the root level should mirror the app screen size. - config.setAppBounds(leftInset /*left*/, topInset /*top*/, leftInset + displayInfo.appWidth /*right*/, - topInset + displayInfo.appHeight /*bottom*/); + config.windowConfiguration.setAppBounds(leftInset /* left */, topInset /* top */, + leftInset + displayInfo.appWidth /* right */, + topInset + displayInfo.appHeight /* bottom */); final boolean rotated = (displayInfo.rotation == Surface.ROTATION_90 || displayInfo.rotation == Surface.ROTATION_270); @@ -1445,7 +1461,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } @VisibleForTesting - int getStaskPosById(int stackId) { + int getStackPosById(int stackId) { for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { final TaskStack stack = mTaskStackContainers.get(i); if (stack.mStackId == stackId) { @@ -1456,7 +1472,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } @Override - void onConfigurationChanged(Configuration newParentConfig) { + public void onConfigurationChanged(Configuration newParentConfig) { super.onConfigurationChanged(newParentConfig); // The display size information is heavily dependent on the resources in the current @@ -1792,7 +1808,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mTmpTaskForResizePointSearchResult.reset(); for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { final TaskStack stack = mTaskStackContainers.get(stackNdx); - if (!StackId.isTaskResizeAllowed(stack.mStackId)) { + if (!stack.getWindowConfiguration().canResizeTask()) { return null; } @@ -2099,6 +2115,38 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } } + void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + proto.write(ID, mDisplayId); + for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) { + final TaskStack stack = mTaskStackContainers.get(stackNdx); + stack.writeToProto(proto, STACKS); + } + mDividerControllerLocked.writeToProto(proto, DOCKED_STACK_DIVIDER_CONTROLLER); + mPinnedStackControllerLocked.writeToProto(proto, PINNED_STACK_CONTROLLER); + for (int i = mAboveAppWindowsContainers.size() - 1; i >= 0; --i) { + final WindowToken windowToken = mAboveAppWindowsContainers.get(i); + windowToken.writeToProto(proto, ABOVE_APP_WINDOWS); + } + for (int i = mBelowAppWindowsContainers.size() - 1; i >= 0; --i) { + final WindowToken windowToken = mBelowAppWindowsContainers.get(i); + windowToken.writeToProto(proto, BELOW_APP_WINDOWS); + } + for (int i = mImeWindowsContainers.size() - 1; i >= 0; --i) { + final WindowToken windowToken = mImeWindowsContainers.get(i); + windowToken.writeToProto(proto, IME_WINDOWS); + } + proto.write(DPI, mBaseDisplayDensity); + mDisplayInfo.writeToProto(proto, DISPLAY_INFO); + proto.write(ROTATION, mRotation); + final ScreenRotationAnimation screenRotationAnimation = + mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId); + if (screenRotationAnimation != null) { + screenRotationAnimation.writeToProto(proto, SCREEN_ROTATION_ANIMATION); + } + proto.end(token); + } + public void dump(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId); final String subPrefix = " " + prefix; @@ -2125,8 +2173,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight); pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth); pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight); - pw.println(subPrefix + "deferred=" + mDeferredRemoval + pw.print(subPrefix + "deferred=" + mDeferredRemoval + " mLayoutNeeded=" + mLayoutNeeded); + pw.println(" mTouchExcludeRegion=" + mTouchExcludeRegion); pw.println(); pw.println(prefix + "Application tokens in top down Z order:"); @@ -2302,8 +2351,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } else if (w.mAppToken != null && w.mAppToken.isClientHidden()) { Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): " + w + " surface=" + wsa.mSurfaceController - + " token=" + w.mAppToken - + " saved=" + w.hasSavedSurface()); + + " token=" + w.mAppToken); if (SHOW_TRANSACTIONS) logSurface(w, "LEAK DESTROY", false); wsa.destroySurface(); mTmpWindow = w; @@ -3204,6 +3252,19 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mService.requestTraversal(); } + boolean okToDisplay() { + if (mDisplayId == DEFAULT_DISPLAY) { + return !mService.mDisplayFrozen + && mService.mDisplayEnabled && mService.mPolicy.isScreenOn(); + } + return mDisplayInfo.state == Display.STATE_ON; + } + + boolean okToAnimate() { + return okToDisplay() && + (mDisplayId != DEFAULT_DISPLAY || mService.mPolicy.okToAnimate()); + } + static final class TaskForResizePointSearchResult { boolean searchDone; Task taskForResize; @@ -3317,7 +3378,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo @Override void positionChildAt(int position, TaskStack child, boolean includingParents) { - if (StackId.isAlwaysOnTop(child.mStackId) && position != POSITION_TOP) { + if (child.getWindowConfiguration().isAlwaysOnTop() + && position != POSITION_TOP) { // This stack is always-on-top, override the default behavior. Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom"); @@ -3541,7 +3603,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED; - if (policy.isKeyguardShowingAndNotOccluded()) { + if (policy.isKeyguardShowingAndNotOccluded() + || mService.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) { return mLastKeyguardForcedOrientation; } diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java index 6b514552b227..030b986ef0e9 100644 --- a/services/core/java/com/android/server/wm/DockedStackDividerController.java +++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java @@ -34,6 +34,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerService.H.NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED; import static com.android.server.wm.WindowManagerService.LAYER_OFFSET_DIM; +import static com.android.server.wm.proto.DockedStackDividerControllerProto.MINIMIZED_DOCK; import android.content.Context; import android.content.res.Configuration; @@ -42,6 +43,7 @@ import android.os.RemoteCallbackList; import android.os.RemoteException; import android.util.ArraySet; import android.util.Slog; +import android.util.proto.ProtoOutputStream; import android.view.DisplayInfo; import android.view.IDockedStackListener; import android.view.animation.AnimationUtils; @@ -239,8 +241,8 @@ public class DockedStackDividerController implements DimLayerUser { final int leftInset = mTmpRect.left; final int topInset = mTmpRect.top; - config.setAppBounds(leftInset /*left*/, topInset /*top*/, leftInset + appWidth /*right*/, - topInset + appHeight /*bottom*/); + config.windowConfiguration.setAppBounds(leftInset /*left*/, topInset /*top*/, + leftInset + appWidth /*right*/, topInset + appHeight /*bottom*/); config.screenWidthDp = (int) (mService.mPolicy.getConfigDisplayWidth(dw, dh, rotation, baseConfig.uiMode, @@ -606,8 +608,7 @@ public class DockedStackDividerController implements DimLayerUser { final TaskStack fullscreenStack = mDisplayContent.getStackById(FULLSCREEN_WORKSPACE_STACK_ID); final boolean homeVisible = homeTask.getTopVisibleAppToken() != null; - final boolean homeBehind = (fullscreenStack != null && fullscreenStack.isVisible()) - || (homeStack.hasMultipleTaskWithHomeTaskNotTop()); + final boolean homeBehind = fullscreenStack != null && fullscreenStack.isVisible(); setMinimizedDockedStack(homeVisible && !homeBehind, animate); } @@ -919,4 +920,10 @@ public class DockedStackDividerController implements DimLayerUser { mDimLayer.printTo(prefix + " ", pw); } } + + void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + proto.write(MINIMIZED_DOCK, mMinimizedDock); + proto.end(token); + } } diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java index 6d33ce2941bc..1e7140a12d01 100644 --- a/services/core/java/com/android/server/wm/PinnedStackController.java +++ b/services/core/java/com/android/server/wm/PinnedStackController.java @@ -21,6 +21,8 @@ import static android.util.TypedValue.COMPLEX_UNIT_DIP; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; +import static com.android.server.wm.proto.PinnedStackControllerProto.DEFAULT_BOUNDS; +import static com.android.server.wm.proto.PinnedStackControllerProto.MOVEMENT_BOUNDS; import android.app.RemoteAction; import android.content.pm.ParceledListSlice; @@ -35,6 +37,7 @@ import android.util.Log; import android.util.Size; import android.util.Slog; import android.util.TypedValue; +import android.util.proto.ProtoOutputStream; import android.view.DisplayInfo; import android.view.Gravity; import android.view.IPinnedStackController; @@ -505,4 +508,12 @@ class PinnedStackController { pw.println(prefix + " ]"); } } + + void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + getDefaultBounds().writeToProto(proto, DEFAULT_BOUNDS); + mService.getStackBounds(PINNED_STACK_ID, mTmpRect); + getMovementBounds(mTmpRect).writeToProto(proto, MOVEMENT_BOUNDS); + proto.end(token); + } } diff --git a/services/core/java/com/android/server/wm/PinnedStackWindowController.java b/services/core/java/com/android/server/wm/PinnedStackWindowController.java index 989e8f23693a..b5c9b99b35d6 100644 --- a/services/core/java/com/android/server/wm/PinnedStackWindowController.java +++ b/services/core/java/com/android/server/wm/PinnedStackWindowController.java @@ -24,6 +24,7 @@ import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_ import static com.android.server.wm.BoundsAnimationController.SchedulePipModeChangedState; import android.app.RemoteAction; +import android.content.res.Configuration; import android.graphics.Rect; import com.android.server.UiThread; @@ -39,8 +40,9 @@ public class PinnedStackWindowController extends StackWindowController { private Rect mTmpToBounds = new Rect(); public PinnedStackWindowController(int stackId, PinnedStackWindowListener listener, - int displayId, boolean onTop, Rect outBounds) { - super(stackId, listener, displayId, onTop, outBounds, WindowManagerService.getInstance()); + int displayId, boolean onTop, Rect outBounds, Configuration overrideConfig) { + super(stackId, listener, displayId, onTop, outBounds, overrideConfig, + WindowManagerService.getInstance()); } /** @@ -202,10 +204,12 @@ public class PinnedStackWindowController extends StackWindowController { */ /** Calls directly into activity manager so window manager lock shouldn't held. */ - public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) { + public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds, + boolean forceUpdate) { if (mListener != null) { PinnedStackWindowListener listener = (PinnedStackWindowListener) mListener; - listener.updatePictureInPictureModeForPinnedStackAnimation(targetStackBounds); + listener.updatePictureInPictureModeForPinnedStackAnimation(targetStackBounds, + forceUpdate); } } } diff --git a/services/core/java/com/android/server/wm/PinnedStackWindowListener.java b/services/core/java/com/android/server/wm/PinnedStackWindowListener.java index 12b9c1f0c552..33e8a60329bf 100644 --- a/services/core/java/com/android/server/wm/PinnedStackWindowListener.java +++ b/services/core/java/com/android/server/wm/PinnedStackWindowListener.java @@ -28,5 +28,6 @@ public interface PinnedStackWindowListener extends StackWindowListener { * Called when the stack container pinned stack animation will change the picture-in-picture * mode. This is a direct call into ActivityManager. */ - default void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {} + default void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds, + boolean forceUpdate) {} } diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 7bcad9fd852f..54dd19961999 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -18,7 +18,6 @@ package com.android.server.wm; import android.content.res.Configuration; import android.graphics.Rect; -import android.hardware.display.DisplayManager; import android.hardware.power.V1_0.PowerHint; import android.os.Binder; import android.os.Debug; @@ -32,14 +31,15 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; +import android.util.ArraySet; import android.util.EventLog; import android.util.Slog; import android.util.SparseIntArray; +import android.util.proto.ProtoOutputStream; import android.view.Display; import android.view.DisplayInfo; import android.view.WindowManager; -import com.android.internal.os.SomeArgs; import com.android.internal.util.ArrayUtils; import com.android.server.EventLogTags; @@ -89,6 +89,8 @@ import static com.android.server.wm.WindowSurfacePlacer.SET_TURN_ON_SCREEN; import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION; import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING; import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE; +import static com.android.server.wm.proto.WindowManagerServiceProto.DISPLAYS; +import static com.android.server.wm.proto.WindowManagerServiceProto.WINDOWS; /** Root {@link WindowContainer} for the device. */ class RootWindowContainer extends WindowContainer<DisplayContent> { @@ -373,7 +375,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { } @Override - void onConfigurationChanged(Configuration newParentConfig) { + public void onConfigurationChanged(Configuration newParentConfig) { prepareFreezingTaskBounds(); super.onConfigurationChanged(newParentConfig); @@ -663,19 +665,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { defaultDisplay.pendingLayoutChanges); } - for (i = mService.mResizingWindows.size() - 1; i >= 0; i--) { - WindowState win = mService.mResizingWindows.get(i); - if (win.mAppFreezing) { - // Don't remove this window until rotation has completed. - continue; - } - // Discard the saved surface if window size is changed, it can't be reused. - if (win.mAppToken != null) { - win.mAppToken.destroySavedSurfaces(); - } - win.reportResized(); - mService.mResizingWindows.remove(i); - } + final ArraySet<DisplayContent> touchExcludeRegionUpdateDisplays = handleResizingWindows(); if (DEBUG_ORIENTATION && mService.mDisplayFrozen) Slog.v(TAG, "With display frozen, orientationChangeComplete=" + mOrientationChangeComplete); @@ -702,7 +692,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { if (win.getDisplayContent().mWallpaperController.isWallpaperTarget(win)) { wallpaperDestroyed = true; } - win.destroyOrSaveSurfaceUnchecked(); + win.destroySurfaceUnchecked(); } while (i > 0); mService.mDestroySurface.clear(); } @@ -817,6 +807,16 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { mService.mInputMonitor.updateInputWindowsLw(false /*force*/); } mService.setFocusTaskRegionLocked(null); + if (touchExcludeRegionUpdateDisplays != null) { + final DisplayContent focusedDc = mService.mFocusedApp != null + ? mService.mFocusedApp.getDisplayContent() : null; + for (DisplayContent dc : touchExcludeRegionUpdateDisplays) { + // The focused DisplayContent was recalcuated in setFocusTaskRegionLocked + if (focusedDc != dc) { + dc.setTouchExcludeRegion(null /* focusedTask */); + } + } + } // Check to see if we are now in a state where the screen should // be enabled, because the window obscured flags have changed. @@ -868,6 +868,33 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { } /** + * Handles resizing windows during surface placement. + * + * @return A set of any DisplayContent whose touch exclude region needs to be recalculated due + * to a tap-exclude window resizing, or null if no such DisplayContents were found. + */ + private ArraySet<DisplayContent> handleResizingWindows() { + ArraySet<DisplayContent> touchExcludeRegionUpdateSet = null; + for (int i = mService.mResizingWindows.size() - 1; i >= 0; i--) { + WindowState win = mService.mResizingWindows.get(i); + if (win.mAppFreezing) { + // Don't remove this window until rotation has completed. + continue; + } + win.reportResized(); + mService.mResizingWindows.remove(i); + if (WindowManagerService.excludeWindowTypeFromTapOutTask(win.mAttrs.type)) { + final DisplayContent dc = win.getDisplayContent(); + if (touchExcludeRegionUpdateSet == null) { + touchExcludeRegionUpdateSet = new ArraySet<>(); + } + touchExcludeRegionUpdateSet.add(dc); + } + } + return touchExcludeRegionUpdateSet; + } + + /** * @param w WindowState this method is applied to. * @param obscured True if there is a window on top of this obscuring the display. * @param syswin System window? @@ -1055,6 +1082,19 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { } } + void writeToProto(ProtoOutputStream proto) { + if (mService.mDisplayReady) { + final int count = mChildren.size(); + for (int i = 0; i < count; ++i) { + final DisplayContent displayContent = mChildren.get(i); + displayContent.writeToProto(proto, DISPLAYS); + } + } + forAllWindows((w) -> { + w.writeIdentifierToProto(proto, WINDOWS); + }, true); + } + @Override String getName() { return "ROOT"; diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index 83337ca98e35..d5b6d24631e6 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -25,12 +25,15 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER; import static com.android.server.wm.WindowStateAnimator.WINDOW_FREEZE_LAYER; import static com.android.server.wm.WindowSurfaceController.SurfaceTrace; +import static com.android.server.wm.proto.ScreenRotationAnimationProto.ANIMATION_RUNNING; +import static com.android.server.wm.proto.ScreenRotationAnimationProto.STARTED; import android.content.Context; import android.graphics.Matrix; import android.graphics.PixelFormat; import android.graphics.Rect; import android.util.Slog; +import android.util.proto.ProtoOutputStream; import android.view.Display; import android.view.DisplayInfo; import android.view.Surface; @@ -198,7 +201,7 @@ class ScreenRotationAnimation { pw.print(prefix); pw.print("mEnterTransformation="); mEnterTransformation.printShortString(pw); pw.println(); pw.print(prefix); pw.print("mFrameTransformation="); - mEnterTransformation.printShortString(pw); pw.println(); + mFrameTransformation.printShortString(pw); pw.println(); pw.print(prefix); pw.print("mFrameInitialMatrix="); mFrameInitialMatrix.printShortString(pw); pw.println(); @@ -216,6 +219,13 @@ class ScreenRotationAnimation { } } + public void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + proto.write(STARTED, mStarted); + proto.write(ANIMATION_RUNNING, mAnimRunning); + proto.end(token); + } + public ScreenRotationAnimation(Context context, DisplayContent displayContent, SurfaceSession session, boolean inTransaction, boolean forceDefaultOrientation, boolean isSecure, WindowManagerService service) { @@ -280,7 +290,7 @@ class ScreenRotationAnimation { // capture a screenshot into the surface we just created Surface sur = new Surface(); sur.copyFrom(mSurfaceControl); - // FIXME: we should use the proper display + // TODO(multidisplay): we should use the proper display SurfaceControl.screenshot(SurfaceControl.getBuiltInDisplay( SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN), sur); mSurfaceControl.setLayerStack(display.getLayerStack()); diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 7a8c2f91b4e9..178124776823 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.Manifest.permission.DEVICE_POWER; import static android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; import static android.content.pm.PackageManager.PERMISSION_GRANTED; @@ -84,6 +85,7 @@ public class Session extends IWindowSession.Stub private final Set<WindowSurfaceController> mAlertWindowSurfaces = new HashSet<>(); final boolean mCanAddInternalSystemWindow; final boolean mCanHideNonSystemOverlayWindows; + final boolean mCanAcquireSleepToken; private AlertWindowNotification mAlertWindowNotification; private boolean mShowingAlertWindowNotificationAllowed; private boolean mClientDead = false; @@ -103,6 +105,8 @@ public class Session extends IWindowSession.Stub INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED; mCanHideNonSystemOverlayWindows = service.mContext.checkCallingOrSelfPermission( HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED; + mCanAcquireSleepToken = service.mContext.checkCallingOrSelfPermission(DEVICE_POWER) + == PERMISSION_GRANTED; mShowingAlertWindowNotificationAllowed = mService.mShowAlertWindowNotifications; StringBuilder sb = new StringBuilder(); sb.append("Session{"); diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java index 9c44c14d7866..aaacef5c5e57 100644 --- a/services/core/java/com/android/server/wm/StackWindowController.java +++ b/services/core/java/com/android/server/wm/StackWindowController.java @@ -16,11 +16,10 @@ package com.android.server.wm; -import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import android.app.ActivityManager.StackId; -import android.app.RemoteAction; +import android.app.WindowConfiguration; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Handler; @@ -30,11 +29,9 @@ import android.util.Slog; import android.util.SparseArray; import android.view.DisplayInfo; -import com.android.server.UiThread; import com.android.internal.annotations.VisibleForTesting; import java.lang.ref.WeakReference; -import java.util.List; import static com.android.server.wm.WindowContainer.POSITION_BOTTOM; import static com.android.server.wm.WindowContainer.POSITION_TOP; @@ -61,13 +58,15 @@ public class StackWindowController private final Rect mTmpDisplayBounds = new Rect(); public StackWindowController(int stackId, StackWindowListener listener, - int displayId, boolean onTop, Rect outBounds) { - this(stackId, listener, displayId, onTop, outBounds, WindowManagerService.getInstance()); + int displayId, boolean onTop, Rect outBounds, Configuration overriderConfig) { + this(stackId, listener, displayId, onTop, outBounds, overriderConfig, + WindowManagerService.getInstance()); } @VisibleForTesting public StackWindowController(int stackId, StackWindowListener listener, - int displayId, boolean onTop, Rect outBounds, WindowManagerService service) { + int displayId, boolean onTop, Rect outBounds, Configuration overrideConfig, + WindowManagerService service) { super(listener, service); mStackId = stackId; mHandler = new H(new WeakReference<>(this), service.mH.getLooper()); @@ -80,6 +79,9 @@ public class StackWindowController } final TaskStack stack = dc.addStackToDisplay(stackId, onTop); + if (overrideConfig != null) { + stack.onOverrideConfigurationChanged(overrideConfig); + } stack.setController(this); getRawBounds(outBounds); } @@ -278,12 +280,12 @@ public class StackWindowController int width; int height; - final Rect parentAppBounds = parentConfig.appBounds; + final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds(); - config.setAppBounds(!bounds.isEmpty() ? bounds : null); + config.windowConfiguration.setAppBounds(!bounds.isEmpty() ? bounds : null); boolean intersectParentBounds = false; - if (StackId.tasksAreFloating(mStackId)) { + if (stack.getWindowConfiguration().tasksAreFloating()) { // Floating tasks should not be resized to the screen's bounds. if (mStackId == PINNED_STACK_ID && bounds.width() == mTmpDisplayBounds.width() && @@ -295,7 +297,7 @@ public class StackWindowController nonDecorBounds.inset(mTmpNonDecorInsets); // Move app bounds to zero to apply intersection with parent correctly. They are // used only for evaluating width and height, so it's OK to move them around. - config.appBounds.offsetTo(0, 0); + config.windowConfiguration.getAppBounds().offsetTo(0, 0); intersectParentBounds = true; } width = (int) (stableBounds.width() / density); @@ -319,8 +321,8 @@ public class StackWindowController intersectParentBounds = true; } - if (intersectParentBounds && config.appBounds != null) { - config.appBounds.intersect(parentAppBounds); + if (intersectParentBounds && config.windowConfiguration.getAppBounds() != null) { + config.windowConfiguration.getAppBounds().intersect(parentAppBounds); } config.screenWidthDp = width; @@ -360,7 +362,7 @@ public class StackWindowController bounds.height() == displayInfo.logicalHeight)) { // If the bounds are fullscreen, return the value of the fullscreen configuration return displayContent.getConfiguration().smallestScreenWidthDp; - } else if (StackId.tasksAreFloating(mStackId)) { + } else if (mContainer.getWindowConfiguration().tasksAreFloating()) { // For floating tasks, calculate the smallest width from the bounds of the task return (int) (Math.min(bounds.width(), bounds.height()) / density); } else { diff --git a/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java b/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java index ac06c6db4c5c..b0eaf1488f21 100644 --- a/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java +++ b/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java @@ -26,15 +26,18 @@ import android.view.Surface.OutOfResourcesException; import android.view.SurfaceControl; import android.view.SurfaceSession; -import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; -import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; +import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; +import static android.view.WindowManagerPolicy.NAV_BAR_BOTTOM; +import static android.view.WindowManagerPolicy.NAV_BAR_LEFT; +import static android.view.WindowManagerPolicy.NAV_BAR_RIGHT; /** - * SurfaceControl extension that has background sized to match its container. + * SurfaceControl extension that has black background behind navigation bar area for fullscreen + * letterboxed apps. */ class SurfaceControlWithBackground extends SurfaceControl { - // SurfaceControl that holds the background behind opaque letterboxed app windows. + // SurfaceControl that holds the background. private SurfaceControl mBackgroundControl; // Flag that defines whether the background should be shown. @@ -51,8 +54,10 @@ class SurfaceControlWithBackground extends SurfaceControl { private float mLastDsDx = 1, mLastDsDy = 1; private float mLastX, mLastY; - // Will skip alpha animation for background of starting window. - private boolean mIsStartingWindow; + // SurfaceFlinger doesn't support crop rectangles where width or height is non-positive. + // If we just set an empty crop it will behave as if there is no crop at all. + // To fix this we explicitly hide the surface and won't let it to be shown. + private boolean mHiddenForCrop = false; public SurfaceControlWithBackground(SurfaceControlWithBackground other) { super(other); @@ -67,16 +72,14 @@ class SurfaceControlWithBackground extends SurfaceControl { super(s, name, w, h, format, flags, windowType, ownerUid); // We should only show background behind app windows that are letterboxed in a task. - if (!windowSurfaceController.mAnimator.mWin.isLetterboxedAppWindow() - || windowType < FIRST_APPLICATION_WINDOW - || windowType > LAST_APPLICATION_WINDOW) { + if ((windowType != TYPE_BASE_APPLICATION && windowType != TYPE_APPLICATION_STARTING) + || !windowSurfaceController.mAnimator.mWin.isLetterboxedAppWindow()) { return; } mWindowSurfaceController = windowSurfaceController; mLastWidth = w; mLastHeight = h; mWindowSurfaceController.getContainerRect(mTmpContainerRect); - mIsStartingWindow = windowType == TYPE_APPLICATION_STARTING; mBackgroundControl = new SurfaceControl(s, "Background for - " + name, mTmpContainerRect.width(), mTmpContainerRect.height(), PixelFormat.OPAQUE, flags | SurfaceControl.FX_SURFACE_DIM); @@ -89,10 +92,7 @@ class SurfaceControlWithBackground extends SurfaceControl { if (mBackgroundControl == null) { return; } - // We won't animate alpha for starting window because it will be visible as a flash for user - // when fading out to reveal real app window. - final float backgroundAlpha = mIsStartingWindow && alpha < 1.f ? 0 : alpha; - mBackgroundControl.setAlpha(backgroundAlpha); + mBackgroundControl.setAlpha(alpha); } @Override @@ -146,15 +146,10 @@ class SurfaceControlWithBackground extends SurfaceControl { if (mBackgroundControl == null) { return; } - if (crop.width() < mLastWidth || crop.height() < mLastHeight) { - // We're animating and cropping window, compute the appropriate crop for background. - calculateBgCrop(crop); - mBackgroundControl.setWindowCrop(mTmpContainerRect); - } else { - // When not animating just set crop to container rect. - mWindowSurfaceController.getContainerRect(mTmpContainerRect); - mBackgroundControl.setWindowCrop(mTmpContainerRect); - } + calculateBgCrop(crop); + mBackgroundControl.setWindowCrop(mTmpContainerRect); + mHiddenForCrop = mTmpContainerRect.isEmpty(); + updateBackgroundVisibility(); } @Override @@ -164,34 +159,24 @@ class SurfaceControlWithBackground extends SurfaceControl { if (mBackgroundControl == null) { return; } - if (crop.width() < mLastWidth || crop.height() < mLastHeight) { - // We're animating and cropping window, compute the appropriate crop for background. - calculateBgCrop(crop); - mBackgroundControl.setFinalCrop(mTmpContainerRect); - } else { - // When not animating just set crop to container rect. - mWindowSurfaceController.getContainerRect(mTmpContainerRect); - mBackgroundControl.setFinalCrop(mTmpContainerRect); - } + mWindowSurfaceController.getContainerRect(mTmpContainerRect); + mBackgroundControl.setFinalCrop(mTmpContainerRect); } - /** Compute background crop based on current animation progress for main surface control. */ + /** + * Compute background crop based on current animation progress for main surface control and + * update {@link #mTmpContainerRect} with new values. + */ private void calculateBgCrop(Rect crop) { // Track overall progress of animation by computing cropped portion of status bar. final Rect contentInsets = mWindowSurfaceController.mAnimator.mWin.mContentInsets; float d = contentInsets.top == 0 ? 0 : (float) crop.top / contentInsets.top; if (d > 1.f) { // We're running expand animation from launcher, won't compute custom bg crop here. - mTmpContainerRect.set(crop); + mTmpContainerRect.setEmpty(); return; } - // Compute additional offset for the background when app window is positioned not at (0,0). - // E.g. landscape with navigation bar on the left. - final Rect winFrame = mWindowSurfaceController.mAnimator.mWin.mFrame; - final int offsetX = (int) (winFrame.left * mLastDsDx * d + 0.5); - final int offsetY = (int) (winFrame.top * mLastDsDy * d + 0.5); - // Compute new scaled width and height for background that will depend on current animation // progress. Those consist of current crop rect for the main surface + scaled areas outside // of letterboxed area. @@ -201,17 +186,39 @@ class SurfaceControlWithBackground extends SurfaceControl { // computing correct frames for letterboxed windows in WindowState. d = d < 0.025f ? 0 : d; mWindowSurfaceController.getContainerRect(mTmpContainerRect); - final int backgroundWidth = - (int) (crop.width() + (mTmpContainerRect.width() - mLastWidth) * (1 - d) + 0.5); - final int backgroundHeight = - (int) (crop.height() + (mTmpContainerRect.height() - mLastHeight) * (1 - d) + 0.5); - - mTmpContainerRect.set(crop); - // Make sure that part of background to left/top is visible and scaled. - mTmpContainerRect.offset(offsetX, offsetY); - // Set correct width/height, so that area to right/bottom is cropped properly. - mTmpContainerRect.right = mTmpContainerRect.left + backgroundWidth; - mTmpContainerRect.bottom = mTmpContainerRect.top + backgroundHeight; + int backgroundWidth = 0, backgroundHeight = 0; + // Compute additional offset for the background when app window is positioned not at (0,0). + // E.g. landscape with navigation bar on the left. + final Rect winFrame = mWindowSurfaceController.mAnimator.mWin.mFrame; + int offsetX = (int)((winFrame.left - mTmpContainerRect.left) * mLastDsDx), + offsetY = (int) ((winFrame.top - mTmpContainerRect.top) * mLastDsDy); + + // Position and size background. + final int bgPosition = mWindowSurfaceController.mAnimator.mService.getNavBarPosition(); + + switch (bgPosition) { + case NAV_BAR_LEFT: + backgroundWidth = (int) ((mTmpContainerRect.width() - mLastWidth) * (1 - d) + 0.5); + backgroundHeight = crop.height(); + offsetX += crop.left - backgroundWidth; + offsetY += crop.top; + break; + case NAV_BAR_RIGHT: + backgroundWidth = (int) ((mTmpContainerRect.width() - mLastWidth) * (1 - d) + 0.5); + backgroundHeight = crop.height(); + offsetX += crop.right; + offsetY += crop.top; + break; + case NAV_BAR_BOTTOM: + backgroundWidth = crop.width(); + backgroundHeight = (int) ((mTmpContainerRect.height() - mLastHeight) * (1 - d) + + 0.5); + offsetX += crop.left; + offsetY += crop.bottom; + break; + } + mTmpContainerRect.set(offsetX, offsetY, offsetX + backgroundWidth, + offsetY + backgroundHeight); } @Override @@ -317,7 +324,7 @@ class SurfaceControlWithBackground extends SurfaceControl { return; } final AppWindowToken appWindowToken = mWindowSurfaceController.mAnimator.mWin.mAppToken; - if (appWindowToken != null && appWindowToken.fillsParent() && mVisible) { + if (!mHiddenForCrop && mVisible && appWindowToken != null && appWindowToken.fillsParent()) { mBackgroundControl.show(); } else { mBackgroundControl.hide(); diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index e5055e92828e..f57238e34694 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -29,6 +29,11 @@ import static com.android.server.EventLogTags.WM_TASK_REMOVED; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; +import static com.android.server.wm.proto.TaskProto.APP_WINDOW_TOKENS; +import static com.android.server.wm.proto.TaskProto.BOUNDS; +import static com.android.server.wm.proto.TaskProto.FILLS_PARENT; +import static com.android.server.wm.proto.TaskProto.ID; +import static com.android.server.wm.proto.TaskProto.TEMP_INSET_BOUNDS; import android.app.ActivityManager.StackId; import android.app.ActivityManager.TaskDescription; @@ -37,11 +42,11 @@ import android.content.res.Configuration; import android.graphics.Rect; import android.util.EventLog; import android.util.Slog; +import android.util.proto.ProtoOutputStream; import android.view.DisplayInfo; import android.view.Surface; import com.android.internal.annotations.VisibleForTesting; -import com.android.server.wm.DimLayer.DimLayerUser; import java.io.PrintWriter; import java.util.function.Consumer; @@ -92,27 +97,23 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU private boolean mDragResizing; private int mDragResizeMode; - private boolean mHomeTask; - private TaskDescription mTaskDescription; // If set to true, the task will report that it is not in the floating - // state regardless of it's stack affilation. As the floating state drives + // state regardless of it's stack affiliation. As the floating state drives // production of content insets this can be used to preserve them across // stack moves and we in fact do so when moving from full screen to pinned. private boolean mPreserveNonFloatingState = false; Task(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds, Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture, - boolean homeTask, TaskDescription taskDescription, - TaskWindowContainerController controller) { + TaskDescription taskDescription, TaskWindowContainerController controller) { mTaskId = taskId; mStack = stack; mUserId = userId; mService = service; mResizeMode = resizeMode; mSupportsPictureInPicture = supportsPictureInPicture; - mHomeTask = homeTask; setController(controller); setBounds(bounds, overrideConfig); mTaskDescription = taskDescription; @@ -239,7 +240,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU // Update task bounds if needed. updateDisplayInfo(getDisplayContent()); - if (StackId.windowsAreScaleable(mStack.mStackId)) { + if (getWindowConfiguration().windowsAreScaleable()) { // We force windows out of SCALING_MODE_FREEZE so that we can continue to animate them // while a resize is pending. forceWindowsScaleable(true /* force */); @@ -365,10 +366,6 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU return isResizeable(); } - boolean isHomeTask() { - return mHomeTask; - } - boolean resizeLocked(Rect bounds, Configuration overrideConfig, boolean forced) { int boundsChanged = setBounds(bounds, overrideConfig); if (forced) { @@ -567,7 +564,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU // from its stack. The stack will take care of task rotation for the other case. mTmpRect2.set(mBounds); - if (!StackId.isTaskResizeAllowed(mStack.mStackId)) { + if (!getWindowConfiguration().canResizeTask()) { setBounds(mTmpRect2, getOverrideConfiguration()); return; } @@ -615,7 +612,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU * we will have a jump at the end. */ boolean isFloating() { - return StackId.tasksAreFloating(mStack.mStackId) + return getWindowConfiguration().tasksAreFloating() && !mStack.isAnimatingBoundsToFullscreen() && !mPreserveNonFloatingState; } @@ -704,7 +701,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU @Override boolean fillsParent() { - return mFillsParent || !StackId.isTaskResizeAllowed(mStack.mStackId); + return mFillsParent || !getWindowConfiguration().canResizeTask(); } @Override @@ -735,6 +732,19 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU return "Task=" + mTaskId; } + void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + proto.write(ID, mTaskId); + for (int i = mChildren.size() - 1; i >= 0; i--) { + final AppWindowToken appWindowToken = mChildren.get(i); + appWindowToken.writeToProto(proto, APP_WINDOW_TOKENS); + } + proto.write(FILLS_PARENT, mFillsParent); + mBounds.writeToProto(proto, BOUNDS); + mTempInsetBounds.writeToProto(proto, TEMP_INSET_BOUNDS); + proto.end(token); + } + public void dump(String prefix, PrintWriter pw) { final String doublePrefix = prefix + " "; diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java index 940ad33268db..463240228fb6 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotController.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java @@ -16,8 +16,8 @@ package com.android.server.wm; -import static android.app.ActivityManager.ENABLE_TASK_SNAPSHOTS; - +import static com.android.server.wm.TaskSnapshotPersister.DISABLE_FULL_SIZED_BITMAPS; +import static com.android.server.wm.TaskSnapshotPersister.REDUCED_SCALE; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; @@ -102,6 +102,11 @@ class TaskSnapshotController { */ private final boolean mIsRunningOnIoT; + /** + * Flag indicating whether we are running on an Android Wear device. + */ + private final boolean mIsRunningOnWear; + TaskSnapshotController(WindowManagerService service) { mService = service; mCache = new TaskSnapshotCache(mService, mLoader); @@ -109,6 +114,8 @@ class TaskSnapshotController { PackageManager.FEATURE_LEANBACK); mIsRunningOnIoT = mService.mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_EMBEDDED); + mIsRunningOnWear = mService.mContext.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_WATCH); } void systemReady() { @@ -181,7 +188,8 @@ class TaskSnapshotController { */ @Nullable TaskSnapshot getSnapshot(int taskId, int userId, boolean restoreFromDisk, boolean reducedResolution) { - return mCache.getSnapshot(taskId, userId, restoreFromDisk, reducedResolution); + return mCache.getSnapshot(taskId, userId, restoreFromDisk, reducedResolution + || DISABLE_FULL_SIZED_BITMAPS); } /** @@ -202,19 +210,20 @@ class TaskSnapshotController { if (mainWindow == null) { return null; } + final boolean isLowRamDevice = ActivityManager.isLowRamDeviceStatic(); + final float scaleFraction = isLowRamDevice ? REDUCED_SCALE : 1f; final GraphicBuffer buffer = top.mDisplayContent.screenshotApplicationsToBuffer(top.token, - -1, -1, false, 1.0f, false, true); - if (buffer == null) { + -1, -1, false, scaleFraction, false, true); + if (buffer == null || buffer.getWidth() <= 1 || buffer.getHeight() <= 1) { return null; } return new TaskSnapshot(buffer, top.getConfiguration().orientation, - minRect(mainWindow.mContentInsets, mainWindow.mStableInsets), false /* reduced */, - 1f /* scale */); + minRect(mainWindow.mContentInsets, mainWindow.mStableInsets), + isLowRamDevice /* reduced */, scaleFraction /* scale */); } private boolean shouldDisableSnapshots() { - return !ENABLE_TASK_SNAPSHOTS || ActivityManager.isLowRamDeviceStatic() - || mIsRunningOnTv || mIsRunningOnIoT; + return mIsRunningOnWear || mIsRunningOnTv || mIsRunningOnIoT; } private Rect minRect(Rect rect1, Rect rect2) { diff --git a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java index ec21d259f70e..537f31775951 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java @@ -68,7 +68,7 @@ class TaskSnapshotLoader { final File bitmapFile = reducedResolution ? mPersister.getReducedResolutionBitmapFile(taskId, userId) : mPersister.getBitmapFile(taskId, userId); - if (!protoFile.exists() || !bitmapFile.exists()) { + if (bitmapFile == null || !protoFile.exists() || !bitmapFile.exists()) { return null; } try { diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java index f90b3fb6c1de..a2c9283a9b1e 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java @@ -21,6 +21,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.annotation.TestApi; +import android.app.ActivityManager; import android.app.ActivityManager.TaskSnapshot; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; @@ -53,6 +54,7 @@ class TaskSnapshotPersister { private static final String SNAPSHOTS_DIRNAME = "snapshots"; private static final String REDUCED_POSTFIX = "_reduced"; static final float REDUCED_SCALE = 0.5f; + static final boolean DISABLE_FULL_SIZED_BITMAPS = ActivityManager.isLowRamDeviceStatic(); private static final long DELAY_MS = 100; private static final int QUALITY = 95; private static final String PROTO_EXTENSION = ".proto"; @@ -183,6 +185,11 @@ class TaskSnapshotPersister { } File getBitmapFile(int taskId, int userId) { + // Full sized bitmaps are disabled on low ram devices + if (DISABLE_FULL_SIZED_BITMAPS) { + Slog.wtf(TAG, "This device does not support full sized resolution bitmaps."); + return null; + } return new File(getDirectory(userId), taskId + BITMAP_EXTENSION); } @@ -197,11 +204,15 @@ class TaskSnapshotPersister { private void deleteSnapshot(int taskId, int userId) { final File protoFile = getProtoFile(taskId, userId); - final File bitmapFile = getBitmapFile(taskId, userId); final File bitmapReducedFile = getReducedResolutionBitmapFile(taskId, userId); protoFile.delete(); - bitmapFile.delete(); bitmapReducedFile.delete(); + + // Low ram devices do not have a full sized file to delete + if (!DISABLE_FULL_SIZED_BITMAPS) { + final File bitmapFile = getBitmapFile(taskId, userId); + bitmapFile.delete(); + } } interface DirectoryResolver { @@ -322,8 +333,6 @@ class TaskSnapshotPersister { } boolean writeBuffer() { - final File file = getBitmapFile(mTaskId, mUserId); - final File reducedFile = getReducedResolutionBitmapFile(mTaskId, mUserId); final Bitmap bitmap = Bitmap.createHardwareBitmap(mSnapshot.getSnapshot()); if (bitmap == null) { Slog.e(TAG, "Invalid task snapshot hw bitmap"); @@ -331,18 +340,33 @@ class TaskSnapshotPersister { } final Bitmap swBitmap = bitmap.copy(Config.ARGB_8888, false /* isMutable */); - final Bitmap reduced = Bitmap.createScaledBitmap(swBitmap, - (int) (bitmap.getWidth() * REDUCED_SCALE), - (int) (bitmap.getHeight() * REDUCED_SCALE), true /* filter */); + final File reducedFile = getReducedResolutionBitmapFile(mTaskId, mUserId); + final Bitmap reduced = mSnapshot.isReducedResolution() + ? swBitmap + : Bitmap.createScaledBitmap(swBitmap, + (int) (bitmap.getWidth() * REDUCED_SCALE), + (int) (bitmap.getHeight() * REDUCED_SCALE), true /* filter */); try { - FileOutputStream fos = new FileOutputStream(file); - swBitmap.compress(JPEG, QUALITY, fos); - fos.close(); FileOutputStream reducedFos = new FileOutputStream(reducedFile); reduced.compress(JPEG, QUALITY, reducedFos); reducedFos.close(); } catch (IOException e) { - Slog.e(TAG, "Unable to open " + file + " or " + reducedFile +" for persisting.", e); + Slog.e(TAG, "Unable to open " + reducedFile +" for persisting.", e); + return false; + } + + // For snapshots with reduced resolution, do not create or save full sized bitmaps + if (mSnapshot.isReducedResolution()) { + return true; + } + + final File file = getBitmapFile(mTaskId, mUserId); + try { + FileOutputStream fos = new FileOutputStream(file); + swBitmap.compress(JPEG, QUALITY, fos); + fos.close(); + } catch (IOException e) { + Slog.e(TAG, "Unable to open " + file + " for persisting.", e); return false; } return true; diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java index 1bece6903eac..4698d72567c4 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java @@ -162,7 +162,7 @@ class TaskSnapshotSurface implements StartingSurface { + task); return null; } - final WindowState topFullscreenWindow = topFullscreenToken.findMainWindow(); + final WindowState topFullscreenWindow = topFullscreenToken.getTopFullscreenWindow(); if (mainWindow == null || topFullscreenWindow == null) { Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for token=" + token); @@ -320,6 +320,10 @@ class TaskSnapshotSurface implements StartingSurface { mChildSurfaceControl.show(); mChildSurfaceControl.setWindowCrop(crop); mChildSurfaceControl.setPosition(frame.left, frame.top); + + // Scale the mismatch dimensions to fill the task bounds + final float scale = 1 / mSnapshot.getScale(); + mChildSurfaceControl.setMatrix(scale, 0, 0, scale); } finally { SurfaceControl.closeTransaction(); } @@ -332,6 +336,11 @@ class TaskSnapshotSurface implements StartingSurface { mSurface.release(); } + /** + * Calculates the snapshot crop in snapshot coordinate space. + * + * @return crop rect in snapshot coordinate space. + */ @VisibleForTesting Rect calculateSnapshotCrop() { final Rect rect = new Rect(); @@ -340,16 +349,28 @@ class TaskSnapshotSurface implements StartingSurface { // Let's remove all system decorations except the status bar, but only if the task is at the // very top of the screen. - rect.inset(insets.left, mTaskBounds.top != 0 ? insets.top : 0, insets.right, insets.bottom); + rect.inset((int) (insets.left * mSnapshot.getScale()), + mTaskBounds.top != 0 ? (int) (insets.top * mSnapshot.getScale()) : 0, + (int) (insets.right * mSnapshot.getScale()), + (int) (insets.bottom * mSnapshot.getScale())); return rect; } + /** + * Calculates the snapshot frame in window coordinate space from crop. + * + * @param crop rect that is in snapshot coordinate space. + */ @VisibleForTesting Rect calculateSnapshotFrame(Rect crop) { final Rect frame = new Rect(crop); + final float scale = mSnapshot.getScale(); + + // Rescale the frame from snapshot to window coordinate space + frame.scale(1 / scale); // By default, offset it to to top/left corner - frame.offsetTo(-crop.left, -crop.top); + frame.offsetTo((int) (-crop.left / scale), (int) (-crop.top / scale)); // However, we also need to make space for the navigation bar on the left side. final int colorViewLeftInset = getColorViewLeftInset(mStableInsets.left, diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 39878ccb07dd..6ec7565ab156 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -36,6 +36,11 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerService.LAYER_OFFSET_DIM; +import static com.android.server.wm.proto.StackProto.ANIMATION_BACKGROUND_SURFACE_IS_DIMMING; +import static com.android.server.wm.proto.StackProto.BOUNDS; +import static com.android.server.wm.proto.StackProto.FILLS_PARENT; +import static com.android.server.wm.proto.StackProto.ID; +import static com.android.server.wm.proto.StackProto.TASKS; import android.app.ActivityManager.StackId; import android.content.res.Configuration; @@ -45,6 +50,7 @@ import android.os.RemoteException; import android.util.EventLog; import android.util.Slog; import android.util.SparseArray; +import android.util.proto.ProtoOutputStream; import android.view.DisplayInfo; import android.view.Surface; @@ -52,7 +58,6 @@ import com.android.internal.policy.DividerSnapAlgorithm; import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget; import com.android.internal.policy.DockedDividerUtils; import com.android.server.EventLogTags; -import com.android.server.UiThread; import java.io.PrintWriter; @@ -155,20 +160,10 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye } Task findHomeTask() { - if (mStackId != HOME_STACK_ID) { + if (!isActivityTypeHome() || mChildren.isEmpty()) { return null; } - - for (int i = mChildren.size() - 1; i >= 0; i--) { - if (mChildren.get(i).isHomeTask()) { - return mChildren.get(i); - } - } - return null; - } - - boolean hasMultipleTaskWithHomeTaskNotTop() { - return mChildren.size() > 1 && !mChildren.get(mChildren.size() - 1).isHomeTask(); + return mChildren.get(mChildren.size() - 1); } /** @@ -1225,6 +1220,18 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye return mMinimizeAmount != 0f; } + void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + proto.write(ID, mStackId); + for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) { + mChildren.get(taskNdx).writeToProto(proto, TASKS); + } + proto.write(FILLS_PARENT, mFillsParent); + mBounds.writeToProto(proto, BOUNDS); + proto.write(ANIMATION_BACKGROUND_SURFACE_IS_DIMMING, mAnimationBackgroundSurface.isDimming()); + proto.end(token); + } + public void dump(String prefix, PrintWriter pw) { pw.println(prefix + "mStackId=" + mStackId); pw.println(prefix + "mDeferRemoval=" + mDeferRemoval); @@ -1386,7 +1393,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye void findTaskForResizePoint(int x, int y, int delta, DisplayContent.TaskForResizePointSearchResult results) { - if (!StackId.isTaskResizeAllowed(mStackId)) { + if (!getWindowConfiguration().canResizeTask()) { results.searchDone = true; return; } @@ -1443,7 +1450,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye * small portion which the home stack currently is resized to. */ - if (task.isHomeTask() && isMinimizedDockAndHomeStackResizable()) { + if (task.isActivityTypeHome() && isMinimizedDockAndHomeStackResizable()) { mDisplayContent.getLogicalDisplayRect(mTmpRect); } else { task.getDimBounds(mTmpRect); @@ -1498,7 +1505,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye } @Override // AnimatesBounds - public void onAnimationStart(boolean schedulePipModeChangedCallback) { + public void onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate) { // Hold the lock since this is called from the BoundsAnimator running on the UiThread synchronized (mService.mWindowMap) { mBoundsAnimatingRequested = false; @@ -1523,9 +1530,11 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye final PinnedStackWindowController controller = (PinnedStackWindowController) getController(); if (schedulePipModeChangedCallback && controller != null) { - // We need to schedule the PiP mode change after the animation down, so use the - // final bounds - controller.updatePictureInPictureModeForPinnedStackAnimation(null); + // We need to schedule the PiP mode change before the animation up. It is possible + // in this case for the animation down to not have been completed, so always + // force-schedule and update to the client to ensure that it is notified that it + // is no longer in picture-in-picture mode + controller.updatePictureInPictureModeForPinnedStackAnimation(null, forceUpdate); } } } @@ -1553,7 +1562,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye // We need to schedule the PiP mode change after the animation down, so use the // final bounds controller.updatePictureInPictureModeForPinnedStackAnimation( - mBoundsAnimationTarget); + mBoundsAnimationTarget, false /* forceUpdate */); } if (finalStackSize != null) { @@ -1583,10 +1592,6 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye return false; } - public boolean hasMovementAnimations() { - return StackId.hasMovementAnimations(mStackId); - } - public boolean isForceScaled() { return mBoundsAnimating; } diff --git a/services/core/java/com/android/server/wm/TaskWindowContainerController.java b/services/core/java/com/android/server/wm/TaskWindowContainerController.java index 54a6cc01c831..d8929c9d80c2 100644 --- a/services/core/java/com/android/server/wm/TaskWindowContainerController.java +++ b/services/core/java/com/android/server/wm/TaskWindowContainerController.java @@ -51,18 +51,17 @@ public class TaskWindowContainerController public TaskWindowContainerController(int taskId, TaskWindowContainerListener listener, StackWindowController stackController, int userId, Rect bounds, Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture, - boolean homeTask, boolean toTop, boolean showForAllUsers, - TaskDescription taskDescription) { + boolean toTop, boolean showForAllUsers, TaskDescription taskDescription) { this(taskId, listener, stackController, userId, bounds, overrideConfig, resizeMode, - supportsPictureInPicture, homeTask, toTop, showForAllUsers, taskDescription, + supportsPictureInPicture, toTop, showForAllUsers, taskDescription, WindowManagerService.getInstance()); } public TaskWindowContainerController(int taskId, TaskWindowContainerListener listener, StackWindowController stackController, int userId, Rect bounds, Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture, - boolean homeTask, boolean toTop, boolean showForAllUsers, - TaskDescription taskDescription, WindowManagerService service) { + boolean toTop, boolean showForAllUsers, TaskDescription taskDescription, + WindowManagerService service) { super(listener, service); mTaskId = taskId; mHandler = new H(new WeakReference<>(this), service.mH.getLooper()); @@ -78,7 +77,7 @@ public class TaskWindowContainerController } EventLog.writeEvent(WM_TASK_CREATED, taskId, stack.mStackId); final Task task = createTask(taskId, stack, userId, bounds, overrideConfig, resizeMode, - supportsPictureInPicture, homeTask, taskDescription); + supportsPictureInPicture, taskDescription); final int position = toTop ? POSITION_TOP : POSITION_BOTTOM; // We only want to move the parents to the parents if we are creating this task at the // top of its stack. @@ -89,9 +88,9 @@ public class TaskWindowContainerController @VisibleForTesting Task createTask(int taskId, TaskStack stack, int userId, Rect bounds, Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture, - boolean homeTask, TaskDescription taskDescription) { + TaskDescription taskDescription) { return new Task(taskId, stack, userId, mService, bounds, overrideConfig, resizeMode, - supportsPictureInPicture, homeTask, taskDescription, this); + supportsPictureInPicture, taskDescription, this); } @Override diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index 079ae40bcb48..c01ee31e8c1c 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -272,7 +272,6 @@ public class WindowAnimator { mRemoveReplacedWindows = false; } - mService.stopUsingSavedSurfaceLocked(); mService.destroyPreservedSurfaceLocked(); mService.mWindowPlacerLocked.destroyPendingSurfaces(); diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 3df73d7c627a..926719ddf318 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -38,7 +38,8 @@ import java.util.function.Predicate; * The test class is {@link WindowContainerTests} which must be kept up-to-date and ran anytime * changes are made to this class. */ -class WindowContainer<E extends WindowContainer> implements Comparable<WindowContainer> { +class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E> + implements Comparable<WindowContainer> { static final int POSITION_TOP = Integer.MAX_VALUE; static final int POSITION_BOTTOM = Integer.MIN_VALUE; @@ -54,22 +55,6 @@ class WindowContainer<E extends WindowContainer> implements Comparable<WindowCon // screen with the top-most window container at the tail of the list. protected final WindowList<E> mChildren = new WindowList<E>(); - /** Contains override configuration settings applied to this window container. */ - private Configuration mOverrideConfiguration = new Configuration(); - - /** - * Contains full configuration applied to this window container. Corresponds to full parent's - * config with applied {@link #mOverrideConfiguration}. - */ - private Configuration mFullConfiguration = new Configuration(); - - /** - * Contains merged override configuration settings from the top of the hierarchy down to this - * particular instance. It is different from {@link #mFullConfiguration} because it starts from - * topmost container's override config instead of global config. - */ - private Configuration mMergedOverrideConfiguration = new Configuration(); - // The specified orientation for this window container. protected int mOrientation = SCREEN_ORIENTATION_UNSPECIFIED; @@ -79,17 +64,29 @@ class WindowContainer<E extends WindowContainer> implements Comparable<WindowCon // The owner/creator for this container. No controller if null. private WindowContainerController mController; + @Override final protected WindowContainer getParent() { return mParent; } + + @Override + final protected int getChildCount() { + return mChildren.size(); + } + + @Override + final protected E getChildAt(int index) { + return mChildren.get(index); + } + final protected void setParent(WindowContainer parent) { mParent = parent; // Removing parent usually means that we've detached this entity to destroy it or to attach // to another parent. In both cases we don't need to update the configuration now. if (mParent != null) { // Update full configuration of this container and all its children. - onConfigurationChanged(mParent.mFullConfiguration); + onConfigurationChanged(mParent.getConfiguration()); // Update merged override configuration of this container and all its children. onMergedOverrideConfigurationChanged(); } @@ -282,44 +279,13 @@ class WindowContainer<E extends WindowContainer> implements Comparable<WindowCon } /** - * Returns full configuration applied to this window container. - * This method should be used for getting settings applied in each particular level of the - * hierarchy. - */ - Configuration getConfiguration() { - return mFullConfiguration; - } - - /** - * Notify that parent config changed and we need to update full configuration. - * @see #mFullConfiguration - */ - void onConfigurationChanged(Configuration newParentConfig) { - mFullConfiguration.setTo(newParentConfig); - mFullConfiguration.updateFrom(mOverrideConfiguration); - for (int i = mChildren.size() - 1; i >= 0; --i) { - final WindowContainer child = mChildren.get(i); - child.onConfigurationChanged(mFullConfiguration); - } - } - - /** Returns override configuration applied to this window container. */ - Configuration getOverrideConfiguration() { - return mOverrideConfiguration; - } - - /** * Update override configuration and recalculate full config. * @see #mOverrideConfiguration * @see #mFullConfiguration */ - void onOverrideConfigurationChanged(Configuration overrideConfiguration) { - mOverrideConfiguration.setTo(overrideConfiguration); - // Update full configuration of this container and all its children. - onConfigurationChanged(mParent != null ? mParent.getConfiguration() : EMPTY); - // Update merged override config of this container and all its children. - onMergedOverrideConfigurationChanged(); - + @Override + final public void onOverrideConfigurationChanged(Configuration overrideConfiguration) { + super.onOverrideConfigurationChanged(overrideConfiguration); if (mParent != null) { mParent.onDescendantOverrideConfigurationChanged(); } @@ -335,33 +301,6 @@ class WindowContainer<E extends WindowContainer> implements Comparable<WindowCon } /** - * Get merged override configuration from the top of the hierarchy down to this - * particular instance. This should be reported to client as override config. - */ - Configuration getMergedOverrideConfiguration() { - return mMergedOverrideConfiguration; - } - - /** - * Update merged override configuration based on corresponding parent's config and notify all - * its children. If there is no parent, merged override configuration will set equal to current - * override config. - * @see #mMergedOverrideConfiguration - */ - private void onMergedOverrideConfigurationChanged() { - if (mParent != null) { - mMergedOverrideConfiguration.setTo(mParent.getMergedOverrideConfiguration()); - mMergedOverrideConfiguration.updateFrom(mOverrideConfiguration); - } else { - mMergedOverrideConfiguration.setTo(mOverrideConfiguration); - } - for (int i = mChildren.size() - 1; i >= 0; --i) { - final WindowContainer child = mChildren.get(i); - child.onMergedOverrideConfigurationChanged(); - } - } - - /** * Notify that the display this container is on has changed. * @param dc The new display this container is on. */ @@ -424,13 +363,6 @@ class WindowContainer<E extends WindowContainer> implements Comparable<WindowCon } } - void setVisibleBeforeClientHidden() { - for (int i = mChildren.size() - 1; i >= 0; --i) { - final WindowContainer wc = mChildren.get(i); - wc.setVisibleBeforeClientHidden(); - } - } - /** * Returns true if the container or one of its children as some content it can display or wants * to display (e.g. app views or saved surface). diff --git a/services/core/java/com/android/server/wm/WindowLayersController.java b/services/core/java/com/android/server/wm/WindowLayersController.java index 5dc79f8500c0..5d1083e2be26 100644 --- a/services/core/java/com/android/server/wm/WindowLayersController.java +++ b/services/core/java/com/android/server/wm/WindowLayersController.java @@ -30,6 +30,7 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; +import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET; import static com.android.server.wm.WindowManagerService.WINDOW_LAYER_MULTIPLIER; /** @@ -198,7 +199,7 @@ class WindowLayersController { private void adjustSpecialWindows() { // The following adjustments are beyond the highest docked-affected layer - int layer = mHighestDockedAffectedLayer + WINDOW_LAYER_MULTIPLIER; + int layer = mHighestDockedAffectedLayer + TYPE_LAYER_OFFSET; // Adjust the docked stack windows and dock divider above only the windows that are affected // by the docked stack. When this happens, also boost the assistant window layers, otherwise diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 5c664c2d16ce..32ee51c8f751 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -102,6 +102,14 @@ import static com.android.server.wm.WindowManagerDebugConfig.SHOW_VERBOSE_TRANSA import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; +import static com.android.server.wm.proto.WindowManagerServiceProto.APP_TRANSITION; +import static com.android.server.wm.proto.WindowManagerServiceProto.DISPLAY_FROZEN; +import static com.android.server.wm.proto.WindowManagerServiceProto.FOCUSED_APP; +import static com.android.server.wm.proto.WindowManagerServiceProto.FOCUSED_WINDOW; +import static com.android.server.wm.proto.WindowManagerServiceProto.INPUT_METHOD_WINDOW; +import static com.android.server.wm.proto.WindowManagerServiceProto.LAST_ORIENTATION; +import static com.android.server.wm.proto.WindowManagerServiceProto.POLICY; +import static com.android.server.wm.proto.WindowManagerServiceProto.ROTATION; import android.Manifest; import android.Manifest.permission; @@ -175,6 +183,7 @@ import android.util.SparseArray; import android.util.SparseIntArray; import android.util.TimeUtils; import android.util.TypedValue; +import android.util.proto.ProtoOutputStream; import android.view.AppTransitionAnimationSpec; import android.view.Display; import android.view.DisplayInfo; @@ -436,13 +445,6 @@ public class WindowManagerService extends IWindowManager.Stub final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<>(); /** - * List of window tokens that have finished drawing their own windows and - * no longer need to show any saved surfaces. Windows that's still showing - * saved surfaces will be cleaned up after next animation pass. - */ - final ArrayList<AppWindowToken> mFinishedEarlyAnim = new ArrayList<>(); - - /** * List of app window tokens that are waiting for replacing windows. If the * replacement doesn't come in time the stale windows needs to be disposed of. */ @@ -2069,17 +2071,8 @@ public class WindowManagerService extends IWindowManager.Stub winAnimator.mEnterAnimationPending = false; winAnimator.mEnteringAnimation = false; - final boolean usingSavedSurfaceBeforeVisible = - oldVisibility != View.VISIBLE && win.isAnimatingWithSavedSurface(); - if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) { - if (winAnimator.hasSurface() && !win.mAnimatingExit - && usingSavedSurfaceBeforeVisible) { - Slog.d(TAG, "Ignoring layout to invisible when using saved surface " + win); - } - } - if (winAnimator.hasSurface() && !win.mAnimatingExit - && !usingSavedSurfaceBeforeVisible) { + if (winAnimator.hasSurface() && !win.mAnimatingExit) { if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Relayout invis " + win + ": mAnimatingExit=" + win.mAnimatingExit); // If we are not currently running the exit animation, we @@ -2347,7 +2340,7 @@ public class WindowManagerService extends IWindowManager.Stub // artifacts when we unfreeze the display if some different animation // is running. Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WM#applyAnimationLocked"); - if (okToAnimate()) { + if (atoken.okToAnimate()) { final DisplayContent displayContent = atoken.getTask().getDisplayContent(); final DisplayInfo displayInfo = displayContent.getDisplayInfo(); final int width = displayInfo.appWidth; @@ -2425,14 +2418,6 @@ public class WindowManagerService extends IWindowManager.Stub return false; } - boolean okToDisplay() { - return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn(); - } - - boolean okToAnimate() { - return okToDisplay() && mPolicy.okToAnimate(); - } - @Override public void addWindowToken(IBinder binder, int type, int displayId) { if (!checkCallingPermission(MANAGE_APP_TOKENS, "addWindowToken()")) { @@ -2699,7 +2684,9 @@ public class WindowManagerService extends IWindowManager.Stub synchronized(mWindowMap) { boolean prepared = mAppTransition.prepareAppTransitionLocked(transit, alwaysKeepCurrent, flags, forceOverride); - if (prepared && okToAnimate()) { + // TODO (multidisplay): associate app transitions with displays + final DisplayContent dc = mRoot.getDisplayContent(DEFAULT_DISPLAY); + if (prepared && dc != null && dc.okToAnimate()) { mSkipAppTransitionAnimation = false; } } @@ -5371,14 +5358,6 @@ public class WindowManagerService extends IWindowManager.Stub mDestroyPreservedSurface.clear(); } - void stopUsingSavedSurfaceLocked() { - for (int i = mFinishedEarlyAnim.size() - 1; i >= 0 ; i--) { - final AppWindowToken wtoken = mFinishedEarlyAnim.get(i); - wtoken.stopUsingSavedSurfaceLocked(); - } - mFinishedEarlyAnim.clear(); - } - // ------------------------------------------------------------- // IWindowManager API // ------------------------------------------------------------- @@ -5817,7 +5796,7 @@ public class WindowManagerService extends IWindowManager.Stub // If the screen is currently frozen or off, then keep // it frozen/off until this window draws at its new // orientation. - if (!okToDisplay() && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) { + if (!w.mToken.okToDisplay() && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) { if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Changing surface while display frozen: " + w); w.setOrientationChanging(true); w.mLastFreezeDuration = 0; @@ -6033,7 +6012,7 @@ public class WindowManagerService extends IWindowManager.Stub return; } - if (!displayContent.isReady() || !mPolicy.isScreenOn() || !okToAnimate()) { + if (!displayContent.isReady() || !mPolicy.isScreenOn() || !displayContent.okToAnimate()) { // No need to freeze the screen before the display is ready, if the screen is off, // or we can't currently animate. return; @@ -6069,7 +6048,8 @@ public class WindowManagerService extends IWindowManager.Stub Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); } - if (CUSTOM_SCREEN_ROTATION) { + // TODO(multidisplay): rotation on non-default displays + if (CUSTOM_SCREEN_ROTATION && displayContent.isDefaultDisplay) { mExitAnimId = exitAnim; mEnterAnimId = enterAnim; ScreenRotationAnimation screenRotationAnimation = @@ -6081,7 +6061,6 @@ public class WindowManagerService extends IWindowManager.Stub // Check whether the current screen contains any secure content. boolean isSecure = displayContent.hasSecureWindowOnScreen(); - // TODO(multidisplay): rotation on main screen only. displayContent.updateDisplayInfo(); screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent, mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure, @@ -6524,6 +6503,25 @@ public class WindowManagerService extends IWindowManager.Stub } } + private void writeToProtoLocked(ProtoOutputStream proto) { + mPolicy.writeToProto(proto, POLICY); + mRoot.writeToProto(proto); + if (mCurrentFocus != null) { + mCurrentFocus.writeIdentifierToProto(proto, FOCUSED_WINDOW); + } + if (mFocusedApp != null) { + mFocusedApp.writeNameToProto(proto, FOCUSED_APP); + } + if (mInputMethodWindow != null) { + mInputMethodWindow.writeIdentifierToProto(proto, INPUT_METHOD_WINDOW); + } + proto.write(DISPLAY_FROZEN, mDisplayFrozen); + final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked(); + proto.write(ROTATION, defaultDisplayContent.getRotation()); + proto.write(LAST_ORIENTATION, defaultDisplayContent.getLastOrientation()); + mAppTransition.writeToProto(proto, APP_TRANSITION); + } + private void dumpWindowsLocked(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows) { pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)"); @@ -6798,6 +6796,7 @@ public class WindowManagerService extends IWindowManager.Stub if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; boolean dumpAll = false; + boolean useProto = false; int opti = 0; while (opti < args.length) { @@ -6808,6 +6807,8 @@ public class WindowManagerService extends IWindowManager.Stub opti++; if ("-a".equals(opt)) { dumpAll = true; + } else if ("--proto".equals(opt)) { + useProto = true; } else if ("-h".equals(opt)) { pw.println("Window manager dump options:"); pw.println(" [-a] [-h] [cmd] ..."); @@ -6827,12 +6828,21 @@ public class WindowManagerService extends IWindowManager.Stub pw.println(" \"visible\" for the visible windows."); pw.println(" \"visible-apps\" for the visible app windows."); pw.println(" -a: include all available server state."); + pw.println(" --proto: output dump in protocol buffer format."); return; } else { pw.println("Unknown argument: " + opt + "; use -h for help"); } } + if (useProto) { + final ProtoOutputStream proto = new ProtoOutputStream(fd); + synchronized (mWindowMap) { + writeToProtoLocked(proto); + } + proto.flush(); + return; + } // Is the caller requesting to dump a particular piece of data? if (opti < args.length) { String cmd = args[opti]; diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 12abe39b082b..e8e40a78554c 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -16,12 +16,10 @@ package com.android.server.wm; -import static android.app.ActivityManager.ENABLE_TASK_SNAPSHOTS; import static android.app.ActivityManager.StackId; import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; import static android.app.ActivityManager.StackId.INVALID_STACK_ID; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; -import static android.app.ActivityManager.isLowRamDeviceStatic; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT; @@ -38,7 +36,6 @@ import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; import static android.view.WindowManager.LayoutParams.FLAG_SCALED; -import static android.view.WindowManager.LayoutParams.FLAG_SECURE; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; import static android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON; @@ -102,6 +99,23 @@ import static com.android.server.wm.WindowStateAnimator.COMMIT_DRAW_PENDING; import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING; import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN; import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW; +import static com.android.server.wm.proto.IdentifierProto.HASH_CODE; +import static com.android.server.wm.proto.IdentifierProto.TITLE; +import static com.android.server.wm.proto.IdentifierProto.USER_ID; +import static com.android.server.wm.proto.WindowStateProto.ANIMATING_EXIT; +import static com.android.server.wm.proto.WindowStateProto.ANIMATOR; +import static com.android.server.wm.proto.WindowStateProto.ATTRIBUTES; +import static com.android.server.wm.proto.WindowStateProto.CHILD_WINDOWS; +import static com.android.server.wm.proto.WindowStateProto.CONTAINING_FRAME; +import static com.android.server.wm.proto.WindowStateProto.CONTENT_FRAME; +import static com.android.server.wm.proto.WindowStateProto.CONTENT_INSETS; +import static com.android.server.wm.proto.WindowStateProto.DISPLAY_ID; +import static com.android.server.wm.proto.WindowStateProto.FRAME; +import static com.android.server.wm.proto.WindowStateProto.GIVEN_CONTENT_INSETS; +import static com.android.server.wm.proto.WindowStateProto.IDENTIFIER; +import static com.android.server.wm.proto.WindowStateProto.PARENT_FRAME; +import static com.android.server.wm.proto.WindowStateProto.STACK_ID; +import static com.android.server.wm.proto.WindowStateProto.SURFACE_INSETS; import android.app.AppOpsManager; import android.content.Context; @@ -121,10 +135,11 @@ import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; import android.os.WorkSource; -import android.util.MergedConfiguration; import android.util.DisplayMetrics; +import android.util.MergedConfiguration; import android.util.Slog; import android.util.TimeUtils; +import android.util.proto.ProtoOutputStream; import android.view.DisplayInfo; import android.view.Gravity; import android.view.IApplicationToken; @@ -164,9 +179,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // to capture touch events in that area. static final int RESIZE_HANDLE_WIDTH_IN_DP = 30; - private static final boolean DEBUG_DISABLE_SAVING_SURFACES = false || - ENABLE_TASK_SNAPSHOTS; - final WindowManagerService mService; final WindowManagerPolicy mPolicy; final Context mContext; @@ -503,15 +515,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP /** When true this window can be displayed on screens owther than mOwnerUid's */ private boolean mShowToOwnerOnly; - // Whether the window has a saved surface from last pause, which can be - // used to start an entering animation earlier. - private boolean mSurfaceSaved = false; - - // Whether we're performing an entering animation with a saved surface. This flag is - // true during the time we're showing a window with a previously saved surface. It's - // cleared when surface is destroyed, saved, or re-drawn by the app. - private boolean mAnimatingWithSavedSurface; - // Whether the window was visible when we set the app to invisible last time. WM uses // this as a hint to restore the surface (if available) for early animation next time // the app is brought visible. @@ -567,8 +570,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP */ boolean mSeamlesslyRotated = false; - private static final Region sEmptyRegion = new Region(); - /** * Surface insets from the previous call to relayout(), used to track * if we are changing the Surface insets. @@ -734,6 +735,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return mOwnerCanAddInternalSystemWindow; } + @Override + public boolean canAcquireSleepToken() { + return mSession.mCanAcquireSleepToken; + } + /** * Subtracts the insets calculated by intersecting {@param layoutFrame} with {@param insetFrame} * from {@param frame}. In other words, it applies the insets that would result if @@ -1347,10 +1353,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP @Override boolean hasContentToDisplay() { - // If we're animating with a saved surface, we're already visible. - // Return true so that the alpha doesn't get cleared. - if (!mAppFreezing && isDrawnLw() - && (mViewVisibility == View.VISIBLE || isAnimatingWithSavedSurface() + if (!mAppFreezing && isDrawnLw() && (mViewVisibility == View.VISIBLE || (mWinAnimator.isAnimationSet() && !mService.mAppTransition.isTransitionSet()))) { return true; } @@ -1438,19 +1441,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP /** * Whether this window's drawn state might affect the drawn states of the app token. * - * @param visibleOnly Whether we should consider only the windows that's currently - * visible in layout. If true, windows that has not relayout to VISIBLE - * would always return false. - * * @return true if the window should be considered while evaluating allDrawn flags. */ - boolean mightAffectAllDrawn(boolean visibleOnly) { - final boolean isViewVisible = (mAppToken == null || !mAppToken.isClientHidden()) - && (mViewVisibility == View.VISIBLE) && !mWindowRemovalAllowed; - return (isOnScreen() && (!visibleOnly || isViewVisible) - || mWinAnimator.mAttrType == TYPE_BASE_APPLICATION - || mWinAnimator.mAttrType == TYPE_DRAWN_APPLICATION) - && !mAnimatingExit && !mDestroying; + boolean mightAffectAllDrawn() { + final boolean isAppType = mWinAnimator.mAttrType == TYPE_BASE_APPLICATION + || mWinAnimator.mAttrType == TYPE_DRAWN_APPLICATION; + return (isOnScreen() || isAppType) && !mAnimatingExit && !mDestroying; } /** @@ -1479,7 +1475,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // TODO: Another visibility method that was added late in the release to minimize risk. @Override public boolean canAffectSystemUiFlags() { - final boolean shown = mWinAnimator.getShown(); + final boolean shown = mWinAnimator.getShown() && mWinAnimator.mShownAlpha > 0f; // We only consider the app to be exiting when the animation has started. After the app // transition is executed the windows are marked exiting before the new windows have been @@ -1644,10 +1640,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP @Override void onResize() { - // Some windows won't go through the resizing process, if they don't have a surface, so - // destroy all saved surfaces here. - destroySavedSurface(); - final ArrayList<WindowState> resizingWindows = mService.mResizingWindows; if (mHasSurface && !resizingWindows.contains(this)) { if (DEBUG_RESIZE) Slog.d(TAG, "onResize: Resizing " + this); @@ -1711,10 +1703,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP final boolean adjustedForMinimizedDockOrIme = task != null && (task.mStack.isAdjustedForMinimizedDockedStack() || task.mStack.isAdjustedForIme()); - if (mService.okToAnimate() + if (mToken.okToAnimate() && (mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0 && !isDragResizing() && !adjustedForMinimizedDockOrIme - && (task == null || getTask().mStack.hasMovementAnimations()) + && getWindowConfiguration().hasMovementAnimations() && !mWinAnimator.mLastHidden) { mWinAnimator.setMoveAnimation(left, top); } @@ -1880,7 +1872,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // First, see if we need to run an animation. If we do, we have to hold off on removing the // window until the animation is done. If the display is frozen, just remove immediately, // since the animation wouldn't be seen. - if (mHasSurface && mService.okToAnimate()) { + if (mHasSurface && mToken.okToAnimate()) { if (mWillReplaceWindow) { // This window is going to be replaced. We need to keep it around until the new one // gets added, then we will get rid of this one. @@ -1896,19 +1888,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return; } - if (isAnimatingWithSavedSurface() && !mAppToken.allDrawnExcludingSaved) { - // We started enter animation early with a saved surface, now the app asks to remove - // this window. If we remove it now and the app is not yet drawn, we'll show a - // flicker. Delay the removal now until it's really drawn. - if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, - "removeWindowLocked: delay removal of " + this + " due to early animation"); - // Do not set mAnimatingExit to true here, it will cause the surface to be hidden - // immediately after the enter animation is done. If the app is not yet drawn then - // it will show up as a flicker. - setupWindowForRemoveOnExit(); - Binder.restoreCallingIdentity(origId); - return; - } // If we are not currently running the exit animation, we need to see about starting one wasVisible = isWinVisibleLw(); @@ -2315,7 +2294,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mLayoutNeeded = true; } - if (isDrawnLw() && mService.okToAnimate()) { + if (isDrawnLw() && mToken.okToAnimate()) { mWinAnimator.applyEnterAnimationLocked(); } } @@ -2399,7 +2378,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP * because we want to preserve its location on screen to be re-activated later when the user * interacts with it. */ - boolean shouldKeepVisibleDeadAppWindow() { + private boolean shouldKeepVisibleDeadAppWindow() { if (!isWinVisibleLw() || mAppToken == null || mAppToken.isClientHidden()) { // Not a visible app window or the app isn't dead. return false; @@ -2417,8 +2396,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return false; } - final TaskStack stack = getStack(); - return stack != null && StackId.keepVisibleDeadAppWindowOnScreen(stack.mStackId); + return getWindowConfiguration().keepVisibleDeadAppWindowOnScreen(); } /** @return true if this window desires key events. */ @@ -2471,7 +2449,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (doAnimation) { if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility=" + mPolicyVisibility + " mAnimation=" + mWinAnimator.mAnimation); - if (!mService.okToAnimate()) { + if (!mToken.okToAnimate()) { doAnimation = false; } else if (mPolicyVisibility && mWinAnimator.mAnimation == null) { // Check for the case where we are currently visible and @@ -2501,7 +2479,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP boolean hideLw(boolean doAnimation, boolean requestAnim) { if (doAnimation) { - if (!mService.okToAnimate()) { + if (!mToken.okToAnimate()) { doAnimation = false; } } @@ -2612,10 +2590,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return mAnimatingExit || (mService.mClosingApps.contains(mAppToken)); } - boolean isAnimatingWithSavedSurface() { - return mAnimatingWithSavedSurface; - } - @Override boolean isAnimating() { if (mWinAnimator.isAnimationSet() || mAnimatingExit) { @@ -2624,48 +2598,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return super.isAnimating(); } - boolean isAnimatingInvisibleWithSavedSurface() { - if (mAnimatingWithSavedSurface - && (mViewVisibility != View.VISIBLE || mWindowRemovalAllowed)) { - return true; - } - for (int i = mChildren.size() - 1; i >= 0; --i) { - final WindowState c = mChildren.get(i); - if (c.isAnimatingInvisibleWithSavedSurface()) { - return true; - } - } - return false; - } - - void stopUsingSavedSurface() { - for (int i = mChildren.size() - 1; i >= 0; --i) { - final WindowState c = mChildren.get(i); - c.stopUsingSavedSurface(); - } - - if (!isAnimatingInvisibleWithSavedSurface()) { - return; - } - - if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.d(TAG, "stopUsingSavedSurface: " + this); - clearAnimatingWithSavedSurface(); - mDestroying = true; - mWinAnimator.hide("stopUsingSavedSurface"); - getDisplayContent().mWallpaperController.hideWallpapers(this); - } - - void markSavedSurfaceExiting() { - if (isAnimatingInvisibleWithSavedSurface()) { - mAnimatingExit = true; - mWinAnimator.mAnimating = true; - } - for (int i = mChildren.size() - 1; i >= 0; --i) { - final WindowState c = mChildren.get(i); - c.markSavedSurfaceExiting(); - } - } - void addWinAnimatorToList(ArrayList<WindowStateAnimator> animators) { animators.add(mWinAnimator); @@ -2704,25 +2636,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } - public void setVisibleBeforeClientHidden() { - mWasVisibleBeforeClientHidden |= - (mViewVisibility == View.VISIBLE || mAnimatingWithSavedSurface); - - super.setVisibleBeforeClientHidden(); - } - - public void clearWasVisibleBeforeClientHidden() { - mWasVisibleBeforeClientHidden = false; - for (int i = mChildren.size() - 1; i >= 0; --i) { - final WindowState c = mChildren.get(i); - c.clearWasVisibleBeforeClientHidden(); - } - } - - public boolean wasVisibleBeforeClientHidden() { - return mWasVisibleBeforeClientHidden; - } - void onStartFreezingScreen() { mAppFreezing = true; for (int i = mChildren.size() - 1; i >= 0; --i) { @@ -2755,48 +2668,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return true; } - private boolean shouldSaveSurface() { - if (mWinAnimator.mSurfaceController == null) { - // Don't bother if the surface controller is gone for any reason. - return false; - } - - if (!mWasVisibleBeforeClientHidden) { - return false; - } - - if ((mAttrs.flags & FLAG_SECURE) != 0) { - // We don't save secure surfaces since their content shouldn't be shown while the app - // isn't on screen and content might leak through during the transition animation with - // saved surface. - return false; - } - - if (isLowRamDeviceStatic()) { - // Don't save surfaces on Svelte devices. - return false; - } - - final Task task = getTask(); - final AppWindowToken taskTop = task.getTopVisibleAppToken(); - if (taskTop != null && taskTop != mAppToken) { - // Don't save if the window is not the topmost window. - return false; - } - - if (mResizedWhileGone) { - // Somebody resized our window while we were gone for layout, which means that the - // client got an old size, so we have an outdated surface here. - return false; - } - - if (DEBUG_DISABLE_SAVING_SURFACES) { - return false; - } - - return mAppToken.shouldSaveSurface(); - } - boolean destroySurface(boolean cleanupOnResume, boolean appStopped) { boolean destroyedSomething = false; for (int i = mChildren.size() - 1; i >= 0; --i) { @@ -2818,7 +2689,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP + " win.mWindowRemovalAllowed=" + mWindowRemovalAllowed + " win.mRemoveOnExit=" + mRemoveOnExit); if (!cleanupOnResume || mRemoveOnExit) { - destroyOrSaveSurfaceUnchecked(); + destroySurfaceUnchecked(); } if (mRemoveOnExit) { removeImmediately(); @@ -2836,156 +2707,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // Destroy or save the application surface without checking // various indicators of whether the client has released the surface. // This is in general unsafe, and most callers should use {@link #destroySurface} - void destroyOrSaveSurfaceUnchecked() { - mSurfaceSaved = shouldSaveSurface(); - if (mSurfaceSaved) { - if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) { - Slog.v(TAG, "Saving surface: " + this); - } - // Previous user of the surface may have set a transparent region signaling a portion - // doesn't need to be composited, so reset to default empty state. - mSession.setTransparentRegion(mClient, sEmptyRegion); - - mWinAnimator.hide("saved surface"); - mWinAnimator.mDrawState = WindowStateAnimator.NO_SURFACE; - setHasSurface(false); - // The client should have disconnected at this point, but if it doesn't, - // we need to make sure it's disconnected. Otherwise when we reuse the surface - // the client can't reconnect to the buffer queue, and rendering will fail. - if (mWinAnimator.mSurfaceController != null) { - mWinAnimator.mSurfaceController.disconnectInTransaction(); - } - mAnimatingWithSavedSurface = false; - } else { - mWinAnimator.destroySurfaceLocked(); - } + void destroySurfaceUnchecked() { + mWinAnimator.destroySurfaceLocked(); + // Clear animating flags now, since the surface is now gone. (Note this is true even // if the surface is saved, to outside world the surface is still NO_SURFACE.) mAnimatingExit = false; } - void destroySavedSurface() { - for (int i = mChildren.size() - 1; i >= 0; --i) { - final WindowState c = mChildren.get(i); - c.destroySavedSurface(); - } - - if (mSurfaceSaved) { - if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "Destroying saved surface: " + this); - mWinAnimator.destroySurfaceLocked(); - mSurfaceSaved = false; - } - mWasVisibleBeforeClientHidden = false; - } - - /** Returns -1 if there are no interesting windows or number of interesting windows not drawn.*/ - int restoreSavedSurfaceForInterestingWindow() { - int interestingNotDrawn = -1; - for (int i = mChildren.size() - 1; i >= 0; --i) { - final WindowState c = mChildren.get(i); - final int childInterestingNotDrawn = c.restoreSavedSurfaceForInterestingWindow(); - if (childInterestingNotDrawn != -1) { - if (interestingNotDrawn == -1) { - interestingNotDrawn = childInterestingNotDrawn; - } else { - interestingNotDrawn += childInterestingNotDrawn; - } - } - } - - if (mAttrs.type == TYPE_APPLICATION_STARTING - || mAppDied || !wasVisibleBeforeClientHidden() - || (mAppToken.mAppAnimator.freezingScreen && mAppFreezing)) { - // Window isn't interesting... - return interestingNotDrawn; - } - - restoreSavedSurface(); - - if (!isDrawnLw()) { - if (interestingNotDrawn == -1) { - interestingNotDrawn = 1; - } else { - interestingNotDrawn++; - } - } - return interestingNotDrawn; - } - - /** Returns true if the saved surface was restored. */ - boolean restoreSavedSurface() { - if (!mSurfaceSaved) { - return false; - } - - // Sometimes we save surfaces due to layout invisible directly after rotation occurs. - // However this means the surface was never laid out in the new orientation. - // We can only restore to the last rotation we were laid out as visible in. - if (mLastVisibleLayoutRotation != getDisplayContent().getRotation()) { - destroySavedSurface(); - return false; - } - mSurfaceSaved = false; - - if (mWinAnimator.mSurfaceController != null) { - setHasSurface(true); - mWinAnimator.mDrawState = READY_TO_SHOW; - mAnimatingWithSavedSurface = true; - - requestUpdateWallpaperIfNeeded(); - - if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) { - Slog.v(TAG, "Restoring saved surface: " + this); - } - } else { - // mSurfaceController shouldn't be null if mSurfaceSaved was still true at - // this point. Even if we destroyed the saved surface because of rotation - // or resize, mSurfaceSaved flag should have been cleared. So this is a wtf. - Slog.wtf(TAG, "Failed to restore saved surface: surface gone! " + this); - } - - return true; - } - - boolean canRestoreSurface() { - if (mWasVisibleBeforeClientHidden && mSurfaceSaved) { - return true; - } - - for (int i = mChildren.size() - 1; i >= 0; --i) { - final WindowState c = mChildren.get(i); - if (c.canRestoreSurface()) { - return true; - } - } - - return false; - } - - boolean hasSavedSurface() { - return mSurfaceSaved; - } - - void clearHasSavedSurface() { - mSurfaceSaved = false; - mAnimatingWithSavedSurface = false; - if (mWasVisibleBeforeClientHidden) { - mAppToken.destroySavedSurfaces(); - } - } - - boolean clearAnimatingWithSavedSurface() { - if (mAnimatingWithSavedSurface) { - // App has drawn something to its windows, we're no longer animating with - // the saved surfaces. - if (DEBUG_ANIM) Slog.d(TAG, - "clearAnimatingWithSavedSurface(): win=" + this); - mAnimatingWithSavedSurface = false; - return true; - } - return false; - } - @Override public boolean isDefaultDisplay() { final DisplayContent displayContent = getDisplayContent(); @@ -3186,7 +2915,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // one or more frame to wrong offset. So here we send fullscreen backdrop if either // isDragResizing() or isDragResizeChanged() is true. boolean resizing = isDragResizing() || isDragResizeChanged(); - if (StackId.useWindowFrameForBackdrop(getStackId()) || !resizing) { + if (getWindowConfiguration().useWindowFrameForBackdrop() || !resizing) { return frame; } final DisplayInfo displayInfo = getDisplayInfo(); @@ -3390,6 +3119,38 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP || (isChildWindow() && getParentWindow().isDockedResizing()); } + void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + writeIdentifierToProto(proto, IDENTIFIER); + proto.write(DISPLAY_ID, getDisplayId()); + proto.write(STACK_ID, getStackId()); + mAttrs.writeToProto(proto, ATTRIBUTES); + mGivenContentInsets.writeToProto(proto, GIVEN_CONTENT_INSETS); + mFrame.writeToProto(proto, FRAME); + mContainingFrame.writeToProto(proto, CONTAINING_FRAME); + mParentFrame.writeToProto(proto, PARENT_FRAME); + mContentFrame.writeToProto(proto, CONTENT_FRAME); + mContentInsets.writeToProto(proto, CONTENT_INSETS); + mAttrs.surfaceInsets.writeToProto(proto, SURFACE_INSETS); + mWinAnimator.writeToProto(proto, ANIMATOR); + proto.write(ANIMATING_EXIT, mAnimatingExit); + for (int i = 0; i < mChildren.size(); i++) { + mChildren.get(i).writeToProto(proto, CHILD_WINDOWS); + } + proto.end(token); + } + + void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + proto.write(HASH_CODE, System.identityHashCode(this)); + proto.write(USER_ID, UserHandle.getUserId(mOwnerUid)); + final CharSequence title = getWindowTag(); + if (title != null) { + proto.write(TITLE, title.toString()); + } + proto.end(token); + } + void dump(PrintWriter pw, String prefix, boolean dumpAll) { final TaskStack stack = getStack(); pw.print(prefix); pw.print("mDisplayId="); pw.print(getDisplayId()); @@ -3433,12 +3194,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (mAppToken != null) { pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken); pw.print(prefix); pw.print(" isAnimatingWithSavedSurface()="); - pw.print(isAnimatingWithSavedSurface()); pw.print(" mAppDied=");pw.print(mAppDied); pw.print(prefix); pw.print("drawnStateEvaluated="); pw.print(getDrawnStateEvaluated()); pw.print(prefix); pw.print("mightAffectAllDrawn="); - pw.println(mightAffectAllDrawn(false /*visibleOnly*/)); + pw.println(mightAffectAllDrawn()); } pw.print(prefix); pw.print("mViewVisibility=0x"); pw.print(Integer.toHexString(mViewVisibility)); @@ -3489,7 +3249,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface); pw.print(" mShownPosition="); mShownPosition.printShortString(pw); pw.print(" isReadyForDisplay()="); pw.print(isReadyForDisplay()); - pw.print(" hasSavedSurface()="); pw.print(hasSavedSurface()); pw.print(" mWindowRemovalAllowed="); pw.println(mWindowRemovalAllowed); if (dumpAll) { pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw); @@ -3972,6 +3731,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP windowInfo.type = mAttrs.type; windowInfo.layer = mLayer; windowInfo.token = mClient.asBinder(); + if (mAppToken != null) { + windowInfo.activityToken = mAppToken.appToken.asBinder(); + } windowInfo.title = mAttrs.accessibilityTitle; windowInfo.accessibilityIdOfAnchor = mAttrs.accessibilityIdOfAnchor; windowInfo.focused = isFocused(); @@ -4544,11 +4306,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP && getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER; result |= freeformResizing ? RELAYOUT_RES_DRAG_RESIZING_FREEFORM : 0; result |= dockedResizing ? RELAYOUT_RES_DRAG_RESIZING_DOCKED : 0; - if (isAnimatingWithSavedSurface()) { - // If we're animating with a saved surface now, request client to report draw. - // We still need to know when the real thing is drawn. - result |= RELAYOUT_RES_FIRST_TIME; - } return result; } diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 86265c297b1b..ddb8df24ff92 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -16,7 +16,6 @@ package com.android.server.wm; -import static android.app.ActivityManager.StackId; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; import static android.view.WindowManager.LayoutParams.FLAG_SCALED; @@ -46,7 +45,10 @@ import static com.android.server.wm.WindowManagerService.localLOGV; import static com.android.server.wm.WindowManagerService.logWithStack; import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE; import static com.android.server.wm.WindowSurfacePlacer.SET_TURN_ON_SCREEN; +import static com.android.server.wm.proto.WindowStateAnimatorProto.LAST_CLIP_RECT; +import static com.android.server.wm.proto.WindowStateAnimatorProto.SURFACE; +import android.app.WindowConfiguration; import android.content.Context; import android.graphics.Matrix; import android.graphics.PixelFormat; @@ -57,6 +59,7 @@ import android.graphics.Region; import android.os.Debug; import android.os.Trace; import android.util.Slog; +import android.util.proto.ProtoOutputStream; import android.view.DisplayInfo; import android.view.MagnificationSpec; import android.view.Surface.OutOfResourcesException; @@ -343,7 +346,7 @@ class WindowStateAnimator { mAnimation.cancel(); mAnimation = null; mLocalAnimating = false; - mWin.destroyOrSaveSurfaceUnchecked(); + mWin.destroySurfaceUnchecked(); } } @@ -369,7 +372,7 @@ class WindowStateAnimator { // we just started or just stopped animating by comparing mWasAnimating with isAnimationSet(). mWasAnimating = mAnimating; final DisplayContent displayContent = mWin.getDisplayContent(); - if (displayContent != null && mService.okToAnimate()) { + if (mWin.mToken.okToAnimate()) { // We will run animations as long as the display isn't frozen. if (mWin.isDrawnLw() && mAnimation != null) { @@ -503,7 +506,7 @@ class WindowStateAnimator { + drawStateToString()); } - boolean layoutNeeded = mWin.clearAnimatingWithSavedSurface(); + boolean layoutNeeded = false; if (mDrawState == DRAW_PENDING) { if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION) @@ -622,11 +625,6 @@ class WindowStateAnimator { WindowSurfaceController createSurfaceLocked(int windowType, int ownerUid) { final WindowState w = mWin; - if (w.restoreSavedSurface()) { - if (DEBUG_ANIM) Slog.i(TAG, - "createSurface: " + this + ": called when we had a saved surface"); - return mSurfaceController; - } if (mSurfaceController != null) { return mSurfaceController; @@ -785,8 +783,7 @@ class WindowStateAnimator { } boolean hasSurface() { - return !mWin.hasSavedSurface() - && mSurfaceController != null && mSurfaceController.hasSurface(); + return mSurfaceController != null && mSurfaceController.hasSurface(); } void destroySurfaceLocked() { @@ -797,8 +794,6 @@ class WindowStateAnimator { } } - mWin.clearHasSavedSurface(); - if (mSurfaceController == null) { return; } @@ -1142,7 +1137,7 @@ class WindowStateAnimator { final TaskStack stack = w.getTask().mStack; stack.getDimBounds(finalClipRect); - if (StackId.tasksAreFloating(stack.mStackId)) { + if (stack.getWindowConfiguration().tasksAreFloating()) { w.expandForSurfaceInsets(finalClipRect); } @@ -1160,10 +1155,10 @@ class WindowStateAnimator { transform.postScale(spec.scale, spec.scale); transform.postTranslate(-spec.offsetX, -spec.offsetY); transform.mapRect(finalCrop); - finalClipRect.top = (int)finalCrop.top; - finalClipRect.left = (int)finalCrop.left; - finalClipRect.right = (int)finalClipRect.right; - finalClipRect.bottom = (int)finalClipRect.bottom; + finalClipRect.top = (int) finalCrop.top; + finalClipRect.left = (int) finalCrop.left; + finalClipRect.right = (int) finalCrop.right; + finalClipRect.bottom = (int) finalCrop.bottom; } return true; @@ -1321,8 +1316,8 @@ class WindowStateAnimator { // We need to do some acrobatics with surface position, because their clip region is // relative to the inside of the surface, but the stack bounds aren't. - if (StackId.hasWindowShadow(stack.mStackId) - && !StackId.isTaskResizeAllowed(stack.mStackId)) { + final WindowConfiguration winConfig = w.getWindowConfiguration(); + if (winConfig.hasWindowShadow() && !winConfig.canResizeTask()) { // The windows in this stack display drop shadows and the fill the entire stack // area. Adjust the stack bounds we will use to cropping take into account the // offsets we use to display the drop shadow so it doesn't get cropped. @@ -1646,14 +1641,17 @@ class WindowStateAnimator { // hidden while the screen is turning off. // TODO(b/63773439): These cases should be eliminated, though we probably still // want to process mTurnOnScreen in this way for clarity. - if (mWin.mTurnOnScreen && mWin.mAppToken.canTurnScreenOn()) { + if (mWin.mTurnOnScreen && + (mWin.mAppToken == null || mWin.mAppToken.canTurnScreenOn())) { if (DEBUG_VISIBILITY) Slog.v(TAG, "Show surface turning screen on: " + mWin); mWin.mTurnOnScreen = false; // The window should only turn the screen on once per resume, but // prepareSurfaceLocked can be called multiple times. Set canTurnScreenOn to // false so the window doesn't turn the screen on again during this resume. - mWin.mAppToken.setCanTurnScreenOn(false); + if (mWin.mAppToken != null) { + mWin.mAppToken.setCanTurnScreenOn(false); + } mAnimator.mBulkUpdateParams |= SET_TURN_ON_SCREEN; } } @@ -1757,8 +1755,7 @@ class WindowStateAnimator { * @return Returns true if the surface was successfully shown. */ private boolean showSurfaceRobustlyLocked() { - final Task task = mWin.getTask(); - if (task != null && StackId.windowsAreScaleable(task.mStack.mStackId)) { + if (mWin.getWindowConfiguration().windowsAreScaleable()) { mSurfaceController.forceScaleableInTransaction(true); } @@ -1812,7 +1809,7 @@ class WindowStateAnimator { // artifacts when we unfreeze the display if some different animation // is running. Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WSA#applyAnimationLocked"); - if (mService.okToAnimate()) { + if (mWin.mToken.okToAnimate()) { int anim = mPolicy.selectAnimationLw(mWin, transit); int attr = -1; Animation a = null; @@ -1885,6 +1882,15 @@ class WindowStateAnimator { mAnimation = newAnimation; } + void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + mLastClipRect.writeToProto(proto, LAST_CLIP_RECT); + if (mSurfaceController != null) { + mSurfaceController.writeToProto(proto, SURFACE); + } + proto.end(token); + } + public void dump(PrintWriter pw, String prefix, boolean dumpAll) { if (mAnimating || mLocalAnimating || mAnimationIsEntrance || mAnimation != null) { diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java index 110d5cb90f45..2e1e3f763a15 100644 --- a/services/core/java/com/android/server/wm/WindowSurfaceController.java +++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java @@ -17,6 +17,8 @@ package com.android.server.wm; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; +import static android.view.Surface.SCALING_MODE_SCALE_TO_WINDOW; + import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC; import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS; import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS; @@ -24,7 +26,8 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; -import static android.view.Surface.SCALING_MODE_SCALE_TO_WINDOW; +import static com.android.server.wm.proto.WindowSurfaceControllerProto.LAYER; +import static com.android.server.wm.proto.WindowSurfaceControllerProto.SHOWN; import android.graphics.Point; import android.graphics.PointF; @@ -33,6 +36,7 @@ import android.graphics.Region; import android.os.IBinder; import android.os.Debug; import android.os.Trace; +import android.util.proto.ProtoOutputStream; import android.view.Surface; import android.view.SurfaceControl; import android.view.SurfaceSession; @@ -534,6 +538,12 @@ class WindowSurfaceController { return mSurfaceH; } + void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + proto.write(SHOWN, mSurfaceShown); + proto.write(LAYER, mSurfaceLayer); + proto.end(token); + } public void dump(PrintWriter pw, String prefix, boolean dumpAll) { if (dumpAll) { diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index 581b0447dafc..88625d35f9b4 100644 --- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java +++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java @@ -2,7 +2,6 @@ package com.android.server.wm; import static android.app.ActivityManager.StackId.INVALID_STACK_ID; -import static android.app.ActivityManagerInternal.APP_TRANSITION_SAVED_SURFACE; import static android.app.ActivityManagerInternal.APP_TRANSITION_SNAPSHOT; import static android.app.ActivityManagerInternal.APP_TRANSITION_SPLASH_SCREEN; import static android.app.ActivityManagerInternal.APP_TRANSITION_WINDOWS_DRAWN; @@ -445,13 +444,6 @@ class WindowSurfacePlacer { for (int i = 0; i < appsCount; i++) { AppWindowToken wtoken = mService.mClosingApps.valueAt(i); - // If we still have some windows animating with saved surfaces that's - // either invisible or already removed, mark them exiting so that they - // are disposed of after the exit animation. These are not supposed to - // be shown, or are delayed removal until app is actually drawn (in which - // case the window will be removed after the animation). - wtoken.markSavedSurfaceExiting(); - final AppWindowAnimator appAnimator = wtoken.mAppAnimator; if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken); appAnimator.clearThumbnail(); @@ -539,8 +531,6 @@ class WindowSurfacePlacer { + wtoken.startingMoved + " isRelaunching()=" + wtoken.isRelaunching()); - final boolean drawnBeforeRestoring = wtoken.allDrawn; - wtoken.restoreSavedSurfaceForInterestingWindows(); final boolean allDrawn = wtoken.allDrawn && !wtoken.isRelaunching(); if (!allDrawn && !wtoken.startingDisplayed && !wtoken.startingMoved) { @@ -549,8 +539,7 @@ class WindowSurfacePlacer { final TaskStack stack = wtoken.getStack(); final int stackId = stack != null ? stack.mStackId : INVALID_STACK_ID; if (allDrawn) { - outReasons.put(stackId, drawnBeforeRestoring ? APP_TRANSITION_WINDOWS_DRAWN - : APP_TRANSITION_SAVED_SURFACE); + outReasons.put(stackId, APP_TRANSITION_WINDOWS_DRAWN); } else { outReasons.put(stackId, wtoken.startingData instanceof SplashScreenStartingData ? APP_TRANSITION_SPLASH_SCREEN diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index e3033c9c01a8..422615b10fc1 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -16,9 +16,9 @@ package com.android.server.wm; +import android.util.proto.ProtoOutputStream; import java.util.Comparator; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; -import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS; @@ -26,6 +26,8 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEME import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; +import static com.android.server.wm.proto.WindowTokenProto.HASH_CODE; +import static com.android.server.wm.proto.WindowTokenProto.WINDOWS; import android.os.Debug; import android.os.IBinder; @@ -261,6 +263,16 @@ class WindowToken extends WindowContainer<WindowState> { super.onDisplayChanged(dc); } + void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + proto.write(HASH_CODE, System.identityHashCode(this)); + for (int i = 0; i < mChildren.size(); i++) { + final WindowState w = mChildren.get(i); + w.writeToProto(proto, WINDOWS); + } + proto.end(token); + } + void dump(PrintWriter pw, String prefix) { pw.print(prefix); pw.print("windows="); pw.println(mChildren); pw.print(prefix); pw.print("windowType="); pw.print(windowType); @@ -288,4 +300,12 @@ class WindowToken extends WindowContainer<WindowState> { String getName() { return toString(); } + + boolean okToDisplay() { + return mDisplayContent != null && mDisplayContent.okToDisplay(); + } + + boolean okToAnimate() { + return mDisplayContent != null && mDisplayContent.okToAnimate(); + } } diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp index 0370490668ec..d2f374dd9e08 100644 --- a/services/core/jni/com_android_server_VibratorService.cpp +++ b/services/core/jni/com_android_server_VibratorService.cpp @@ -153,9 +153,9 @@ static jlong vibratorPerformEffect(JNIEnv*, jobject, jlong effect, jint strength if (status == Status::OK) { return lengthMs; } else if (status != Status::UNSUPPORTED_OPERATION) { - // Don't warn on UNSUPPORTED_OPERATION, that's a normal even and just means the motor - // doesn't have a pre-defined waveform to perform for it, so we should just fall back - // to the framework waveforms. + // Don't warn on UNSUPPORTED_OPERATION, that's a normal event and just means the motor + // doesn't have a pre-defined waveform to perform for it, so we should just give the + // opportunity to fall back to the framework waveforms. ALOGE("Failed to perform haptic effect: effect=%" PRId64 ", strength=%" PRId32 ", error=%" PRIu32 ").", static_cast<int64_t>(effect), static_cast<int32_t>(strength), static_cast<uint32_t>(status)); diff --git a/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp b/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp index 87312f82d58a..f9cbd1601290 100644 --- a/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp +++ b/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp @@ -74,10 +74,9 @@ int conntrackSocket(unsigned groups) { hidl_handle handleFromFileDescriptor(base::unique_fd fd) { hidl_handle h; - NATIVE_HANDLE_DECLARE_STORAGE(storage, 0, 0); static constexpr int kNumFds = 1; static constexpr int kNumInts = 0; - native_handle_t *nh = native_handle_init(storage, kNumFds, kNumInts); + native_handle_t *nh = native_handle_create(kNumFds, kNumInts); nh->data[0] = fd.release(); static constexpr bool kTakeOwnership = true; diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 77ce7e5dd596..de6f002ebd66 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -48,7 +48,6 @@ import static android.app.admin.DevicePolicyManager.WIPE_EUICC; import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE; import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA; import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES; - import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_ADB; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW; import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; @@ -81,9 +80,9 @@ import android.app.admin.DevicePolicyManagerInternal; import android.app.admin.IDevicePolicyManager; import android.app.admin.NetworkEvent; import android.app.admin.PasswordMetrics; -import android.app.admin.SystemUpdateInfo; import android.app.admin.SecurityLog; import android.app.admin.SecurityLog.SecurityEvent; +import android.app.admin.SystemUpdateInfo; import android.app.admin.SystemUpdatePolicy; import android.app.backup.IBackupManager; import android.app.trust.TrustManager; @@ -94,12 +93,14 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; +import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; import android.content.pm.ParceledListSlice; +import android.content.pm.PermissionInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.StringParceledListSlice; @@ -9580,6 +9581,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { < android.os.Build.VERSION_CODES.M) { return false; } + if (!isRuntimePermission(permission)) { + return false; + } final PackageManager packageManager = mInjector.getPackageManager(); switch (grantState) { case DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED: { @@ -9606,6 +9610,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return true; } catch (SecurityException se) { return false; + } catch (NameNotFoundException e) { + return false; } finally { mInjector.binderRestoreCallingIdentity(ident); } @@ -9655,6 +9661,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + public boolean isRuntimePermission(String permissionName) throws NameNotFoundException { + final PackageManager packageManager = mInjector.getPackageManager(); + PermissionInfo permissionInfo = packageManager.getPermissionInfo(permissionName, 0); + return (permissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) + == PermissionInfo.PROTECTION_DANGEROUS; + } + @Override public boolean isProvisioningAllowed(String action, String packageName) { Preconditions.checkNotNull(packageName); @@ -11141,4 +11154,40 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { new ArrayList<>(getUserData(userId).mOwnerInstalledCaCerts)); } } + + @Override + public boolean clearApplicationUserData(ComponentName admin, String packageName, + IPackageDataObserver callback) { + Preconditions.checkNotNull(admin, "ComponentName is null"); + synchronized (this) { + getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + } + final int userId = UserHandle.getCallingUserId(); + + long ident = mInjector.binderClearCallingIdentity(); + try { + return ActivityManager.getService().clearApplicationUserData(packageName, callback, + userId); + } catch(RemoteException re) { + // Same process, should not happen. + } catch (SecurityException se) { + // This can happen e.g. for device admin packages, do not throw out the exception, + // because callers have no means to know beforehand for which packages this might + // happen. + Slog.w(LOG_TAG, "Not allowed to clear application user data for package " + packageName, + se); + } finally { + mInjector.binderRestoreCallingIdentity(ident); + } + + if (callback != null) { + try { + // If there was a throw above, we send back that removal failed + callback.onRemoveCompleted(packageName, false); + } catch (RemoteException re) { + // Caller is no longer available, ignore + } + } + return false; + } } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index a1b9099f8bab..57271fa10950 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -45,7 +45,7 @@ import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; import android.os.storage.IStorageManager; -import android.util.BootTimingsTraceLog; +import android.util.TimingsTraceLog; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Slog; @@ -121,7 +121,6 @@ import java.io.File; import java.io.IOException; import java.util.Locale; import java.util.Timer; -import java.util.TimerTask; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Future; @@ -135,8 +134,8 @@ public final class SystemServer { // Tag for timing measurement of non-main asynchronous operations. private static final String SYSTEM_SERVER_TIMING_ASYNC_TAG = SYSTEM_SERVER_TIMING_TAG + "Async"; - private static final BootTimingsTraceLog BOOT_TIMINGS_TRACE_LOG - = new BootTimingsTraceLog(SYSTEM_SERVER_TIMING_TAG, Trace.TRACE_TAG_SYSTEM_SERVER); + private static final TimingsTraceLog BOOT_TIMINGS_TRACE_LOG + = new TimingsTraceLog(SYSTEM_SERVER_TIMING_TAG, Trace.TRACE_TAG_SYSTEM_SERVER); private static final String ENCRYPTING_STATE = "trigger_restart_min_framework"; private static final String ENCRYPTED_STATE = "1"; @@ -638,7 +637,7 @@ public final class SystemServer { // Start sensor service in a separate thread. Completion should be checked // before using it. mSensorServiceStart = SystemServerInitThreadPool.get().submit(() -> { - BootTimingsTraceLog traceLog = new BootTimingsTraceLog( + TimingsTraceLog traceLog = new TimingsTraceLog( SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER); traceLog.traceBegin(START_SENSOR_SERVICE); startSensorService(); @@ -736,7 +735,7 @@ public final class SystemServer { mZygotePreload = SystemServerInitThreadPool.get().submit(() -> { try { Slog.i(TAG, SECONDARY_ZYGOTE_PRELOAD); - BootTimingsTraceLog traceLog = new BootTimingsTraceLog( + TimingsTraceLog traceLog = new TimingsTraceLog( SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER); traceLog.traceBegin(SECONDARY_ZYGOTE_PRELOAD); if (!Process.zygoteProcess.preloadDefault(Build.SUPPORTED_32_BIT_ABIS[0])) { @@ -829,9 +828,11 @@ public final class SystemServer { // because it need to connect to SensorManager. This have to start // after START_SENSOR_SERVICE is done. SystemServerInitThreadPool.get().submit(() -> { - traceBeginAndSlog(START_HIDL_SERVICES); + TimingsTraceLog traceLog = new TimingsTraceLog( + SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER); + traceLog.traceBegin(START_HIDL_SERVICES); startHidlServices(); - traceEnd(); + traceLog.traceEnd(); }, START_HIDL_SERVICES); if (!disableVrManager) { @@ -1330,11 +1331,13 @@ public final class SystemServer { traceEnd(); } - if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_VOICE_RECOGNIZERS)) { - traceBeginAndSlog("StartVoiceRecognitionManager"); - mSystemServiceManager.startService(VOICE_RECOGNITION_MANAGER_SERVICE_CLASS); - traceEnd(); - } + // We need to always start this service, regardless of whether the + // FEATURE_VOICE_RECOGNIZERS feature is set, because it needs to take care + // of initializing various settings. It will internally modify its behavior + // based on that feature. + traceBeginAndSlog("StartVoiceRecognitionManager"); + mSystemServiceManager.startService(VOICE_RECOGNITION_MANAGER_SERVICE_CLASS); + traceEnd(); if (GestureLauncherService.isGestureLauncherEnabled(context.getResources())) { traceBeginAndSlog("StartGestureLauncher"); @@ -1686,7 +1689,7 @@ public final class SystemServer { if (!mOnlyCore) { webviewPrep = SystemServerInitThreadPool.get().submit(() -> { Slog.i(TAG, WEBVIEW_PREPARATION); - BootTimingsTraceLog traceLog = new BootTimingsTraceLog( + TimingsTraceLog traceLog = new TimingsTraceLog( SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER); traceLog.traceBegin(WEBVIEW_PREPARATION); ConcurrentUtils.waitForFutureNoInterrupt(mZygotePreload, "Zygote preload"); @@ -1842,7 +1845,7 @@ public final class SystemServer { // TODO: Switch from checkService to getService once it's always // in the build and should reliably be there. final IIncidentManager incident = IIncidentManager.Stub.asInterface( - ServiceManager.checkService("incident")); + ServiceManager.getService(Context.INCIDENT_SERVICE)); if (incident != null) incident.systemRunning(); } catch (Throwable e) { reportWtf("Notifying incident daemon running", e); diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java index 8cb2df761fbe..190b3a613ca1 100644 --- a/services/net/java/android/net/apf/ApfFilter.java +++ b/services/net/java/android/net/apf/ApfFilter.java @@ -180,6 +180,7 @@ public class ApfFilter { private static final int ETH_DEST_ADDR_OFFSET = 0; private static final int ETH_ETHERTYPE_OFFSET = 12; private static final int ETH_TYPE_MIN = 0x0600; + private static final int ETH_TYPE_MAX = 0xFFFF; private static final byte[] ETH_BROADCAST_MAC_ADDRESS = {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff }; // TODO: Make these offsets relative to end of link-layer header; don't include ETH_HEADER_LEN. @@ -232,6 +233,9 @@ public class ApfFilter { private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24; // Do not log ApfProgramEvents whose actual lifetimes was less than this. private static final int APF_PROGRAM_EVENT_LIFETIME_THRESHOLD = 2; + // Limit on the Black List size to cap on program usage for this + // TODO: Select a proper max length + private static final int APF_MAX_ETH_TYPE_BLACK_LIST_LEN = 20; private final ApfCapabilities mApfCapabilities; private final IpManager.Callback mIpManagerCallback; @@ -247,6 +251,8 @@ public class ApfFilter { @GuardedBy("this") private boolean mMulticastFilter; private final boolean mDrop802_3Frames; + private final int[] mEthTypeBlackList; + // Our IPv4 address, if we have just one, otherwise null. @GuardedBy("this") private byte[] mIPv4Address; @@ -257,12 +263,16 @@ public class ApfFilter { @VisibleForTesting ApfFilter(ApfCapabilities apfCapabilities, NetworkInterface networkInterface, IpManager.Callback ipManagerCallback, boolean multicastFilter, - boolean ieee802_3Filter, IpConnectivityLog log) { + boolean ieee802_3Filter, int[] ethTypeBlackList, IpConnectivityLog log) { mApfCapabilities = apfCapabilities; mIpManagerCallback = ipManagerCallback; mNetworkInterface = networkInterface; mMulticastFilter = multicastFilter; mDrop802_3Frames = ieee802_3Filter; + + // Now fill the black list from the passed array + mEthTypeBlackList = filterEthTypeBlackList(ethTypeBlackList); + mMetricsLog = log; // TODO: ApfFilter should not generate programs until IpManager sends provisioning success. @@ -278,6 +288,35 @@ public class ApfFilter { return mUniqueCounter++; } + @GuardedBy("this") + private static int[] filterEthTypeBlackList(int[] ethTypeBlackList) { + ArrayList<Integer> bl = new ArrayList<Integer>(); + + for (int p : ethTypeBlackList) { + // Check if the protocol is a valid ether type + if ((p < ETH_TYPE_MIN) || (p > ETH_TYPE_MAX)) { + continue; + } + + // Check if the protocol is not repeated in the passed array + if (bl.contains(p)) { + continue; + } + + // Check if list reach its max size + if (bl.size() == APF_MAX_ETH_TYPE_BLACK_LIST_LEN) { + Log.w(TAG, "Passed EthType Black List size too large (" + bl.size() + + ") using top " + APF_MAX_ETH_TYPE_BLACK_LIST_LEN + " protocols"); + break; + } + + // Now add the protocol to the list + bl.add(p); + } + + return bl.stream().mapToInt(Integer::intValue).toArray(); + } + /** * Attempt to start listening for RAs and, if RAs are received, generating and installing * filters to ignore useless RAs. @@ -891,6 +930,7 @@ public class ApfFilter { * Begin generating an APF program to: * <ul> * <li>Drop/Pass 802.3 frames (based on policy) + * <li>Drop packets with EtherType within the Black List * <li>Drop ARP requests not for us, if mIPv4Address is set, * <li>Drop IPv4 broadcast packets, except DHCP destined to our MAC, * <li>Drop IPv4 multicast packets, if mMulticastFilter, @@ -914,6 +954,8 @@ public class ApfFilter { // // if it's a 802.3 Frame (ethtype < 0x0600): // drop or pass based on configurations + // if it has a ether-type that belongs to the black list + // drop // if it's ARP: // insert ARP filter to drop or pass these appropriately // if it's IPv4: @@ -931,6 +973,11 @@ public class ApfFilter { gen.addJumpIfR0LessThan(ETH_TYPE_MIN, gen.DROP_LABEL); } + // Handle ether-type black list + for (int p : mEthTypeBlackList) { + gen.addJumpIfR0Equals(p, gen.DROP_LABEL); + } + // Add ARP filters: String skipArpFiltersLabel = "skipArpFilters"; gen.addJumpIfR0NotEquals(ETH_P_ARP, skipArpFiltersLabel); @@ -1115,7 +1162,7 @@ public class ApfFilter { */ public static ApfFilter maybeCreate(ApfCapabilities apfCapabilities, NetworkInterface networkInterface, IpManager.Callback ipManagerCallback, - boolean multicastFilter, boolean ieee802_3Filter) { + boolean multicastFilter, boolean ieee802_3Filter, int[] ethTypeBlackList) { if (apfCapabilities == null || networkInterface == null) return null; if (apfCapabilities.apfVersionSupported == 0) return null; if (apfCapabilities.maximumApfProgramSize < 512) { @@ -1132,7 +1179,7 @@ public class ApfFilter { return null; } return new ApfFilter(apfCapabilities, networkInterface, ipManagerCallback, - multicastFilter, ieee802_3Filter, new IpConnectivityLog()); + multicastFilter, ieee802_3Filter, ethTypeBlackList, new IpConnectivityLog()); } public synchronized void shutdown() { diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java index 46c1292e4f95..1d83897df750 100644 --- a/services/net/java/android/net/ip/IpManager.java +++ b/services/net/java/android/net/ip/IpManager.java @@ -36,6 +36,7 @@ import android.net.dhcp.DhcpClient; import android.net.metrics.IpConnectivityLog; import android.net.metrics.IpManagerEvent; import android.net.util.MultinetworkPolicyTracker; +import android.net.util.NetdService; import android.net.util.NetworkConstants; import android.net.util.SharedLog; import android.os.INetworkManagementService; @@ -66,9 +67,11 @@ import java.net.Inet6Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; +import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Objects; +import java.util.List; import java.util.Set; import java.util.StringJoiner; import java.util.function.Predicate; @@ -91,7 +94,6 @@ import java.util.stream.Collectors; */ public class IpManager extends StateMachine { private static final boolean DBG = false; - private static final boolean VDBG = false; // For message logging. private static final Class[] sMessageClasses = { IpManager.class, DhcpClient.class }; @@ -423,6 +425,10 @@ public class IpManager extends StateMachine { } public boolean isValid() { + if (ipAddresses.isEmpty()) { + return false; + } + // For every IP address, there must be at least one prefix containing that address. for (LinkAddress addr : ipAddresses) { if (!any(directlyConnectedRoutes, (p) -> p.contains(addr.getAddress()))) { @@ -459,14 +465,47 @@ public class IpManager extends StateMachine { return true; } + /** + * @return true if the given list of addressess and routes satisfies provisioning for this + * InitialConfiguration. LinkAddresses and RouteInfo objects are not compared with equality + * because addresses and routes seen by Netlink will contain additional fields like flags, + * interfaces, and so on. If this InitialConfiguration has no IP address specified, the + * provisioning check always fails. + * + * If the given list of routes is null, only addresses are taken into considerations. + */ + public boolean isProvisionedBy(List<LinkAddress> addresses, List<RouteInfo> routes) { + if (ipAddresses.isEmpty()) { + return false; + } + + for (LinkAddress addr : ipAddresses) { + if (!any(addresses, (addrSeen) -> addr.isSameAddressAs(addrSeen))) { + return false; + } + } + + if (routes != null) { + for (IpPrefix prefix : directlyConnectedRoutes) { + if (!any(routes, (routeSeen) -> isDirectlyConnectedRoute(routeSeen, prefix))) { + return false; + } + } + } + + return true; + } + + private static boolean isDirectlyConnectedRoute(RouteInfo route, IpPrefix prefix) { + return !route.hasGateway() && prefix.equals(route.getDestination()); + } + private static boolean isPrefixLengthCompliant(LinkAddress addr) { - return (addr.getAddress() instanceof Inet4Address) - || isCompliantIPv6PrefixLength(addr.getPrefixLength()); + return addr.isIPv4() || isCompliantIPv6PrefixLength(addr.getPrefixLength()); } private static boolean isPrefixLengthCompliant(IpPrefix prefix) { - return (prefix.getAddress() instanceof Inet4Address) - || isCompliantIPv6PrefixLength(prefix.getPrefixLength()); + return prefix.isIPv4() || isCompliantIPv6PrefixLength(prefix.getPrefixLength()); } private static boolean isCompliantIPv6PrefixLength(int prefixLength) { @@ -479,45 +518,25 @@ public class IpManager extends StateMachine { } private static boolean isIPv6GUA(LinkAddress addr) { - return (addr.getAddress() instanceof Inet6Address) && addr.isGlobalPreferred(); - } - - private static <T> boolean any(Iterable<T> coll, Predicate<T> fn) { - for (T t : coll) { - if (fn.test(t)) { - return true; - } - } - return false; - } - - private static <T> boolean all(Iterable<T> coll, Predicate<T> fn) { - return !any(coll, not(fn)); - } - - private static <T> Predicate<T> not(Predicate<T> fn) { - return (t) -> !fn.test(t); - } - - private static <T> String join(String delimiter, Collection<T> coll) { - return coll.stream().map(Object::toString).collect(Collectors.joining(delimiter)); + return addr.isIPv6() && addr.isGlobalPreferred(); } } public static final String DUMP_ARG = "ipmanager"; public static final String DUMP_ARG_CONFIRM = "confirm"; - private static final int CMD_STOP = 1; - private static final int CMD_START = 2; - private static final int CMD_CONFIRM = 3; - private static final int EVENT_PRE_DHCP_ACTION_COMPLETE = 4; + private static final int CMD_TERMINATE_AFTER_STOP = 1; + private static final int CMD_STOP = 2; + private static final int CMD_START = 3; + private static final int CMD_CONFIRM = 4; + private static final int EVENT_PRE_DHCP_ACTION_COMPLETE = 5; // Sent by NetlinkTracker to communicate netlink events. - private static final int EVENT_NETLINK_LINKPROPERTIES_CHANGED = 5; - private static final int CMD_UPDATE_TCP_BUFFER_SIZES = 6; - private static final int CMD_UPDATE_HTTP_PROXY = 7; - private static final int CMD_SET_MULTICAST_FILTER = 8; - private static final int EVENT_PROVISIONING_TIMEOUT = 9; - private static final int EVENT_DHCPACTION_TIMEOUT = 10; + private static final int EVENT_NETLINK_LINKPROPERTIES_CHANGED = 6; + private static final int CMD_UPDATE_TCP_BUFFER_SIZES = 7; + private static final int CMD_UPDATE_HTTP_PROXY = 8; + private static final int CMD_SET_MULTICAST_FILTER = 9; + private static final int EVENT_PROVISIONING_TIMEOUT = 10; + private static final int EVENT_DHCPACTION_TIMEOUT = 11; private static final int MAX_LOG_RECORDS = 500; private static final int MAX_PACKET_RECORDS = 100; @@ -549,6 +568,7 @@ public class IpManager extends StateMachine { private final LocalLog mConnectivityPacketLog; private final MessageHandlingLogger mMsgStateLogger; private final IpConnectivityLog mMetricsLog = new IpConnectivityLog(); + private final INetd mNetd; private NetworkInterface mNetworkInterface; @@ -568,14 +588,22 @@ public class IpManager extends StateMachine { public IpManager(Context context, String ifName, Callback callback) { this(context, ifName, callback, INetworkManagementService.Stub.asInterface( - ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE))); + ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)), + NetdService.getInstance()); } /** * An expanded constructor, useful for dependency injection. + * TODO: migrate all test users to mock IpManager directly and remove this ctor. */ public IpManager(Context context, String ifName, Callback callback, INetworkManagementService nwService) { + this(context, ifName, callback, nwService, NetdService.getInstance()); + } + + @VisibleForTesting + IpManager(Context context, String ifName, Callback callback, + INetworkManagementService nwService, INetd netd) { super(IpManager.class.getSimpleName() + "." + ifName); mTag = getName(); @@ -584,6 +612,7 @@ public class IpManager extends StateMachine { mClatInterfaceName = CLAT_PREFIX + ifName; mCallback = new LoggingCallbackWrapper(callback); mNwService = nwService; + mNetd = netd; mLog = new SharedLog(MAX_LOG_RECORDS, mTag); mConnectivityPacketLog = new LocalLog(MAX_PACKET_RECORDS); @@ -675,6 +704,16 @@ public class IpManager extends StateMachine { mMultinetworkPolicyTracker.start(); } + private void stopStateMachineUpdaters() { + try { + mNwService.unregisterObserver(mNetlinkTracker); + } catch (RemoteException e) { + logError("Couldn't unregister NetlinkTracker: %s", e); + } + + mMultinetworkPolicyTracker.shutdown(); + } + @Override protected void onQuitting() { mCallback.onQuit(); @@ -683,8 +722,7 @@ public class IpManager extends StateMachine { // Shut down this IpManager instance altogether. public void shutdown() { stop(); - mMultinetworkPolicyTracker.shutdown(); - quit(); + sendMessage(CMD_TERMINATE_AFTER_STOP); } public static ProvisioningConfiguration.Builder buildProvisioningConfiguration() { @@ -829,7 +867,7 @@ public class IpManager extends StateMachine { final String richerLogLine = getWhatToString(msg.what) + " " + logLine; mLog.log(richerLogLine); - if (VDBG) { + if (DBG) { Log.d(mTag, richerLogLine); } @@ -886,10 +924,20 @@ public class IpManager extends StateMachine { } // For now: use WifiStateMachine's historical notion of provisioned. - private static boolean isProvisioned(LinkProperties lp) { + @VisibleForTesting + static boolean isProvisioned(LinkProperties lp, InitialConfiguration config) { // For historical reasons, we should connect even if all we have is // an IPv4 address and nothing else. - return lp.isProvisioned() || lp.hasIPv4Address(); + if (lp.hasIPv4Address() || lp.isProvisioned()) { + return true; + } + if (config == null) { + return false; + } + + // When an InitialConfiguration is specified, ignore any difference with previous + // properties and instead check if properties observed match the desired properties. + return config.isProvisionedBy(lp.getLinkAddresses(), lp.getRoutes()); } // TODO: Investigate folding all this into the existing static function @@ -898,12 +946,11 @@ public class IpManager extends StateMachine { // object that is a correct and complete assessment of what changed, taking // account of the asymmetries described in the comments in this function. // Then switch to using it everywhere (IpReachabilityMonitor, etc.). - private ProvisioningChange compareProvisioning( - LinkProperties oldLp, LinkProperties newLp) { + private ProvisioningChange compareProvisioning(LinkProperties oldLp, LinkProperties newLp) { ProvisioningChange delta; - - final boolean wasProvisioned = isProvisioned(oldLp); - final boolean isProvisioned = isProvisioned(newLp); + InitialConfiguration config = mConfiguration != null ? mConfiguration.mInitialConfig : null; + final boolean wasProvisioned = isProvisioned(oldLp, config); + final boolean isProvisioned = isProvisioned(newLp, config); if (!wasProvisioned && isProvisioned) { delta = ProvisioningChange.GAINED_PROVISIONING; @@ -975,19 +1022,19 @@ public class IpManager extends StateMachine { private void dispatchCallback(ProvisioningChange delta, LinkProperties newLp) { switch (delta) { case GAINED_PROVISIONING: - if (VDBG) { Log.d(mTag, "onProvisioningSuccess()"); } + if (DBG) { Log.d(mTag, "onProvisioningSuccess()"); } recordMetric(IpManagerEvent.PROVISIONING_OK); mCallback.onProvisioningSuccess(newLp); break; case LOST_PROVISIONING: - if (VDBG) { Log.d(mTag, "onProvisioningFailure()"); } + if (DBG) { Log.d(mTag, "onProvisioningFailure()"); } recordMetric(IpManagerEvent.PROVISIONING_FAIL); mCallback.onProvisioningFailure(newLp); break; default: - if (VDBG) { Log.d(mTag, "onLinkPropertiesChange()"); } + if (DBG) { Log.d(mTag, "onLinkPropertiesChange()"); } mCallback.onLinkPropertiesChange(newLp); break; } @@ -1016,10 +1063,6 @@ public class IpManager extends StateMachine { return delta; } - private boolean linkPropertiesUnchanged(LinkProperties newLp) { - return Objects.equals(newLp, mLinkProperties); - } - private LinkProperties assembleLinkProperties() { // [1] Create a new LinkProperties object to populate. LinkProperties newLp = new LinkProperties(); @@ -1066,9 +1109,26 @@ public class IpManager extends StateMachine { newLp.setHttpProxy(mHttpProxy); } - if (VDBG) { - Log.d(mTag, "newLp{" + newLp + "}"); + // [5] Add data from InitialConfiguration + if (mConfiguration != null && mConfiguration.mInitialConfig != null) { + InitialConfiguration config = mConfiguration.mInitialConfig; + // Add InitialConfiguration routes and dns server addresses once all addresses + // specified in the InitialConfiguration have been observed with Netlink. + if (config.isProvisionedBy(newLp.getLinkAddresses(), null)) { + for (IpPrefix prefix : config.directlyConnectedRoutes) { + newLp.addRoute(new RouteInfo(prefix, null, mInterfaceName)); + } + } + addAllReachableDnsServers(newLp, config.dnsServers); + } + final LinkProperties oldLp = mLinkProperties; + if (DBG) { + Log.d(mTag, String.format("Netlink-seen LPs: %s, new LPs: %s; old LPs: %s", + netlinkLinkProperties, newLp, oldLp)); } + + // TODO: also learn via netlink routes specified by an InitialConfiguration and specified + // from a static IP v4 config instead of manually patching them in in steps [3] and [5]. return newLp; } @@ -1087,7 +1147,7 @@ public class IpManager extends StateMachine { // Returns false if we have lost provisioning, true otherwise. private boolean handleLinkPropertiesUpdate(boolean sendCallbacks) { final LinkProperties newLp = assembleLinkProperties(); - if (linkPropertiesUnchanged(newLp)) { + if (Objects.equals(newLp, mLinkProperties)) { return true; } final ProvisioningChange delta = setLinkProperties(newLp); @@ -1102,7 +1162,7 @@ public class IpManager extends StateMachine { ifcg.setLinkAddress(address); try { mNwService.setInterfaceConfig(mInterfaceName, ifcg); - if (VDBG) Log.d(mTag, "IPv4 configuration succeeded"); + if (DBG) Log.d(mTag, "IPv4 configuration succeeded"); } catch (IllegalStateException | RemoteException e) { logError("IPv4 configuration failed: %s", e); return false; @@ -1125,7 +1185,7 @@ public class IpManager extends StateMachine { final LinkProperties newLp = assembleLinkProperties(); final ProvisioningChange delta = setLinkProperties(newLp); - if (VDBG) { + if (DBG) { Log.d(mTag, "onNewDhcpResults(" + Objects.toString(dhcpResults) + ")"); } mCallback.onNewDhcpResults(dhcpResults); @@ -1141,7 +1201,7 @@ public class IpManager extends StateMachine { // any addresses upon entry to StoppedState. clearIPv4Address(); mDhcpResults = null; - if (VDBG) { Log.d(mTag, "onNewDhcpResults(null)"); } + if (DBG) { Log.d(mTag, "onNewDhcpResults(null)"); } mCallback.onNewDhcpResults(null); handleProvisioningFailure(); @@ -1218,6 +1278,26 @@ public class IpManager extends StateMachine { return true; } + private boolean applyInitialConfig(InitialConfiguration config) { + if (mNetd == null) { + logError("tried to add %s to %s but INetd was null", config, mInterfaceName); + return false; + } + + // TODO: also support specifying a static IPv4 configuration in InitialConfiguration. + for (LinkAddress addr : findAll(config.ipAddresses, LinkAddress::isIPv6)) { + try { + mNetd.interfaceAddAddress( + mInterfaceName, addr.getAddress().getHostAddress(), addr.getPrefixLength()); + } catch (ServiceSpecificException | RemoteException e) { + logError("failed to add %s to %s: %s", addr, mInterfaceName, e); + return false; + } + } + + return true; + } + private boolean startIpReachabilityMonitor() { try { mIpReachabilityMonitor = new IpReachabilityMonitor( @@ -1277,6 +1357,11 @@ public class IpManager extends StateMachine { @Override public boolean processMessage(Message msg) { switch (msg.what) { + case CMD_TERMINATE_AFTER_STOP: + stopStateMachineUpdaters(); + quit(); + break; + case CMD_STOP: break; @@ -1423,8 +1508,11 @@ public class IpManager extends StateMachine { boolean filter802_3Frames = mContext.getResources().getBoolean(R.bool.config_apfDrop802_3Frames); + int[] ethTypeBlackList = mContext.getResources().getIntArray( + R.array.config_apfEthTypeBlackList); + mApfFilter = ApfFilter.maybeCreate(mConfiguration.mApfCapabilities, mNetworkInterface, - mCallback, mMulticastFiltering, filter802_3Frames); + mCallback, mMulticastFiltering, filter802_3Frames, ethTypeBlackList); // TODO: investigate the effects of any multicast filtering racing/interfering with the // rest of this IP configuration startup. if (mApfFilter == null) { @@ -1446,6 +1534,14 @@ public class IpManager extends StateMachine { return; } + InitialConfiguration config = mConfiguration.mInitialConfig; + if ((config != null) && !applyInitialConfig(config)) { + // TODO introduce a new IpManagerEvent constant to distinguish this error case. + doImmediateProvisioningFailure(IpManagerEvent.ERROR_INVALID_PROVISIONING); + transitionTo(mStoppingState); + return; + } + if (mConfiguration.mUsingIpReachabilityMonitor && !startIpReachabilityMonitor()) { doImmediateProvisioningFailure( IpManagerEvent.ERROR_STARTING_IPREACHABILITYMONITOR); @@ -1652,4 +1748,39 @@ public class IpManager extends StateMachine { receivedInState, processedInState); } } + + // TODO: extract out into CollectionUtils. + static <T> boolean any(Iterable<T> coll, Predicate<T> fn) { + for (T t : coll) { + if (fn.test(t)) { + return true; + } + } + return false; + } + + static <T> boolean all(Iterable<T> coll, Predicate<T> fn) { + return !any(coll, not(fn)); + } + + static <T> Predicate<T> not(Predicate<T> fn) { + return (t) -> !fn.test(t); + } + + static <T> String join(String delimiter, Collection<T> coll) { + return coll.stream().map(Object::toString).collect(Collectors.joining(delimiter)); + } + + static <T> T find(Iterable<T> coll, Predicate<T> fn) { + for (T t: coll) { + if (fn.test(t)) { + return t; + } + } + return null; + } + + static <T> List<T> findAll(Collection<T> coll, Predicate<T> fn) { + return coll.stream().filter(fn).collect(Collectors.toList()); + } } diff --git a/services/net/java/android/net/util/NetworkConstants.java b/services/net/java/android/net/util/NetworkConstants.java index 9b3bc3f0301a..606526816368 100644 --- a/services/net/java/android/net/util/NetworkConstants.java +++ b/services/net/java/android/net/util/NetworkConstants.java @@ -87,6 +87,7 @@ public final class NetworkConstants { public static final int IPV4_PROTOCOL_OFFSET = 9; public static final int IPV4_SRC_ADDR_OFFSET = 12; public static final int IPV4_DST_ADDR_OFFSET = 16; + public static final int IPV4_ADDR_BITS = 32; public static final int IPV4_ADDR_LEN = 4; /** @@ -99,6 +100,7 @@ public final class NetworkConstants { public static final int IPV6_PROTOCOL_OFFSET = 6; public static final int IPV6_SRC_ADDR_OFFSET = 8; public static final int IPV6_DST_ADDR_OFFSET = 24; + public static final int IPV6_ADDR_BITS = 128; public static final int IPV6_ADDR_LEN = 16; public static final int IPV6_MIN_MTU = 1280; public static final int RFC7421_PREFIX_LENGTH = 64; diff --git a/services/net/java/android/net/util/PrefixUtils.java b/services/net/java/android/net/util/PrefixUtils.java index 962aab459a19..f60694aaedc9 100644 --- a/services/net/java/android/net/util/PrefixUtils.java +++ b/services/net/java/android/net/util/PrefixUtils.java @@ -20,6 +20,8 @@ import android.net.IpPrefix; import android.net.LinkAddress; import android.net.LinkProperties; +import java.net.Inet4Address; +import java.net.InetAddress; import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -68,6 +70,13 @@ public class PrefixUtils { return new IpPrefix(addr.getAddress(), addr.getPrefixLength()); } + public static IpPrefix ipAddressAsPrefix(InetAddress ip) { + final int bitLength = (ip instanceof Inet4Address) + ? NetworkConstants.IPV4_ADDR_BITS + : NetworkConstants.IPV6_ADDR_BITS; + return new IpPrefix(ip, bitLength); + } + private static IpPrefix pfx(String prefixStr) { return new IpPrefix(prefixStr); } diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java index 6a6b542f9bb6..71ba685b99c9 100644 --- a/services/print/java/com/android/server/print/PrintManagerService.java +++ b/services/print/java/com/android/server/print/PrintManagerService.java @@ -63,6 +63,7 @@ import com.android.server.SystemService; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -645,7 +646,6 @@ public final class PrintManagerService extends SystemService { int opti = 0; boolean dumpAsProto = false; - int user = UserHandle.USER_ALL; while (opti < args.length) { String opt = args[opti]; if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { @@ -659,48 +659,47 @@ public final class PrintManagerService extends SystemService { } } + ArrayList<UserState> userStatesToDump = new ArrayList<>(); synchronized (mLock) { - final long identity = Binder.clearCallingIdentity(); - try { - if (dumpAsProto) { - dumpLocked(new ProtoOutputStream(fd), UserHandle.of(user)); - } else { - dumpLocked(fd, pw, UserHandle.of(user)); - } - } finally { - Binder.restoreCallingIdentity(identity); + int numUserStates = mUserStates.size(); + for (int i = 0; i < numUserStates; i++) { + userStatesToDump.add(mUserStates.valueAt(i)); + } + } + + final long identity = Binder.clearCallingIdentity(); + try { + if (dumpAsProto) { + dump(new ProtoOutputStream(fd), userStatesToDump); + } else { + dump(fd, pw, userStatesToDump); } + } finally { + Binder.restoreCallingIdentity(identity); } } - private void dumpLocked(@NonNull ProtoOutputStream proto, @NonNull UserHandle user) { - final int userStateCount = mUserStates.size(); + private void dump(@NonNull ProtoOutputStream proto, + @NonNull ArrayList<UserState> userStatesToDump) { + final int userStateCount = userStatesToDump.size(); for (int i = 0; i < userStateCount; i++) { - UserState userState = mUserStates.valueAt(i); - - if (user.equals(UserHandle.ALL) || mUserStates.keyAt(i) == user.getIdentifier()) { - long token = proto.start(PrintServiceDumpProto.USER_STATES); - userState.dump(proto); - proto.end(token); - } + long token = proto.start(PrintServiceDumpProto.USER_STATES); + userStatesToDump.get(i).dump(proto); + proto.end(token); } proto.flush(); } - private void dumpLocked(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, - @NonNull UserHandle user) { + private void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, + @NonNull ArrayList<UserState> userStatesToDump) { pw = Preconditions.checkNotNull(pw); pw.println("PRINT MANAGER STATE (dumpsys print)"); - final int userStateCount = mUserStates.size(); + final int userStateCount = userStatesToDump.size(); for (int i = 0; i < userStateCount; i++) { - UserState userState = mUserStates.valueAt(i); - - if (user.equals(UserHandle.ALL) || mUserStates.keyAt(i) == user.getIdentifier()) { - userState.dump(fd, pw, ""); - pw.println(); - } + userStatesToDump.get(i).dump(fd, pw, ""); + pw.println(); } } diff --git a/services/robotests/Android.mk b/services/robotests/Android.mk new file mode 100644 index 000000000000..3e82d3ee1d2f --- /dev/null +++ b/services/robotests/Android.mk @@ -0,0 +1,76 @@ +# Copyright (C) 2016 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +############################################################ +# FrameworksServicesLib app just for Robolectric test target. # +############################################################ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_PACKAGE_NAME := FrameworksServicesLib +LOCAL_MODULE_TAGS := optional + +LOCAL_PRIVILEGED_MODULE := true + +LOCAL_STATIC_JAVA_LIBRARIES := \ + frameworks-base-testutils \ + services.backup \ + services.core \ + android-support-test \ + mockito-target-minus-junit4 \ + platform-test-annotations \ + truth-prebuilt + +include $(BUILD_PACKAGE) + +############################################# +# FrameworksServices Robolectric test target. # +############################################# +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +# Include the testing libraries (JUnit4 + Robolectric libs). +LOCAL_STATIC_JAVA_LIBRARIES := \ + platform-system-robolectric \ + truth-prebuilt + +LOCAL_JAVA_LIBRARIES := \ + junit \ + platform-robolectric-prebuilt + +LOCAL_INSTRUMENTATION_FOR := FrameworksServicesLib +LOCAL_MODULE := FrameworksServicesRoboTests + +LOCAL_MODULE_TAGS := optional + +include $(BUILD_STATIC_JAVA_LIBRARY) + +############################################################# +# FrameworksServices runner target to run the previous target. # +############################################################# +include $(CLEAR_VARS) + +LOCAL_MODULE := RunFrameworksServicesRoboTests + +LOCAL_SDK_VERSION := current + +LOCAL_STATIC_JAVA_LIBRARIES := \ + FrameworksServicesRoboTests + +LOCAL_TEST_PACKAGE := FrameworksServicesLib + +include prebuilts/misc/common/robolectric/run_robotests.mk diff --git a/services/robotests/src/com/android/server/backup/TransportManagerTest.java b/services/robotests/src/com/android/server/backup/TransportManagerTest.java new file mode 100644 index 000000000000..0f7a091a8315 --- /dev/null +++ b/services/robotests/src/com/android/server/backup/TransportManagerTest.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.backup; + +import static com.google.common.truth.Truth.assertThat; + +import android.annotation.RequiresPermission; +import android.content.ComponentName; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.os.UserHandle; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.res.ResourceLoader; +import org.robolectric.res.builder.DefaultPackageManager; +import org.robolectric.res.builder.RobolectricPackageManager; +import org.robolectric.shadows.ShadowContextImpl; +import org.robolectric.shadows.ShadowLooper; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + +@RunWith(RobolectricTestRunner.class) +@Config( + manifest = Config.NONE, + sdk = 23, + shadows = {TransportManagerTest.ShadowContextImplWithBindServiceAsUser.class} +) +public class TransportManagerTest { + private static final String PACKAGE_NAME = "some.package.name"; + private static final String TRANSPORT1_NAME = "transport1.name"; + private static final String TRANSPORT2_NAME = "transport2.name"; + private static final ComponentName TRANSPORT1_COMPONENT_NAME = new ComponentName(PACKAGE_NAME, + TRANSPORT1_NAME); + private static final ComponentName TRANSPORT2_COMPONENT_NAME = new ComponentName(PACKAGE_NAME, + TRANSPORT2_NAME); + private static final List<ComponentName> TRANSPORTS_COMPONENT_NAMES = Arrays.asList( + TRANSPORT1_COMPONENT_NAME, TRANSPORT2_COMPONENT_NAME); + + private RobolectricPackageManager mPackageManager; + + @Mock private TransportManager.TransportBoundListener mTransportBoundListener; + + @Before + public void setUp() { + mPackageManager = new DefaultPackageManagerWithQueryIntentServicesAsUser( + RuntimeEnvironment.getAppResourceLoader()); + RuntimeEnvironment.setRobolectricPackageManager(mPackageManager); + } + + @Test + public void onPackageAdded_bindsToAllTransports() { + Intent intent = new Intent(TransportManager.SERVICE_ACTION_TRANSPORT_HOST); + intent.setPackage(PACKAGE_NAME); + + PackageInfo packageInfo = new PackageInfo(); + packageInfo.packageName = PACKAGE_NAME; + packageInfo.applicationInfo = new ApplicationInfo(); + packageInfo.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED; + + mPackageManager.addPackage(packageInfo); + + ResolveInfo transport1 = new ResolveInfo(); + transport1.serviceInfo = new ServiceInfo(); + transport1.serviceInfo.packageName = PACKAGE_NAME; + transport1.serviceInfo.name = TRANSPORT1_NAME; + + ResolveInfo transport2 = new ResolveInfo(); + transport2.serviceInfo = new ServiceInfo(); + transport2.serviceInfo.packageName = PACKAGE_NAME; + transport2.serviceInfo.name = TRANSPORT2_NAME; + + mPackageManager.addResolveInfoForIntent(intent, Arrays.asList(transport1, transport2)); + + TransportManager transportManager = new TransportManager( + RuntimeEnvironment.application.getApplicationContext(), + new HashSet<>(TRANSPORTS_COMPONENT_NAMES), + null, + mTransportBoundListener, + ShadowLooper.getMainLooper()); + transportManager.onPackageAdded(PACKAGE_NAME); + + assertThat(transportManager.getAllTransportComponents()).asList().containsExactlyElementsIn( + TRANSPORTS_COMPONENT_NAMES); + } + + private static class DefaultPackageManagerWithQueryIntentServicesAsUser extends + DefaultPackageManager { + + /* package */ DefaultPackageManagerWithQueryIntentServicesAsUser( + ResourceLoader appResourceLoader) { + super(appResourceLoader); + } + + @Override + public List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int flags, int userId) { + return super.queryIntentServices(intent, flags); + } + } + + @Implements(className = ShadowContextImpl.CLASS_NAME) + public static class ShadowContextImplWithBindServiceAsUser extends ShadowContextImpl { + + @Implementation + public boolean bindServiceAsUser(@RequiresPermission Intent service, ServiceConnection conn, + int flags, UserHandle user) { + return true; + } + } +} diff --git a/services/tests/notification/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/notification/src/com/android/server/notification/ManagedServicesTest.java index bd65f571d20b..613f01c20300 100644 --- a/services/tests/notification/src/com/android/server/notification/ManagedServicesTest.java +++ b/services/tests/notification/src/com/android/server/notification/ManagedServicesTest.java @@ -38,6 +38,7 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.UserInfo; +import android.os.Build; import android.os.IBinder; import android.os.IInterface; import android.os.UserHandle; @@ -90,6 +91,7 @@ public class ManagedServicesTest extends NotificationTestCase { private ArrayMap<Integer, String> mExpectedSecondaryPackages; private ArrayMap<Integer, String> mExpectedSecondaryComponentNames; + // type : user : list of approved private ArrayMap<Integer, ArrayMap<Integer, String>> mExpectedPrimary = new ArrayMap<>(); private ArrayMap<Integer, ArrayMap<Integer, String>> mExpectedSecondary = new ArrayMap<>(); @@ -146,15 +148,82 @@ public class ManagedServicesTest extends NotificationTestCase { service.onSettingRestored( service.getConfig().secureSettingName, mExpectedPrimary.get(approvalLevel).get(userId), - userId); + Build.VERSION_CODES.O, userId); } verifyExpectedApprovedEntries(service, true); for (int userId : mExpectedSecondary.get(approvalLevel).keySet()) { service.onSettingRestored(service.getConfig().secondarySettingName, - mExpectedSecondary.get(approvalLevel).get(userId), userId); + mExpectedSecondary.get(approvalLevel).get(userId), Build.VERSION_CODES.O, + userId); + } + verifyExpectedApprovedEntries(service); + } + } + + @Test + public void testBackupAndRestore_migration_preO() throws Exception { + ArrayMap backupPrimaryPackages = new ArrayMap<>(); + backupPrimaryPackages.put(0, "backup.0:backup:0a"); + backupPrimaryPackages.put(10, "10.backup"); + backupPrimaryPackages.put(11, "eleven"); + backupPrimaryPackages.put(12, ""); + ArrayMap backupPrimaryComponentNames = new ArrayMap<>(); + backupPrimaryComponentNames.put(0, "backup.first/whatever:a/b"); + backupPrimaryComponentNames.put(10, "again/M1"); + backupPrimaryComponentNames.put(11, "orange/youglad:itisnot/banana"); + backupPrimaryComponentNames.put(12, ""); + ArrayMap<Integer, ArrayMap<Integer, String>> backupPrimary = new ArrayMap<>(); + backupPrimary.put(APPROVAL_BY_PACKAGE, backupPrimaryPackages); + backupPrimary.put(APPROVAL_BY_COMPONENT, backupPrimaryComponentNames); + + ArrayMap backupSecondaryComponentNames = new ArrayMap<>(); + backupSecondaryComponentNames.put(0, "secondary.1/component.Name"); + backupSecondaryComponentNames.put(10, + "this.is.another.package.backup/with.Component:component.backup/2"); + ArrayMap backupSecondaryPackages = new ArrayMap<>(); + backupSecondaryPackages.put(0, ""); + backupSecondaryPackages.put(10, + "this.is.another.package.backup:package.backup"); + ArrayMap<Integer, ArrayMap<Integer, String>> backupSecondary = new ArrayMap<>(); + backupSecondary.put(APPROVAL_BY_PACKAGE, backupSecondaryPackages); + backupSecondary.put(APPROVAL_BY_COMPONENT, backupSecondaryComponentNames); + + for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { + ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, + mIpm, approvalLevel); + + // not an expected flow but a way to get data into the settings + for (int userId : mExpectedPrimary.get(approvalLevel).keySet()) { + service.onSettingRestored( + service.getConfig().secureSettingName, + mExpectedPrimary.get(approvalLevel).get(userId), + Build.VERSION_CODES.O, userId); + } + + for (int userId : mExpectedSecondary.get(approvalLevel).keySet()) { + service.onSettingRestored(service.getConfig().secondarySettingName, + mExpectedSecondary.get(approvalLevel).get(userId), Build.VERSION_CODES.O, + userId); + } + + // actual test + for (int userId : backupPrimary.get(approvalLevel).keySet()) { + service.onSettingRestored( + service.getConfig().secureSettingName, + backupPrimary.get(approvalLevel).get(userId), + Build.VERSION_CODES.N_MR1, userId); + } + verifyExpectedApprovedEntries(service, true); + + for (int userId : backupSecondary.get(approvalLevel).keySet()) { + service.onSettingRestored(service.getConfig().secondarySettingName, + backupSecondary.get(approvalLevel).get(userId), + Build.VERSION_CODES.N_MR1, userId); } verifyExpectedApprovedEntries(service); + verifyExpectedApprovedEntries(service, backupPrimary.get(approvalLevel)); + verifyExpectedApprovedEntries(service, backupSecondary.get(approvalLevel)); } } @@ -510,6 +579,32 @@ public class ManagedServicesTest extends NotificationTestCase { assertEquals(0, service.getAllowedComponents(10).size()); } + @Test + public void testOnUserRemoved() throws Exception { + for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) { + ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, + mIpm, approvalLevel); + loadXml(service); + + ArrayMap<Integer, String> verifyMap = mExpectedPrimary.get(service.mApprovalLevel); + String user0 = verifyMap.remove(0); + verifyMap = mExpectedSecondary.get(service.mApprovalLevel); + user0 = user0 + ":" + verifyMap.remove(0); + + service.onUserRemoved(0); + + for (String verifyValue : user0.split(":")) { + if (!TextUtils.isEmpty(verifyValue)) { + assertFalse("service type " + service.mApprovalLevel + ":" + verifyValue + + " is still allowed", + service.isPackageOrComponentAllowed(verifyValue, 0)); + } + } + + verifyExpectedApprovedEntries(service); + } + } + private void loadXml(ManagedServices service) throws Exception { final StringBuffer xml = new StringBuffer(); xml.append("<" + service.getConfig().xmlTag + ">\n"); @@ -589,7 +684,8 @@ public class ManagedServicesTest extends NotificationTestCase { for (String packageOrComponent : verifyMap.get(userId).split(":")) { if (!TextUtils.isEmpty(packageOrComponent)) { if (service.mApprovalLevel == APPROVAL_BY_PACKAGE) { - assertTrue(packageOrComponent, service.isComponentEnabledForPackage(packageOrComponent)); + assertTrue(packageOrComponent, + service.isComponentEnabledForPackage(packageOrComponent)); for (int i = 1; i <= 3; i ++) { ComponentName componentName = ComponentName.unflattenFromString( packageOrComponent +"/C" + i); @@ -619,25 +715,22 @@ public class ManagedServicesTest extends NotificationTestCase { ArrayMap<Integer, String> verifyMap = primary ? mExpectedPrimary.get(service.mApprovalLevel) : mExpectedSecondary.get(service.mApprovalLevel); + verifyExpectedApprovedEntries(service, verifyMap); + } + + private void verifyExpectedApprovedEntries(ManagedServices service, + ArrayMap<Integer, String> verifyMap) { for (int userId : verifyMap.keySet()) { for (String verifyValue : verifyMap.get(userId).split(":")) { if (!TextUtils.isEmpty(verifyValue)) { assertTrue("service type " + service.mApprovalLevel + ":" - + verifyValue + " is not allowed for user " + userId, + + verifyValue + " is not allowed for user " + userId, service.isPackageOrComponentAllowed(verifyValue, userId)); } } } } - private boolean isPackage(String packageOrComponent) { - final ComponentName component = ComponentName.unflattenFromString(packageOrComponent); - if (component != null) { - return false; - } - return true; - } - private void writeExpectedValuesToSettings(int approvalLevel) { for (int userId : mExpectedPrimary.get(approvalLevel).keySet()) { Settings.Secure.putStringForUser(getContext().getContentResolver(), SETTING, diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java index 801479b33ce5..65bf33084bb4 100644 --- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java +++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java @@ -46,6 +46,7 @@ import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.content.res.Resources; import android.graphics.Color; import android.media.AudioAttributes; import android.net.Uri; @@ -78,6 +79,7 @@ import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -127,6 +129,8 @@ public class RankingHelperTest extends NotificationTestCase { when(mPm.getPackageUidAsUser(eq(UPDATED_PKG), anyInt())).thenReturn(UID2); when(mContext.getResources()).thenReturn( InstrumentationRegistry.getContext().getResources()); + when(mContext.getContentResolver()).thenReturn( + InstrumentationRegistry.getContext().getContentResolver()); when(mContext.getPackageManager()).thenReturn(mPm); when(mContext.getApplicationInfo()).thenReturn(legacy); // most tests assume badging is enabled @@ -1366,4 +1370,22 @@ public class RankingHelperTest extends NotificationTestCase { assertFalse(mHelper.badgingEnabled(USER)); assertTrue(mHelper.badgingEnabled(USER2)); } + + @Test + public void testOnLocaleChanged_updatesDefaultChannels() throws Exception { + String newLabel = "bananas!"; + final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG, UID, + NotificationChannel.DEFAULT_CHANNEL_ID, false); + assertFalse(newLabel.equals(defaultChannel.getName())); + + Resources res = mock(Resources.class); + when(mContext.getResources()).thenReturn(res); + when(res.getString(com.android.internal.R.string.default_notification_channel_label)) + .thenReturn(newLabel); + + mHelper.onLocaleChanged(mContext, USER.getIdentifier()); + + assertEquals(newLabel, mHelper.getNotificationChannel(PKG, UID, + NotificationChannel.DEFAULT_CHANNEL_ID, false).getName()); + } } diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk index baec9565f1ae..fd832237264b 100644 --- a/services/tests/servicestests/Android.mk +++ b/services/tests/servicestests/Android.mk @@ -29,7 +29,8 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/aidl -LOCAL_SRC_FILES += aidl/com/android/servicestests/aidl/INetworkStateObserver.aidl +LOCAL_SRC_FILES += aidl/com/android/servicestests/aidl/INetworkStateObserver.aidl \ + aidl/com/android/servicestests/aidl/ICmdReceiverService.aidl LOCAL_SRC_FILES += $(call all-java-files-under, test-apps/JobTestApp/src) LOCAL_JAVA_LIBRARIES := android.test.mock legacy-android-test diff --git a/services/tests/servicestests/AndroidTest.xml b/services/tests/servicestests/AndroidTest.xml index cea9a8bffde7..23e5072654e7 100644 --- a/services/tests/servicestests/AndroidTest.xml +++ b/services/tests/servicestests/AndroidTest.xml @@ -17,6 +17,7 @@ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> <option name="test-file-name" value="FrameworksServicesTests.apk" /> <option name="test-file-name" value="JobTestApp.apk" /> + <option name="test-file-name" value="ConnTestApp.apk" /> </target_preparer> <option name="test-suite-tag" value="apct" /> diff --git a/services/tests/servicestests/aidl/Android.mk b/services/tests/servicestests/aidl/Android.mk index 0c9b83962833..166da1dea7e3 100644 --- a/services/tests/servicestests/aidl/Android.mk +++ b/services/tests/servicestests/aidl/Android.mk @@ -18,6 +18,7 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := tests LOCAL_SDK_VERSION := current LOCAL_SRC_FILES := \ - com/android/servicestests/aidl/INetworkStateObserver.aidl + com/android/servicestests/aidl/INetworkStateObserver.aidl \ + com/android/servicestests/aidl/ICmdReceiverService.aidl LOCAL_MODULE := servicestests-aidl include $(BUILD_STATIC_JAVA_LIBRARY)
\ No newline at end of file diff --git a/services/tests/servicestests/aidl/com/android/servicestests/aidl/ICmdReceiverService.aidl b/services/tests/servicestests/aidl/com/android/servicestests/aidl/ICmdReceiverService.aidl new file mode 100644 index 000000000000..d96450478f90 --- /dev/null +++ b/services/tests/servicestests/aidl/com/android/servicestests/aidl/ICmdReceiverService.aidl @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.servicestests.aidl; + +interface ICmdReceiverService { + void finishActivity(); +}
\ No newline at end of file diff --git a/services/tests/servicestests/res/raw/conntestapp b/services/tests/servicestests/res/raw/conntestapp Binary files differdeleted file mode 100644 index e99316446f7e..000000000000 --- a/services/tests/servicestests/res/raw/conntestapp +++ /dev/null diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java index bb7e20bcb9c3..3b7db9f73010 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java @@ -56,13 +56,11 @@ import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.net.wifi.WifiSsid; import android.os.Binder; -import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; -import android.os.RemoteCallback; import android.os.RemoteException; import android.os.UserHandle; import android.support.test.InstrumentationRegistry; @@ -369,6 +367,8 @@ public class NetworkScoreServiceTest { @Test public void testSetActiveScorer_noScoreNetworksPermission() { + when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES)) + .thenReturn(PackageManager.PERMISSION_DENIED); when(mContext.checkCallingOrSelfPermission(permission.SCORE_NETWORKS)) .thenReturn(PackageManager.PERMISSION_DENIED); @@ -413,8 +413,8 @@ public class NetworkScoreServiceTest { @Test public void testGetAllValidScorer_noRequestNetworkScoresPermission() { - when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES)) - .thenReturn(PackageManager.PERMISSION_DENIED); + doThrow(new SecurityException()).when(mContext) + .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES), anyString()); try { mNetworkScoreService.getAllValidScorers(); @@ -518,6 +518,49 @@ public class NetworkScoreServiceTest { } @Test + public void testGetActiveScorerPackage_missingRequiredPermissions() throws Exception { + when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES)) + .thenReturn(PackageManager.PERMISSION_DENIED); + when(mContext.checkCallingOrSelfPermission(permission.SCORE_NETWORKS)) + .thenReturn(PackageManager.PERMISSION_DENIED); + + try { + mNetworkScoreService.getActiveScorerPackage(); + fail("SecurityException expected"); + } catch (SecurityException e) { + // expected + } + } + + @Test + public void testGetActiveScorerPackage_noRequestScoresPermission() throws Exception { + when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES)) + .thenReturn(PackageManager.PERMISSION_DENIED); + when(mContext.checkCallingOrSelfPermission(permission.SCORE_NETWORKS)) + .thenReturn(PackageManager.PERMISSION_GRANTED); + + try { + mNetworkScoreService.getActiveScorerPackage(); + } catch (SecurityException e) { + fail("Unexpected SecurityException"); + } + } + + @Test + public void testGetActiveScorerPackage_noScoreNetworksPermission() throws Exception { + when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES)) + .thenReturn(PackageManager.PERMISSION_GRANTED); + when(mContext.checkCallingOrSelfPermission(permission.SCORE_NETWORKS)) + .thenReturn(PackageManager.PERMISSION_DENIED); + + try { + mNetworkScoreService.getActiveScorerPackage(); + } catch (SecurityException e) { + fail("Unexpected SecurityException"); + } + } + + @Test public void testCacheUpdatingConsumer_nullFilter() throws Exception { List<ScoredNetwork> scoredNetworkList = Lists.newArrayList(SCORED_NETWORK); NetworkScoreService.FilteringCacheUpdatingConsumer consumer = @@ -764,8 +807,8 @@ public class NetworkScoreServiceTest { @Test public void testGetActiveScorer_notConnected_canNotRequestScores() throws Exception { - when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES)) - .thenReturn(PackageManager.PERMISSION_DENIED); + doThrow(new SecurityException()).when(mContext) + .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES), anyString()); try { mNetworkScoreService.getActiveScorer(); fail("SecurityException expected."); @@ -789,8 +832,8 @@ public class NetworkScoreServiceTest { @Test public void testGetActiveScorer_connected_canNotRequestScores() throws Exception { - when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES)) - .thenReturn(PackageManager.PERMISSION_DENIED); + doThrow(new SecurityException()).when(mContext) + .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES), anyString()); bindToScorer(false); try { mNetworkScoreService.getActiveScorer(); diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java new file mode 100644 index 000000000000..d3a8deee799e --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java @@ -0,0 +1,116 @@ +/* + ** Copyright 2017, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +package com.android.server.accessibility; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.accessibilityservice.AccessibilityServiceInfo; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.RemoteException; +import android.os.UserHandle; +import android.view.WindowManagerInternal; + +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.Arrays; +import java.util.HashSet; + + +/** + * Tests for AccessibilityServiceConnection + */ +public class AccessibilityServiceConnectionTest { + static final ComponentName COMPONENT_NAME = new ComponentName( + "com.android.server.accessibility", "AccessibilityServiceConnectionTest"); + static final int SERVICE_ID = 42; + + AccessibilityServiceConnection mConnection; + @Mock AccessibilityManagerService.UserState mMockUserState; + @Mock Context mMockContext; + @Mock AccessibilityServiceInfo mMockServiceInfo; + @Mock ResolveInfo mMockResolveInfo; + @Mock AccessibilityManagerService.SecurityPolicy mMockSecurityPolicy; + @Mock AccessibilityClientConnection.SystemSupport mMockSystemSupport; + @Mock WindowManagerInternal mMockWindowManagerInternal; + @Mock GlobalActionPerformer mMockGlobalActionPerformer; + @Mock KeyEventDispatcher mMockKeyEventDispatcher; + + + @BeforeClass + public static void oneTimeInitialization() { + if (Looper.myLooper() == null) { + Looper.prepare(); + } + } + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + when(mMockSystemSupport.getKeyEventDispatcher()).thenReturn(mMockKeyEventDispatcher); + when(mMockServiceInfo.getResolveInfo()).thenReturn(mMockResolveInfo); + mMockResolveInfo.serviceInfo = mock(ServiceInfo.class); + mMockResolveInfo.serviceInfo.applicationInfo = mock(ApplicationInfo.class); + + mConnection = new AccessibilityServiceConnection(mMockUserState, mMockContext, + COMPONENT_NAME, mMockServiceInfo, SERVICE_ID, new Handler(), new Object(), + mMockSecurityPolicy, mMockSystemSupport, mMockWindowManagerInternal, + mMockGlobalActionPerformer); + } + + @Test + public void bind_requestsContextToBindService() { + mConnection.bindLocked(); + verify(mMockContext).bindServiceAsUser(any(Intent.class), eq(mConnection), + eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE), + any(UserHandle.class)); + } + + @Test + public void unbind_requestsContextToUnbindService() { + mConnection.unbindLocked(); + verify(mMockContext).unbindService(mConnection); + } + + @Test + public void bindConnectUnbind_linksAndUnlinksToServiceDeath() throws RemoteException { + IBinder mockBinder = mock(IBinder.class); + when(mMockUserState.getBindingServicesLocked()) + .thenReturn(new HashSet<>(Arrays.asList(COMPONENT_NAME))); + mConnection.bindLocked(); + mConnection.onServiceConnected(COMPONENT_NAME, mockBinder); + verify(mockBinder).linkToDeath(eq(mConnection), anyInt()); + mConnection.unbindLocked(); + verify(mockBinder).unlinkToDeath(eq(mConnection), anyInt()); + } +} diff --git a/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java new file mode 100644 index 000000000000..51e6bc90c947 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java @@ -0,0 +1,72 @@ +/* + ** Copyright 2017, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +package com.android.server.accessibility; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.accessibilityservice.AccessibilityService; +import android.app.StatusBarManager; +import android.content.Context; +import android.view.WindowManagerInternal; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * Tests for GlobalActionPerformer + */ +public class GlobalActionPerformerTest { + GlobalActionPerformer mGlobalActionPerformer; + + @Mock Context mMockContext; + @Mock WindowManagerInternal mMockWindowManagerInternal; + @Mock StatusBarManager mMockStatusBarManager; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + + when(mMockContext.getSystemService(android.app.Service.STATUS_BAR_SERVICE)) + .thenReturn(mMockStatusBarManager); + + mGlobalActionPerformer = + new GlobalActionPerformer(mMockContext, mMockWindowManagerInternal); + } + + @Test + public void testNotifications_expandsNotificationPanel() { + mGlobalActionPerformer + .performGlobalAction(AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS); + verify(mMockStatusBarManager).expandNotificationsPanel(); + } + + @Test + public void testQuickSettings_requestsQuickSettingsPanel() { + mGlobalActionPerformer + .performGlobalAction(AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS); + verify(mMockStatusBarManager).expandSettingsPanel(); + } + + @Test + public void testPowerDialog_requestsFromWindowManager() { + mGlobalActionPerformer.performGlobalAction(AccessibilityService.GLOBAL_ACTION_POWER_DIALOG); + verify(mMockWindowManagerInternal).showGlobalActions(); + } +} diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java new file mode 100644 index 000000000000..50824e32e50d --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationGestureHandlerTest.java @@ -0,0 +1,535 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.accessibility; + +import static android.util.ExceptionUtils.propagate; +import static android.view.MotionEvent.ACTION_DOWN; +import static android.view.MotionEvent.ACTION_MOVE; +import static android.view.MotionEvent.ACTION_POINTER_DOWN; +import static android.view.MotionEvent.ACTION_POINTER_UP; + +import static com.android.server.testutils.TestUtils.strictMock; + +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import android.annotation.NonNull; +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; +import android.util.DebugUtils; +import android.view.InputDevice; +import android.view.MotionEvent; + +import com.android.server.testutils.OffsettableClock; +import com.android.server.testutils.TestHandler; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.function.IntConsumer; + + +@RunWith(AndroidJUnit4.class) +public class MagnificationGestureHandlerTest { + + public static final int STATE_IDLE = 1; + public static final int STATE_ZOOMED = 2; + public static final int STATE_2TAPS = 3; + public static final int STATE_ZOOMED_2TAPS = 4; + public static final int STATE_SHORTCUT_TRIGGERED = 5; + public static final int STATE_DRAGGING_TMP = 6; + public static final int STATE_DRAGGING = 7; + public static final int STATE_PANNING = 8; + public static final int STATE_SCALING_AND_PANNING = 9; + + + public static final int FIRST_STATE = STATE_IDLE; + public static final int LAST_STATE = STATE_SCALING_AND_PANNING; + + // Co-prime x and y, to potentially catch x-y-swapped errors + public static final float DEFAULT_X = 301; + public static final float DEFAULT_Y = 299; + + private Context mContext; + private AccessibilityManagerService mAms; + private MagnificationController mMagnificationController; + private OffsettableClock mClock; + private MagnificationGestureHandler mMgh; + private TestHandler mHandler; + + @Before + public void setUp() { + mContext = InstrumentationRegistry.getContext(); + mAms = new AccessibilityManagerService(mContext); + mMagnificationController = new MagnificationController( + mContext, mAms, /* lock */ new Object()) { + @Override + public boolean magnificationRegionContains(float x, float y) { + return true; + } + + @Override + void setForceShowMagnifiableBounds(boolean show) {} + }; + mMagnificationController.mRegistered = true; + mClock = new OffsettableClock.Stopped(); + + boolean detectTripleTap = true; + boolean detectShortcutTrigger = true; + mMgh = newInstance(detectTripleTap, detectShortcutTrigger); + } + + @NonNull + public MagnificationGestureHandler newInstance(boolean detectTripleTap, + boolean detectShortcutTrigger) { + MagnificationGestureHandler h = new MagnificationGestureHandler( + mContext, mMagnificationController, + detectTripleTap, detectShortcutTrigger); + mHandler = new TestHandler(h.mDetectingStateHandler, mClock); + h.mDetectingStateHandler.mHandler = mHandler; + h.setNext(strictMock(EventStreamTransformation.class)); + return h; + } + + @Test + public void testInitialState_isIdle() { + assertIn(STATE_IDLE); + } + + /** + * Covers paths to get to and back between each state and {@link #STATE_IDLE} + * This navigates between states using "canonical" paths, specified in + * {@link #goFromStateIdleTo} (for traversing away from {@link #STATE_IDLE}) and + * {@link #returnToNormalFrom} (for navigating back to {@link #STATE_IDLE}) + */ + @Test + public void testEachState_isReachableAndRecoverable() { + forEachState(state -> { + goFromStateIdleTo(state); + assertIn(state); + + returnToNormalFrom(state); + try { + assertIn(STATE_IDLE); + } catch (AssertionError e) { + throw new AssertionError("Failed while testing state " + stateToString(state), e); + } + }); + } + + @Test + public void testStates_areMutuallyExclusive() { + forEachState(state1 -> { + forEachState(state2 -> { + if (state1 < state2) { + goFromStateIdleTo(state1); + try { + assertIn(state2); + fail("State " + stateToString(state1) + " also implies state " + + stateToString(state2) + stateDump()); + } catch (AssertionError e) { + // expected + returnToNormalFrom(state1); + } + } + }); + }); + } + + /** + * Covers edges of the graph not covered by "canonical" transitions specified in + * {@link #goFromStateIdleTo} and {@link #returnToNormalFrom} + */ + @SuppressWarnings("Convert2MethodRef") + @Test + public void testAlternativeTransitions_areWorking() { + // A11y button followed by a tap&hold turns temporary "viewport dragging" zoom on + assertTransition(STATE_SHORTCUT_TRIGGERED, () -> { + send(downEvent()); + fastForward1sec(); + }, STATE_DRAGGING_TMP); + + // A11y button followed by a tap turns zoom on + assertTransition(STATE_SHORTCUT_TRIGGERED, () -> tap(), STATE_ZOOMED); + + // A11y button pressed second time negates the 1st press + assertTransition(STATE_SHORTCUT_TRIGGERED, () -> triggerShortcut(), STATE_IDLE); + + // A11y button turns zoom off + assertTransition(STATE_ZOOMED, () -> triggerShortcut(), STATE_IDLE); + + + // Double tap times out while zoomed + assertTransition(STATE_ZOOMED_2TAPS, () -> { + allowEventDelegation(); + fastForward1sec(); + }, STATE_ZOOMED); + + // tap+tap+swipe gets delegated + assertTransition(STATE_2TAPS, () -> { + allowEventDelegation(); + swipe(); + }, STATE_IDLE); + } + + @Test + public void testNonTransitions_dontChangeState() { + // ACTION_POINTER_DOWN triggers event delegation if not magnifying + assertStaysIn(STATE_IDLE, () -> { + allowEventDelegation(); + send(downEvent()); + send(pointerEvent(ACTION_POINTER_DOWN, DEFAULT_X * 2, DEFAULT_Y)); + }); + + // Long tap breaks the triple-tap detection sequence + Runnable tapAndLongTap = () -> { + allowEventDelegation(); + tap(); + longTap(); + }; + assertStaysIn(STATE_IDLE, tapAndLongTap); + assertStaysIn(STATE_ZOOMED, tapAndLongTap); + + // Triple tap with delays in between doesn't count + Runnable slow3tap = () -> { + tap(); + fastForward1sec(); + tap(); + fastForward1sec(); + tap(); + }; + assertStaysIn(STATE_IDLE, slow3tap); + assertStaysIn(STATE_ZOOMED, slow3tap); + } + + @Test + public void testDisablingTripleTap_removesInputLag() { + mMgh = newInstance(/* detect3tap */ false, /* detectShortcut */ true); + goFromStateIdleTo(STATE_IDLE); + allowEventDelegation(); + tap(); + // no fast forward + verify(mMgh.mNext, times(2)).onMotionEvent(any(), any(), anyInt()); + } + + private void assertTransition(int fromState, Runnable transitionAction, int toState) { + goFromStateIdleTo(fromState); + transitionAction.run(); + assertIn(toState); + returnToNormalFrom(toState); + } + + private void assertStaysIn(int state, Runnable action) { + assertTransition(state, action, state); + } + + private void forEachState(IntConsumer action) { + for (int state = FIRST_STATE; state <= LAST_STATE; state++) { + action.accept(state); + } + } + + private void allowEventDelegation() { + doNothing().when(mMgh.mNext).onMotionEvent(any(), any(), anyInt()); + } + + private void fastForward1sec() { + fastForward(1000); + } + + private void fastForward(int ms) { + mClock.fastForward(ms); + mHandler.timeAdvance(); + } + + /** + * Asserts that {@link #mMgh the handler} is in the given {@code state} + */ + private void assertIn(int state) { + switch (state) { + + // Asserts on separate lines for accurate stack traces + + case STATE_IDLE: { + check(tapCount() < 2, state); + check(!mMgh.mShortcutTriggered, state); + check(!isZoomed(), state); + } break; + case STATE_ZOOMED: { + check(isZoomed(), state); + check(tapCount() < 2, state); + } break; + case STATE_2TAPS: { + check(!isZoomed(), state); + check(tapCount() == 2, state); + } break; + case STATE_ZOOMED_2TAPS: { + check(isZoomed(), state); + check(tapCount() == 2, state); + } break; + case STATE_DRAGGING: { + check(mMgh.mCurrentState == MagnificationGestureHandler.STATE_VIEWPORT_DRAGGING, + state); + check(mMgh.mViewportDraggingStateHandler.mZoomedInBeforeDrag, state); + } break; + case STATE_DRAGGING_TMP: { + check(mMgh.mCurrentState == MagnificationGestureHandler.STATE_VIEWPORT_DRAGGING, + state); + check(!mMgh.mViewportDraggingStateHandler.mZoomedInBeforeDrag, state); + } break; + case STATE_SHORTCUT_TRIGGERED: { + check(mMgh.mShortcutTriggered, state); + check(!isZoomed(), state); + } break; + case STATE_PANNING: { + check(mMgh.mCurrentState == MagnificationGestureHandler.STATE_PANNING_SCALING, + state); + check(!mMgh.mPanningScalingStateHandler.mScaling, state); + } break; + case STATE_SCALING_AND_PANNING: { + check(mMgh.mCurrentState == MagnificationGestureHandler.STATE_PANNING_SCALING, + state); + check(mMgh.mPanningScalingStateHandler.mScaling, state); + } break; + default: throw new IllegalArgumentException("Illegal state: " + state); + } + } + + /** + * Defines a "canonical" path from {@link #STATE_IDLE} to {@code state} + */ + private void goFromStateIdleTo(int state) { + try { + switch (state) { + case STATE_IDLE: { + mMgh.clearAndTransitionToStateDetecting(); + } break; + case STATE_2TAPS: { + goFromStateIdleTo(STATE_IDLE); + tap(); + tap(); + } break; + case STATE_ZOOMED: { + if (mMgh.mDetectTripleTap) { + goFromStateIdleTo(STATE_2TAPS); + tap(); + } else { + goFromStateIdleTo(STATE_SHORTCUT_TRIGGERED); + tap(); + } + } break; + case STATE_ZOOMED_2TAPS: { + goFromStateIdleTo(STATE_ZOOMED); + tap(); + tap(); + } break; + case STATE_DRAGGING: { + goFromStateIdleTo(STATE_ZOOMED_2TAPS); + send(downEvent()); + fastForward1sec(); + } break; + case STATE_DRAGGING_TMP: { + goFromStateIdleTo(STATE_2TAPS); + send(downEvent()); + fastForward1sec(); + } break; + case STATE_SHORTCUT_TRIGGERED: { + goFromStateIdleTo(STATE_IDLE); + triggerShortcut(); + } break; + case STATE_PANNING: { + goFromStateIdleTo(STATE_ZOOMED); + send(downEvent()); + send(pointerEvent(ACTION_POINTER_DOWN, DEFAULT_X * 2, DEFAULT_Y)); + } break; + case STATE_SCALING_AND_PANNING: { + goFromStateIdleTo(STATE_PANNING); + send(pointerEvent(ACTION_MOVE, DEFAULT_X * 2, DEFAULT_Y * 3)); + send(pointerEvent(ACTION_MOVE, DEFAULT_X * 2, DEFAULT_Y * 4)); + } break; + default: + throw new IllegalArgumentException("Illegal state: " + state); + } + } catch (Throwable t) { + throw new RuntimeException("Failed to go to state " + stateToString(state), t); + } + } + + /** + * Defines a "canonical" path from {@code state} to {@link #STATE_IDLE} + */ + private void returnToNormalFrom(int state) { + switch (state) { + case STATE_IDLE: { + // no op + } break; + case STATE_2TAPS: { + allowEventDelegation(); + fastForward1sec(); + } break; + case STATE_ZOOMED: { + if (mMgh.mDetectTripleTap) { + tap(); + tap(); + returnToNormalFrom(STATE_ZOOMED_2TAPS); + } else { + triggerShortcut(); + } + } break; + case STATE_ZOOMED_2TAPS: { + tap(); + } break; + case STATE_DRAGGING: { + send(upEvent()); + returnToNormalFrom(STATE_ZOOMED); + } break; + case STATE_DRAGGING_TMP: { + send(upEvent()); + } break; + case STATE_SHORTCUT_TRIGGERED: { + triggerShortcut(); + } break; + case STATE_PANNING: { + send(pointerEvent(ACTION_POINTER_UP, DEFAULT_X * 2, DEFAULT_Y)); + send(upEvent()); + returnToNormalFrom(STATE_ZOOMED); + } break; + case STATE_SCALING_AND_PANNING: { + returnToNormalFrom(STATE_PANNING); + } break; + default: throw new IllegalArgumentException("Illegal state: " + state); + } + } + + private void check(boolean condition, int expectedState) { + if (!condition) { + fail("Expected to be in state " + stateToString(expectedState) + stateDump()); + } + } + + private boolean isZoomed() { + return mMgh.mMagnificationController.isMagnifying(); + } + + private int tapCount() { + return mMgh.mDetectingStateHandler.tapCount(); + } + + private static String stateToString(int state) { + return DebugUtils.valueToString(MagnificationGestureHandlerTest.class, "STATE_", state); + } + + private void tap() { + MotionEvent downEvent = downEvent(); + send(downEvent); + send(upEvent(downEvent.getDownTime())); + } + + private void swipe() { + MotionEvent downEvent = downEvent(); + send(downEvent); + send(moveEvent(DEFAULT_X * 2, DEFAULT_Y * 2)); + send(upEvent(downEvent.getDownTime())); + } + + private void longTap() { + MotionEvent downEvent = downEvent(); + send(downEvent); + fastForward(2000); + send(upEvent(downEvent.getDownTime())); + } + + private void triggerShortcut() { + mMgh.notifyShortcutTriggered(); + } + + private void send(MotionEvent event) { + event.setSource(InputDevice.SOURCE_TOUCHSCREEN); + try { + mMgh.onMotionEvent(event, event, /* policyFlags */ 0); + } catch (Throwable t) { + throw new RuntimeException("Exception while handling " + event, t); + } + fastForward(1); + } + + private MotionEvent moveEvent(float x, float y) { + return MotionEvent.obtain(defaultDownTime(), mClock.now(), ACTION_MOVE, x, y, 0); + } + + private MotionEvent downEvent() { + return MotionEvent.obtain(mClock.now(), mClock.now(), + ACTION_DOWN, DEFAULT_X, DEFAULT_Y, 0); + } + + private MotionEvent upEvent() { + return upEvent(defaultDownTime()); + } + + private MotionEvent upEvent(long downTime) { + return MotionEvent.obtain(downTime, mClock.now(), + MotionEvent.ACTION_UP, DEFAULT_X, DEFAULT_Y, 0); + } + + private long defaultDownTime() { + MotionEvent lastDown = mMgh.mDetectingStateHandler.mLastDown; + return lastDown == null ? mClock.now() - 1 : lastDown.getDownTime(); + } + + private MotionEvent pointerEvent(int action, float x, float y) { + MotionEvent.PointerProperties defPointerProperties = new MotionEvent.PointerProperties(); + defPointerProperties.id = 0; + defPointerProperties.toolType = MotionEvent.TOOL_TYPE_FINGER; + MotionEvent.PointerProperties pointerProperties = new MotionEvent.PointerProperties(); + pointerProperties.id = 1; + pointerProperties.toolType = MotionEvent.TOOL_TYPE_FINGER; + + MotionEvent.PointerCoords defPointerCoords = new MotionEvent.PointerCoords(); + defPointerCoords.x = DEFAULT_X; + defPointerCoords.y = DEFAULT_Y; + MotionEvent.PointerCoords pointerCoords = new MotionEvent.PointerCoords(); + pointerCoords.x = x; + pointerCoords.y = y; + + return MotionEvent.obtain( + /* downTime */ mClock.now(), + /* eventTime */ mClock.now(), + /* action */ action, + /* pointerCount */ 2, + /* pointerProperties */ new MotionEvent.PointerProperties[] { + defPointerProperties, pointerProperties }, + /* pointerCoords */ new MotionEvent.PointerCoords[] { defPointerCoords, pointerCoords }, + /* metaState */ 0, + /* buttonState */ 0, + /* xPrecision */ 1.0f, + /* yPrecision */ 1.0f, + /* deviceId */ 0, + /* edgeFlags */ 0, + /* source */ InputDevice.SOURCE_TOUCHSCREEN, + /* flags */ 0); + } + + private String stateDump() { + return "\nCurrent state dump:\n" + mMgh + "\n" + mHandler.getPendingMessages(); + } +} diff --git a/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java new file mode 100644 index 000000000000..f63d438fd223 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/accessibility/UiAutomationManagerTest.java @@ -0,0 +1,160 @@ +/* + ** Copyright 2017, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +package com.android.server.accessibility; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.accessibilityservice.AccessibilityServiceInfo; +import android.accessibilityservice.IAccessibilityServiceClient; +import android.app.UiAutomation; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.view.WindowManagerInternal; +import android.view.accessibility.AccessibilityEvent; + +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * Tests for UiAutomationManager + */ +public class UiAutomationManagerTest { + static final int SERVICE_ID = 42; + + final UiAutomationManager mUiAutomationManager = new UiAutomationManager(); + + @Mock AccessibilityManagerService.UserState mMockUserState; + @Mock Context mMockContext; + @Mock AccessibilityServiceInfo mMockServiceInfo; + @Mock ResolveInfo mMockResolveInfo; + @Mock AccessibilityManagerService.SecurityPolicy mMockSecurityPolicy; + @Mock AccessibilityClientConnection.SystemSupport mMockSystemSupport; + @Mock WindowManagerInternal mMockWindowManagerInternal; + @Mock GlobalActionPerformer mMockGlobalActionPerformer; + @Mock IBinder mMockOwner; + @Mock IAccessibilityServiceClient mMockAccessibilityServiceClient; + @Mock IBinder mMockServiceAsBinder; + + @BeforeClass + public static void oneTimeInitialization() { + if (Looper.myLooper() == null) { + Looper.prepare(); + } + } + + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + + when(mMockSystemSupport.getKeyEventDispatcher()).thenReturn(mock(KeyEventDispatcher.class)); + + when(mMockServiceInfo.getResolveInfo()).thenReturn(mMockResolveInfo); + mMockResolveInfo.serviceInfo = mock(ServiceInfo.class); + mMockResolveInfo.serviceInfo.applicationInfo = mock(ApplicationInfo.class); + + when(mMockAccessibilityServiceClient.asBinder()).thenReturn(mMockServiceAsBinder); + } + + @Test + public void isRunning_returnsTrueOnlyWhenRunning() { + assertFalse(mUiAutomationManager.isUiAutomationRunningLocked()); + register(0); + assertTrue(mUiAutomationManager.isUiAutomationRunningLocked()); + unregister(); + assertFalse(mUiAutomationManager.isUiAutomationRunningLocked()); + } + + @Test + public void suppressingAccessibilityServicesLocked_dependsOnFlags() { + assertFalse(mUiAutomationManager.suppressingAccessibilityServicesLocked()); + register(0); + assertTrue(mUiAutomationManager.suppressingAccessibilityServicesLocked()); + unregister(); + assertFalse(mUiAutomationManager.suppressingAccessibilityServicesLocked()); + register(UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES); + assertFalse(mUiAutomationManager.suppressingAccessibilityServicesLocked()); + unregister(); + assertFalse(mUiAutomationManager.suppressingAccessibilityServicesLocked()); + } + + @Test + public void isTouchExplorationEnabledLocked_dependsOnInfoFlags() { + assertFalse(mUiAutomationManager.isTouchExplorationEnabledLocked()); + register(0); + assertFalse(mUiAutomationManager.isTouchExplorationEnabledLocked()); + unregister(); + mMockServiceInfo.flags = AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE; + register(0); + assertTrue(mUiAutomationManager.isTouchExplorationEnabledLocked()); + unregister(); + assertFalse(mUiAutomationManager.isTouchExplorationEnabledLocked()); + } + + @Test + public void canRetrieveInteractiveWindowsLocked_dependsOnInfoFlags() { + assertFalse(mUiAutomationManager.canRetrieveInteractiveWindowsLocked()); + register(0); + assertFalse(mUiAutomationManager.canRetrieveInteractiveWindowsLocked()); + unregister(); + mMockServiceInfo.flags = AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS; + register(0); + assertTrue(mUiAutomationManager.canRetrieveInteractiveWindowsLocked()); + unregister(); + assertFalse(mUiAutomationManager.canRetrieveInteractiveWindowsLocked()); + } + + @Test + public void getRequestedEventMaskLocked_dependsOnInfoEventTypes() { + assertEquals(0, mUiAutomationManager.getRequestedEventMaskLocked()); + mMockServiceInfo.eventTypes = 0; + register(0); + assertEquals(mMockServiceInfo.eventTypes, + mUiAutomationManager.getRequestedEventMaskLocked()); + unregister(); + mMockServiceInfo.eventTypes = AccessibilityEvent.TYPES_ALL_MASK; + register(0); + assertEquals(mMockServiceInfo.eventTypes, + mUiAutomationManager.getRequestedEventMaskLocked()); + unregister(); + assertEquals(0, mUiAutomationManager.getRequestedEventMaskLocked()); + } + + private void register(int flags) { + mUiAutomationManager.registerUiTestAutomationServiceLocked(mMockOwner, + mMockAccessibilityServiceClient, mMockContext, mMockServiceInfo, SERVICE_ID, + new Handler(), new Object(), mMockSecurityPolicy, mMockSystemSupport, + mMockWindowManagerInternal, mMockGlobalActionPerformer, flags); + } + + private void unregister() { + mUiAutomationManager.unregisterUiTestAutomationServiceLocked( + mMockAccessibilityServiceClient); + } +} diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java index 2252c85dddf2..47a3a7242a44 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java @@ -126,7 +126,7 @@ public class ActivityRecordTests extends ActivityTestsBase { // Verify with nav bar on the right. when(service.mWindowManager.getNavBarPosition()).thenReturn(navBarPosition); - task.getConfiguration().setAppBounds(taskBounds); + task.getConfiguration().windowConfiguration.setAppBounds(taskBounds); record.info.maxAspectRatio = aspectRatio; record.ensureActivityConfigurationLocked(0 /* globalChanges */, false /* preserveWindow */); assertEquals(expectedActivityBounds, record.getBounds()); diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java index fc9ab9635c57..661dd4fc828c 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java @@ -21,6 +21,7 @@ import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; import android.content.ComponentName; import android.graphics.Rect; @@ -117,4 +118,21 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase { assertTrue(stackTasks.contains(task)); } } + + /** + * Ensures that an activity is removed from the stopping activities list once it is resumed. + */ + @Test + public void testStoppingActivityRemovedWhenResumed() throws Exception { + final ActivityManagerService service = createActivityManagerService(); + final TaskRecord firstTask = createTask(service, testActivityComponent, + FULLSCREEN_WORKSPACE_STACK_ID); + final ActivityRecord firstActivity = createActivity(service, testActivityComponent, + firstTask); + service.mStackSupervisor.mStoppingActivities.add(firstActivity); + + firstActivity.completeResumeLocked(); + + assertFalse(service.mStackSupervisor.mStoppingActivities.contains(firstActivity)); + } } diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java index 48464e5e0248..80e241c0581f 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java @@ -17,9 +17,9 @@ package com.android.server.am; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; import android.app.ActivityManager; import android.content.ComponentName; @@ -78,10 +78,10 @@ public class ActivityStackTests extends ActivityTestsBase { service.mStackSupervisor.inResumeTopActivity = true; testStack.mResumedActivity = activityRecord; - final boolean waiting = testStack.checkReadyForSleepLocked(); + final boolean waiting = testStack.goToSleepIfPossible(false); // Ensure we report not being ready for sleep. - assertTrue(waiting); + assertFalse(waiting); // Make sure the resumed activity is untouched. assertEquals(testStack.mResumedActivity, activityRecord); diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java index 04b5bdebdca1..f3c00b197763 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java @@ -117,7 +117,7 @@ public class ActivityTestsBase { intent.setComponent(component); final TaskRecord task = new TaskRecord(service, 0, aInfo, intent /*intent*/, - null /*_taskDescription*/, new ActivityManager.TaskThumbnailInfo()); + null /*_taskDescription*/); final ActivityStack stack = service.mStackSupervisor.getStack(stackId, true /*createStaticStackIfNeeded*/, true /*onTop*/); service.mStackSupervisor.setFocusStackUnchecked("test", stack); @@ -145,6 +145,10 @@ public class ActivityTestsBase { protected ActivityStackSupervisor createStackSupervisor() { return new TestActivityStackSupervisor(this, mHandlerThread.getLooper()); } + + @Override + void updateUsageStats(ActivityRecord component, boolean resumed) { + } } /** @@ -218,6 +222,12 @@ public class ActivityTestsBase { return createTestStack(stackId, createOnTop); } + + // Always keep things awake + @Override + boolean hasAwakeDisplay() { + return true; + } } private static WindowManagerService prepareMockWindowManager() { @@ -265,8 +275,8 @@ public class ActivityTestsBase { } @Override - protected T createStackWindowController(int displayId, boolean onTop, - Rect outBounds) { + protected T createStackWindowController(int displayId, boolean onTop, Rect outBounds, + Configuration overrideConfig) { mContainerController = (T) WindowTestUtils.createMockStackWindowContainerController(); return mContainerController; } diff --git a/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java b/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java new file mode 100644 index 000000000000..e98e5bfb110e --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java @@ -0,0 +1,355 @@ +/* + * Copyright 2017, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.am; + +import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED; +import static android.app.ActivityManager.LOCK_TASK_MODE_NONE; +import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED; +import static android.os.Process.SYSTEM_UID; +import static com.android.server.am.LockTaskController.STATUS_BAR_MASK_LOCKED; +import static com.android.server.am.LockTaskController.STATUS_BAR_MASK_PINNED; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import android.app.StatusBarManager; +import android.app.admin.IDevicePolicyManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.UserHandle; +import android.platform.test.annotations.Presubmit; +import android.provider.Settings; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SmallTest; + +import com.android.internal.statusbar.IStatusBarService; +import com.android.internal.widget.LockPatternUtils; +import com.android.server.LocalServices; +import com.android.server.statusbar.StatusBarManagerInternal; +import com.android.server.wm.WindowManagerService; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.verification.VerificationMode; + +/** + * Unit tests for {@link LockTaskController}. + * + * Build/Install/Run: + * bit FrameworksServicesTests:com.android.server.am.LockTaskControllerTest + */ +@Presubmit +@SmallTest +public class LockTaskControllerTest { + private static final String TEST_PACKAGE_NAME = "com.test.package"; + private static final String TEST_CLASS_NAME = TEST_PACKAGE_NAME + ".TestClass"; + private static final int TEST_USER_ID = 123; + private static final int TEST_UID = 10467; + + @Mock private ActivityStackSupervisor mSupervisor; + @Mock private IDevicePolicyManager mDevicePolicyManager; + @Mock private IStatusBarService mStatusBarService; + @Mock private WindowManagerService mWindowManager; + @Mock private LockPatternUtils mLockPatternUtils; + @Mock private LockTaskNotify mLockTaskNotify; + @Mock private StatusBarManagerInternal mStatusBarManagerInternal; + + private LockTaskController mLockTaskController; + private Context mContext; + private String mLockToAppSetting; + + @Before + public void setUp() throws Exception { + // This property is used to allow mocking of package private classes with mockito + System.setProperty("dexmaker.share_classloader", "true"); + + MockitoAnnotations.initMocks(this); + + mContext = InstrumentationRegistry.getTargetContext(); + mLockToAppSetting = Settings.Secure.getString(mContext.getContentResolver(), + Settings.Secure.LOCK_TO_APP_EXIT_LOCKED); + + if (Looper.myLooper() == null) { + Looper.prepare(); + } + + mLockTaskController = new LockTaskController(mContext, mSupervisor, + new ImmediatelyExecuteHandler()); + + mLockTaskController.setWindowManager(mWindowManager); + mLockTaskController.mStatusBarService = mStatusBarService; + mLockTaskController.mDevicePolicyManager = mDevicePolicyManager; + mLockTaskController.mLockPatternUtils = mLockPatternUtils; + mLockTaskController.mLockTaskNotify = mLockTaskNotify; + + LocalServices.removeServiceForTest(StatusBarManagerInternal.class); + LocalServices.addService(StatusBarManagerInternal.class, mStatusBarManagerInternal); + } + + @After + public void tearDown() throws Exception { + Settings.Secure.putString(mContext.getContentResolver(), + Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, mLockToAppSetting); + } + + @Test + public void testPreconditions() { + // GIVEN nothing has happened + + // THEN current lock task mode should be NONE + assertEquals(LOCK_TASK_MODE_NONE, mLockTaskController.getLockTaskModeState()); + } + + @Test + public void testStartLockTaskMode_once() throws Exception { + // GIVEN a task record with whitelisted auth + TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED); + + // WHEN calling setLockTaskMode for LOCKED mode without resuming + mLockTaskController.startLockTaskMode(tr, false, TEST_UID); + + // THEN the lock task mode state should be LOCKED + assertEquals(LOCK_TASK_MODE_LOCKED, mLockTaskController.getLockTaskModeState()); + // THEN the task should be locked + assertTrue(mLockTaskController.checkLockedTask(tr)); + + // THEN lock task mode should be started + verifyLockTaskStarted(STATUS_BAR_MASK_LOCKED); + } + + @Test + public void testStartLockTaskMode_twice() throws Exception { + // GIVEN two task records with whitelisted auth + TaskRecord tr1 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED); + TaskRecord tr2 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED); + + // WHEN calling setLockTaskMode for LOCKED mode on both tasks + mLockTaskController.startLockTaskMode(tr1, false, TEST_UID); + mLockTaskController.startLockTaskMode(tr2, false, TEST_UID); + + // THEN the lock task mode state should be LOCKED + assertEquals(LOCK_TASK_MODE_LOCKED, mLockTaskController.getLockTaskModeState()); + // THEN neither of the tasks should be able to move to back of stack + assertTrue(mLockTaskController.checkLockedTask(tr1)); + assertTrue(mLockTaskController.checkLockedTask(tr2)); + + // THEN lock task mode should be started + verifyLockTaskStarted(STATUS_BAR_MASK_LOCKED); + } + + @Test + public void testStartLockTaskMode_pinningRequest() throws Exception { + // GIVEN a task record that is not whitelisted, i.e. with pinned auth + TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_PINNABLE); + + // WHEN calling startLockTaskMode + mLockTaskController.startLockTaskMode(tr, false, TEST_UID); + + // THEN a pinning request should be shown + verify(mStatusBarManagerInternal).showScreenPinningRequest(anyInt()); + } + + @Test + public void testStartLockTaskMode_pinnedBySystem() throws Exception { + // GIVEN a task record with pinned auth + TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_PINNABLE); + + // WHEN the system calls startLockTaskMode + mLockTaskController.startLockTaskMode(tr, true, SYSTEM_UID); + + // THEN the lock task mode state should be PINNED + assertEquals(LOCK_TASK_MODE_PINNED, mLockTaskController.getLockTaskModeState()); + // THEN the task should be locked + assertTrue(mLockTaskController.checkLockedTask(tr)); + + // THEN lock task mode should be started + verifyLockTaskStarted(STATUS_BAR_MASK_PINNED); + } + + @Test + public void testLockTaskViolation() throws Exception { + // GIVEN one task records with whitelisted auth that is in lock task mode + TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED); + mLockTaskController.startLockTaskMode(tr, false, TEST_UID); + + // THEN it's not a lock task violation to try and launch this task without clearing + assertFalse(mLockTaskController.isLockTaskModeViolation(tr, false)); + + // THEN it's a lock task violation to launch another task that is not whitelisted + assertTrue(mLockTaskController.isLockTaskModeViolation(getTaskRecord( + TaskRecord.LOCK_TASK_AUTH_PINNABLE))); + // THEN it's a lock task violation to launch another task that is disallowed from lock task + assertTrue(mLockTaskController.isLockTaskModeViolation(getTaskRecord( + TaskRecord.LOCK_TASK_AUTH_DONT_LOCK))); + + // THEN it's no a lock task violation to launch another task that is whitelisted + assertFalse(mLockTaskController.isLockTaskModeViolation(getTaskRecord( + TaskRecord.LOCK_TASK_AUTH_WHITELISTED))); + assertFalse(mLockTaskController.isLockTaskModeViolation(getTaskRecord( + TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE))); + // THEN it's not a lock task violation to launch another task that is priv launchable + assertFalse(mLockTaskController.isLockTaskModeViolation(getTaskRecord( + TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV))); + } + + @Test + public void testStopLockTaskMode() throws Exception { + // GIVEN one task record with whitelisted auth that is in lock task mode + TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED); + mLockTaskController.startLockTaskMode(tr, false, TEST_UID); + + // WHEN the same caller calls stopLockTaskMode + mLockTaskController.stopLockTaskMode(false, TEST_UID); + + // THEN the lock task mode should be NONE + assertEquals(LOCK_TASK_MODE_NONE, mLockTaskController.getLockTaskModeState()); + // THEN the task should no longer be locked + assertFalse(mLockTaskController.checkLockedTask(tr)); + // THEN lock task mode should have been finished + verifyLockTaskStopped(times(1)); + } + + @Test(expected = SecurityException.class) + public void testStopLockTaskMode_DifferentCaller() throws Exception { + // GIVEN one task record with whitelisted auth that is in lock task mode + TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED); + mLockTaskController.startLockTaskMode(tr, false, TEST_UID); + + // WHEN a different caller calls stopLockTaskMode + mLockTaskController.stopLockTaskMode(false, TEST_UID + 1); + + // THEN security exception should be thrown, because different caller tried to unlock + } + + @Test + public void testStopLockTaskMode_SystemCaller() throws Exception { + // GIVEN one task record with whitelisted auth that is in lock task mode + TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED); + mLockTaskController.startLockTaskMode(tr, false, TEST_UID); + + // WHEN system calls stopLockTaskMode + mLockTaskController.stopLockTaskMode(true, SYSTEM_UID); + + // THEN a lock tash toast should be shown + verify(mLockTaskNotify).showToast(LOCK_TASK_MODE_LOCKED); + // THEN lock task mode should still be active + assertEquals(LOCK_TASK_MODE_LOCKED, mLockTaskController.getLockTaskModeState()); + } + + @Test + public void testStopLockTaskMode_twoTasks() throws Exception { + // GIVEN two task records with whitelisted auth that is in lock task mode + TaskRecord tr1 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED); + TaskRecord tr2 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED); + mLockTaskController.startLockTaskMode(tr1, false, TEST_UID); + mLockTaskController.startLockTaskMode(tr2, false, TEST_UID); + + // WHEN calling stopLockTaskMode + mLockTaskController.stopLockTaskMode(false, TEST_UID); + + // THEN the lock task mode should still be active + assertEquals(LOCK_TASK_MODE_LOCKED, mLockTaskController.getLockTaskModeState()); + // THEN the first task should still be locked + assertTrue(mLockTaskController.checkLockedTask(tr1)); + // THEN the top task should no longer be locked + assertFalse(mLockTaskController.checkLockedTask(tr2)); + // THEN lock task mode should not have been finished + verifyLockTaskStopped(never()); + } + + @Test + public void testStopLockTaskMode_pinned() throws Exception { + // GIVEN one task records that is in pinned mode + TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_PINNABLE); + mLockTaskController.startLockTaskMode(tr, true, SYSTEM_UID); + // GIVEN that the keyguard is required to show after unlocking + Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, 1); + + // WHEN calling stopLockTask + mLockTaskController.stopLockTaskMode(true, SYSTEM_UID); + + // THEN the lock task mode should no longer be active + assertEquals(LOCK_TASK_MODE_NONE, mLockTaskController.getLockTaskModeState()); + // THEN the task should no longer be locked + assertFalse(mLockTaskController.checkLockedTask(tr)); + // THEN lock task mode should have been finished + verifyLockTaskStopped(times(1)); + // THEN the keyguard should be shown + verify(mLockPatternUtils).requireCredentialEntry(UserHandle.USER_ALL); + } + + private TaskRecord getTaskRecord(int lockTaskAuth) { + TaskRecord tr = mock(TaskRecord.class); + tr.mLockTaskAuth = lockTaskAuth; + tr.intent = new Intent() + .setComponent(new ComponentName(TEST_PACKAGE_NAME, TEST_CLASS_NAME)); + tr.userId = TEST_USER_ID; + return tr; + } + + private void verifyLockTaskStarted(int statusBarMask) throws Exception { + // THEN the keyguard should have been disabled + verify(mWindowManager).disableKeyguard(any(IBinder.class), anyString()); + // THEN the status bar should have been disabled + verify(mStatusBarService).disable(eq(statusBarMask), any(IBinder.class), + eq(mContext.getPackageName())); + // THEN the DO/PO should be informed about the operation + verify(mDevicePolicyManager).notifyLockTaskModeChanged(true, TEST_PACKAGE_NAME, + TEST_USER_ID); + } + + private void verifyLockTaskStopped(VerificationMode mode) throws Exception { + // THEN the keyguard should have been disabled + verify(mWindowManager, mode).reenableKeyguard(any(IBinder.class)); + // THEN the status bar should have been disabled + verify(mStatusBarService, mode).disable(eq(StatusBarManager.DISABLE_NONE), + any(IBinder.class), eq(mContext.getPackageName())); + // THEN the DO/PO should be informed about the operation + verify(mDevicePolicyManager, mode).notifyLockTaskModeChanged(false, null, TEST_USER_ID); + } + + /** + * Special handler implementation that executes any message / runnable posted immediately on the + * thread that it's posted on rather than enqueuing them on its looper. + */ + private static class ImmediatelyExecuteHandler extends Handler { + @Override + public boolean sendMessageAtTime(Message msg, long uptimeMillis) { + if (msg.getCallback() != null) { + msg.getCallback().run(); + } + return true; + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java index 7a4746a7f54b..4475de5aa14e 100644 --- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java @@ -16,7 +16,6 @@ package com.android.server.am; -import android.app.ActivityManager; import android.app.IUserSwitchObserver; import android.content.Context; import android.content.IIntentReceiver; @@ -57,16 +56,15 @@ import static com.android.server.am.ActivityManagerService.SYSTEM_USER_CURRENT_M import static com.android.server.am.ActivityManagerService.SYSTEM_USER_START_MSG; import static com.android.server.am.ActivityManagerService.USER_SWITCH_TIMEOUT_MSG; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; public class UserControllerTest extends AndroidTestCase { @@ -117,11 +115,7 @@ public class UserControllerTest extends AndroidTestCase { Mockito.verify(mInjector.getWindowManager(), never()).stopFreezingScreen(); Mockito.verify(mInjector.getWindowManager(), times(1)).setSwitchingUser(anyBoolean()); Mockito.verify(mInjector.getWindowManager()).setSwitchingUser(true); - Mockito.verify(mInjector.getActivityStackSupervisor()).setLockTaskModeLocked( - nullable(TaskRecord.class), - eq(ActivityManager.LOCK_TASK_MODE_NONE), - anyString(), - anyBoolean()); + Mockito.verify(mInjector.getLockTaskController()).clearLockTaskMode(anyString()); startForegroundUserAssertions(); } @@ -131,11 +125,7 @@ public class UserControllerTest extends AndroidTestCase { Mockito.verify( mInjector.getWindowManager(), never()).startFreezingScreen(anyInt(), anyInt()); Mockito.verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean()); - Mockito.verify(mInjector.getActivityStackSupervisor(), never()).setLockTaskModeLocked( - nullable(TaskRecord.class), - eq(ActivityManager.LOCK_TASK_MODE_NONE), - anyString(), - anyBoolean()); + verifyZeroInteractions(mInjector.getLockTaskController()); startBackgroundUserAssertions(); } @@ -324,6 +314,7 @@ public class UserControllerTest extends AndroidTestCase { UserManagerInternal userManagerInternalMock; WindowManagerService windowManagerMock; ActivityStackSupervisor activityStackSupervisor; + LockTaskController lockTaskController; private Context mCtx; List<Intent> sentIntents = new ArrayList<>(); @@ -337,6 +328,7 @@ public class UserControllerTest extends AndroidTestCase { userManagerInternalMock = mock(UserManagerInternal.class); windowManagerMock = mock(WindowManagerService.class); activityStackSupervisor = mock(ActivityStackSupervisor.class); + lockTaskController = mock(LockTaskController.class); } @Override @@ -399,6 +391,10 @@ public class UserControllerTest extends AndroidTestCase { ActivityStackSupervisor getActivityStackSupervisor() { return activityStackSupervisor; } + + LockTaskController getLockTaskController() { + return lockTaskController; + } } private static class TestHandler extends Handler { diff --git a/services/tests/servicestests/src/com/android/server/backup/BackupPasswordManagerTest.java b/services/tests/servicestests/src/com/android/server/backup/BackupPasswordManagerTest.java index 04c02510cb3d..bc162977de2b 100644 --- a/services/tests/servicestests/src/com/android/server/backup/BackupPasswordManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/backup/BackupPasswordManagerTest.java @@ -16,7 +16,7 @@ package com.android.server.backup; -import static com.android.server.testutis.TestUtils.assertExpectException; +import static com.android.server.testutils.TestUtils.assertExpectException; import static com.google.common.truth.Truth.assertThat; diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java index 650681e2755b..db0ec0702b9f 100644 --- a/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java +++ b/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java @@ -31,8 +31,6 @@ import com.android.server.backup.RefactoredBackupManagerService; import org.junit.Test; import org.junit.runner.RunWith; -import java.util.Random; - @SmallTest @Presubmit @RunWith(AndroidJUnit4.class) @@ -40,7 +38,10 @@ public class AppBackupUtilsTest { private static final String CUSTOM_BACKUP_AGENT_NAME = "custom.backup.agent"; private static final String TEST_PACKAGE_NAME = "test_package"; - private final Random mRandom = new Random(1000000009); + private static final Signature SIGNATURE_1 = generateSignature((byte) 1); + private static final Signature SIGNATURE_2 = generateSignature((byte) 2); + private static final Signature SIGNATURE_3 = generateSignature((byte) 3); + private static final Signature SIGNATURE_4 = generateSignature((byte) 4); @Test public void appIsEligibleForBackup_backupNotAllowed_returnsFalse() throws Exception { @@ -220,7 +221,7 @@ public class AppBackupUtilsTest { @Test public void signaturesMatch_targetIsNull_returnsFalse() throws Exception { - boolean result = AppBackupUtils.signaturesMatch(new Signature[0], null); + boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1}, null); assertThat(result).isFalse(); } @@ -237,61 +238,63 @@ public class AppBackupUtilsTest { } @Test - public void signaturesMatch_allowsUnsignedApps_bothSignaturesNull_returnsTrue() + public void signaturesMatch_disallowsUnsignedApps_storedSignatureNull_returnsFalse() throws Exception { PackageInfo packageInfo = new PackageInfo(); - packageInfo.signatures = null; + packageInfo.signatures = new Signature[] {SIGNATURE_1}; packageInfo.applicationInfo = new ApplicationInfo(); boolean result = AppBackupUtils.signaturesMatch(null, packageInfo); - assertThat(result).isTrue(); + assertThat(result).isFalse(); } @Test - public void signaturesMatch_allowsUnsignedApps_bothSignaturesEmpty_returnsTrue() + public void signaturesMatch_disallowsUnsignedApps_storedSignatureEmpty_returnsFalse() throws Exception { PackageInfo packageInfo = new PackageInfo(); - packageInfo.signatures = new Signature[0]; + packageInfo.signatures = new Signature[] {SIGNATURE_1}; packageInfo.applicationInfo = new ApplicationInfo(); boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo); - assertThat(result).isTrue(); + assertThat(result).isFalse(); } + @Test public void - signaturesMatch_allowsUnsignedApps_storedSignatureNullTargetSignatureEmpty_returnsTrue() + signaturesMatch_disallowsUnsignedApps_targetSignatureEmpty_returnsFalse() throws Exception { PackageInfo packageInfo = new PackageInfo(); packageInfo.signatures = new Signature[0]; packageInfo.applicationInfo = new ApplicationInfo(); - boolean result = AppBackupUtils.signaturesMatch(null, packageInfo); + boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1}, + packageInfo); - assertThat(result).isTrue(); + assertThat(result).isFalse(); } @Test public void - signaturesMatch_allowsUnsignedApps_storedSignatureEmptyTargetSignatureNull_returnsTrue() + signaturesMatch_disallowsUnsignedApps_targetSignatureNull_returnsFalse() throws Exception { PackageInfo packageInfo = new PackageInfo(); packageInfo.signatures = null; packageInfo.applicationInfo = new ApplicationInfo(); - boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo); + boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1}, + packageInfo); - assertThat(result).isTrue(); + assertThat(result).isFalse(); } @Test - public void - signaturesMatch_disallowsAppsUnsignedOnOnlyOneDevice_storedSignatureIsNull_returnsFalse() + public void signaturesMatch_disallowsUnsignedApps_bothSignaturesNull_returnsFalse() throws Exception { PackageInfo packageInfo = new PackageInfo(); - packageInfo.signatures = new Signature[]{generateRandomSignature()}; + packageInfo.signatures = null; packageInfo.applicationInfo = new ApplicationInfo(); boolean result = AppBackupUtils.signaturesMatch(null, packageInfo); @@ -300,37 +303,25 @@ public class AppBackupUtilsTest { } @Test - public void - signaturesMatch_disallowsAppsUnsignedOnOnlyOneDevice_targetSignatureIsNull_returnsFalse() + public void signaturesMatch_disallowsUnsignedApps_bothSignaturesEmpty_returnsFalse() throws Exception { PackageInfo packageInfo = new PackageInfo(); - packageInfo.signatures = null; + packageInfo.signatures = new Signature[0]; packageInfo.applicationInfo = new ApplicationInfo(); - boolean result = AppBackupUtils.signaturesMatch(new Signature[]{generateRandomSignature()}, - packageInfo); + boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo); assertThat(result).isFalse(); } @Test - public void signaturesMatch_signaturesMatch_returnsTrue() throws Exception { - Signature signature1 = generateRandomSignature(); - Signature signature2 = generateRandomSignature(); - Signature signature3 = generateRandomSignature(); - assertThat(signature1).isNotEqualTo(signature2); - assertThat(signature2).isNotEqualTo(signature3); - assertThat(signature1).isNotEqualTo(signature3); - - Signature signature1Copy = new Signature(signature1.toByteArray()); - Signature signature2Copy = new Signature(signature2.toByteArray()); - Signature signature3Copy = new Signature(signature3.toByteArray()); - assertThat(signature1Copy).isEqualTo(signature1); - assertThat(signature2Copy).isEqualTo(signature2); - assertThat(signature3Copy).isEqualTo(signature3); + public void signaturesMatch_equalSignatures_returnsTrue() throws Exception { + Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray()); + Signature signature2Copy = new Signature(SIGNATURE_2.toByteArray()); + Signature signature3Copy = new Signature(SIGNATURE_3.toByteArray()); PackageInfo packageInfo = new PackageInfo(); - packageInfo.signatures = new Signature[]{signature1, signature2, signature3}; + packageInfo.signatures = new Signature[]{SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}; packageInfo.applicationInfo = new ApplicationInfo(); boolean result = AppBackupUtils.signaturesMatch( @@ -341,20 +332,11 @@ public class AppBackupUtilsTest { @Test public void signaturesMatch_extraSignatureInTarget_returnsTrue() throws Exception { - Signature signature1 = generateRandomSignature(); - Signature signature2 = generateRandomSignature(); - Signature signature3 = generateRandomSignature(); - assertThat(signature1).isNotEqualTo(signature2); - assertThat(signature2).isNotEqualTo(signature3); - assertThat(signature1).isNotEqualTo(signature3); - - Signature signature1Copy = new Signature(signature1.toByteArray()); - Signature signature2Copy = new Signature(signature2.toByteArray()); - assertThat(signature1Copy).isEqualTo(signature1); - assertThat(signature2Copy).isEqualTo(signature2); + Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray()); + Signature signature2Copy = new Signature(SIGNATURE_2.toByteArray()); PackageInfo packageInfo = new PackageInfo(); - packageInfo.signatures = new Signature[]{signature1, signature2, signature3}; + packageInfo.signatures = new Signature[]{SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}; packageInfo.applicationInfo = new ApplicationInfo(); boolean result = AppBackupUtils.signaturesMatch( @@ -365,96 +347,37 @@ public class AppBackupUtilsTest { @Test public void signaturesMatch_extraSignatureInStored_returnsFalse() throws Exception { - Signature signature1 = generateRandomSignature(); - Signature signature2 = generateRandomSignature(); - Signature signature3 = generateRandomSignature(); - assertThat(signature1).isNotEqualTo(signature2); - assertThat(signature2).isNotEqualTo(signature3); - assertThat(signature1).isNotEqualTo(signature3); - - Signature signature1Copy = new Signature(signature1.toByteArray()); - Signature signature2Copy = new Signature(signature2.toByteArray()); - assertThat(signature1Copy).isEqualTo(signature1); - assertThat(signature2Copy).isEqualTo(signature2); + Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray()); + Signature signature2Copy = new Signature(SIGNATURE_2.toByteArray()); PackageInfo packageInfo = new PackageInfo(); packageInfo.signatures = new Signature[]{signature1Copy, signature2Copy}; packageInfo.applicationInfo = new ApplicationInfo(); boolean result = AppBackupUtils.signaturesMatch( - new Signature[]{signature1, signature2, signature3}, packageInfo); - - assertThat(result).isFalse(); - } - - @Test - public void signaturesMatch_emptyStoredSignatures_returnsTrue() throws Exception { - Signature signature1 = generateRandomSignature(); - Signature signature2 = generateRandomSignature(); - Signature signature3 = generateRandomSignature(); - assertThat(signature1).isNotEqualTo(signature2); - assertThat(signature2).isNotEqualTo(signature3); - assertThat(signature1).isNotEqualTo(signature3); - - PackageInfo packageInfo = new PackageInfo(); - packageInfo.signatures = new Signature[]{signature1, signature2, signature3}; - packageInfo.applicationInfo = new ApplicationInfo(); - - boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo); - - assertThat(result).isTrue(); - } - - @Test - public void signaturesMatch_emptyTargetSignatures_returnsFalse() throws Exception { - Signature signature1 = generateRandomSignature(); - Signature signature2 = generateRandomSignature(); - Signature signature3 = generateRandomSignature(); - assertThat(signature1).isNotEqualTo(signature2); - assertThat(signature2).isNotEqualTo(signature3); - assertThat(signature1).isNotEqualTo(signature3); - - PackageInfo packageInfo = new PackageInfo(); - packageInfo.signatures = new Signature[0]; - packageInfo.applicationInfo = new ApplicationInfo(); - - boolean result = AppBackupUtils.signaturesMatch( - new Signature[]{signature1, signature2, signature3}, packageInfo); + new Signature[]{SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}, packageInfo); assertThat(result).isFalse(); } @Test public void signaturesMatch_oneNonMatchingSignature_returnsFalse() throws Exception { - Signature signature1 = generateRandomSignature(); - Signature signature2 = generateRandomSignature(); - Signature signature3 = generateRandomSignature(); - Signature signature4 = generateRandomSignature(); - assertThat(signature1).isNotEqualTo(signature2); - assertThat(signature2).isNotEqualTo(signature3); - assertThat(signature1).isNotEqualTo(signature3); - assertThat(signature1).isNotEqualTo(signature4); - assertThat(signature2).isNotEqualTo(signature4); - assertThat(signature3).isNotEqualTo(signature4); - - Signature signature1Copy = new Signature(signature1.toByteArray()); - Signature signature2Copy = new Signature(signature2.toByteArray()); - assertThat(signature1Copy).isEqualTo(signature1); - assertThat(signature2Copy).isEqualTo(signature2); + Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray()); + Signature signature2Copy = new Signature(SIGNATURE_2.toByteArray()); PackageInfo packageInfo = new PackageInfo(); - packageInfo.signatures = new Signature[]{signature1, signature2, signature3}; + packageInfo.signatures = new Signature[]{SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}; packageInfo.applicationInfo = new ApplicationInfo(); boolean result = AppBackupUtils.signaturesMatch( - new Signature[]{signature1Copy, signature2Copy, signature4}, packageInfo); + new Signature[]{signature1Copy, signature2Copy, SIGNATURE_4}, packageInfo); assertThat(result).isFalse(); } - private Signature generateRandomSignature() { + private static Signature generateSignature(byte i) { byte[] signatureBytes = new byte[256]; - mRandom.nextBytes(signatureBytes); + signatureBytes[0] = i; return new Signature(signatureBytes); } } diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index e3faa5280859..0fda0fe8c738 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -22,7 +22,7 @@ import static android.os.UserManagerInternal.CAMERA_DISABLED_GLOBALLY; import static android.os.UserManagerInternal.CAMERA_DISABLED_LOCALLY; import static android.os.UserManagerInternal.CAMERA_NOT_DISABLED; -import static com.android.server.testutis.TestUtils.assertExpectException; +import static com.android.server.testutils.TestUtils.assertExpectException; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; @@ -54,7 +54,6 @@ import android.app.admin.DevicePolicyManagerInternal; import android.app.admin.PasswordMetrics; import android.content.BroadcastReceiver; import android.content.ComponentName; -import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; diff --git a/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java b/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java index 5b4c10f11af8..7f48b8e1759a 100644 --- a/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java +++ b/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java @@ -16,48 +16,37 @@ package com.android.server.net; -import static android.util.DebugUtils.valueToString; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import com.android.frameworks.servicestests.R; +import com.android.servicestests.aidl.ICmdReceiverService; import com.android.servicestests.aidl.INetworkStateObserver; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; -import android.content.IntentSender; -import android.content.pm.IPackageDeleteObserver; -import android.content.pm.PackageInstaller; +import android.content.ServiceConnection; import android.content.pm.PackageManager; -import android.net.Uri; import android.os.BatteryManager; import android.os.Bundle; -import android.os.RemoteException; +import android.os.IBinder; import android.os.SystemClock; +import android.provider.Settings; import android.support.test.InstrumentationRegistry; import android.support.test.filters.LargeTest; import android.support.test.runner.AndroidJUnit4; import android.support.test.uiautomator.UiDevice; import android.util.Log; -import libcore.io.IoUtils; - import org.junit.AfterClass; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -76,62 +65,118 @@ import java.util.concurrent.TimeUnit; * Run: adb shell am instrument -e class com.android.server.net.ConnOnActivityStartTest -w \ * com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner */ -@Ignore @LargeTest @RunWith(AndroidJUnit4.class) public class ConnOnActivityStartTest { private static final String TAG = ConnOnActivityStartTest.class.getSimpleName(); - private static final String ACTION_INSTALL_COMPLETE = "com.android.server.net.INSTALL_COMPLETE"; - - private static final String TEST_APP_URI = - "android.resource://com.android.frameworks.servicestests/raw/conntestapp"; private static final String TEST_PKG = "com.android.servicestests.apps.conntestapp"; private static final String TEST_ACTIVITY_CLASS = TEST_PKG + ".ConnTestActivity"; - - private static final String ACTION_FINISH_ACTIVITY = TEST_PKG + ".FINISH"; + private static final String TEST_SERVICE_CLASS = TEST_PKG + ".CmdReceiverService"; private static final String EXTRA_NETWORK_STATE_OBSERVER = TEST_PKG + ".observer"; private static final long BATTERY_OFF_TIMEOUT_MS = 2000; // 2 sec private static final long BATTERY_OFF_CHECK_INTERVAL_MS = 200; // 0.2 sec - private static final long WAIT_FOR_INSTALL_TIMEOUT_MS = 2000; // 2 sec - private static final long NETWORK_CHECK_TIMEOUT_MS = 4000; // 4 sec private static final long SCREEN_ON_DELAY_MS = 500; // 0.5 sec + private static final long BIND_SERVICE_TIMEOUT_SEC = 4; + private static final int REPEAT_TEST_COUNT = 5; + private static final String KEY_PAROLE_DURATION = "parole_duration"; + private static final String DESIRED_PAROLE_DURATION = "0"; + private static Context mContext; private static UiDevice mUiDevice; private static int mTestPkgUid; private static BatteryManager mBatteryManager; + private static boolean mAppIdleConstsUpdated; + private static String mOriginalAppIdleConsts; + + private static ServiceConnection mServiceConnection; + private static ICmdReceiverService mCmdReceiverService; + @BeforeClass public static void setUpOnce() throws Exception { mContext = InstrumentationRegistry.getContext(); mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); - installAppAndAssertInstalled(); + setDesiredParoleDuration(); mContext.getPackageManager().setApplicationEnabledSetting(TEST_PKG, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0); mTestPkgUid = mContext.getPackageManager().getPackageUid(TEST_PKG, 0); mBatteryManager = (BatteryManager) mContext.getSystemService(Context.BATTERY_SERVICE); + bindService(); } @AfterClass public static void tearDownOnce() { - mContext.getPackageManager().deletePackage(TEST_PKG, - new IPackageDeleteObserver.Stub() { - @Override - public void packageDeleted(String packageName, int returnCode) - throws RemoteException { - Log.e(TAG, packageName + " deleted, returnCode: " + returnCode); - } - }, 0); + if (mAppIdleConstsUpdated) { + Settings.Global.putString(mContext.getContentResolver(), + Settings.Global.APP_IDLE_CONSTANTS, mOriginalAppIdleConsts); + } + unbindService(); + } + + private static void bindService() throws Exception { + final CountDownLatch bindLatch = new CountDownLatch(1); + mServiceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + Log.i(TAG, "Service connected"); + mCmdReceiverService = ICmdReceiverService.Stub.asInterface(service); + bindLatch.countDown(); + } + + @Override + public void onServiceDisconnected(ComponentName name) { + Log.i(TAG, "Service disconnected"); + } + }; + final Intent intent = new Intent() + .setComponent(new ComponentName(TEST_PKG, TEST_SERVICE_CLASS)); + // Needs to use BIND_ALLOW_OOM_MANAGEMENT and BIND_NOT_FOREGROUND so that the test app + // does not run in the same process state as this app. + mContext.bindService(intent, mServiceConnection, + Context.BIND_AUTO_CREATE + | Context.BIND_ALLOW_OOM_MANAGEMENT + | Context.BIND_NOT_FOREGROUND); + if (!bindLatch.await(BIND_SERVICE_TIMEOUT_SEC, TimeUnit.SECONDS)) { + fail("Timed out waiting for the service to bind in " + mTestPkgUid); + } + } + + private static void unbindService() { + if (mCmdReceiverService != null) { + mContext.unbindService(mServiceConnection); + } + } + + private static void setDesiredParoleDuration() { + mOriginalAppIdleConsts = Settings.Global.getString(mContext.getContentResolver(), + Settings.Global.APP_IDLE_CONSTANTS); + String newAppIdleConstants; + final String newConstant = KEY_PAROLE_DURATION + "=" + DESIRED_PAROLE_DURATION; + if (mOriginalAppIdleConsts == null || "null".equals(mOriginalAppIdleConsts)) { + // app_idle_constants is initially empty, so just assign the desired value. + newAppIdleConstants = newConstant; + } else if (mOriginalAppIdleConsts.contains(KEY_PAROLE_DURATION)) { + // app_idle_constants contains parole_duration, so replace it with the desired value. + newAppIdleConstants = mOriginalAppIdleConsts.replaceAll( + KEY_PAROLE_DURATION + "=\\d+", newConstant); + } else { + // app_idle_constants didn't have parole_duration, so append the desired value. + newAppIdleConstants = mOriginalAppIdleConsts + "," + newConstant; + } + Settings.Global.putString(mContext.getContentResolver(), + Settings.Global.APP_IDLE_CONSTANTS, newAppIdleConstants); + mAppIdleConstsUpdated = true; } @Test @@ -174,6 +219,7 @@ public class ConnOnActivityStartTest { startActivityAndCheckNetworkAccess(); } finally { turnBatteryOn(); + finishActivity(); setAppIdle(false); } } @@ -195,9 +241,9 @@ public class ConnOnActivityStartTest { turnScreenOn(); SystemClock.sleep(SCREEN_ON_DELAY_MS); startActivityAndCheckNetworkAccess(); - Log.d(TAG, testName + " end #" + i); } finally { finishActivity(); + Log.d(TAG, testName + " end #" + i); } } } @@ -348,74 +394,7 @@ public class ConnOnActivityStartTest { } } - private void finishActivity() { - final Intent finishIntent = new Intent(ACTION_FINISH_ACTIVITY) - .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - mContext.sendBroadcast(finishIntent); - } - private static void installAppAndAssertInstalled() throws Exception { - final CountDownLatch latch = new CountDownLatch(1); - final int[] result = {PackageInstaller.STATUS_SUCCESS}; - final BroadcastReceiver installStatusReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String pkgName = intent.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME); - if (!TEST_PKG.equals(pkgName)) { - return; - } - result[0] = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, - PackageInstaller.STATUS_FAILURE); - latch.countDown(); - } - }; - mContext.registerReceiver(installStatusReceiver, new IntentFilter(ACTION_INSTALL_COMPLETE)); - try { - installApp(); - if (latch.await(WAIT_FOR_INSTALL_TIMEOUT_MS, TimeUnit.MILLISECONDS)) { - if (result[0] != PackageInstaller.STATUS_SUCCESS) { - fail("Couldn't install test app, result: " - + valueToString(PackageInstaller.class, "STATUS_", result[0])); - } - } else { - fail("Timed out waiting for the test app to install"); - } - } finally { - mContext.unregisterReceiver(installStatusReceiver); - } - } - - private static void installApp() throws Exception { - final Uri packageUri = Uri.parse(TEST_APP_URI); - final InputStream in = mContext.getContentResolver().openInputStream(packageUri); - - final PackageInstaller packageInstaller - = mContext.getPackageManager().getPackageInstaller(); - final PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( - PackageInstaller.SessionParams.MODE_FULL_INSTALL); - params.setAppPackageName(TEST_PKG); - - final int sessionId = packageInstaller.createSession(params); - final PackageInstaller.Session session = packageInstaller.openSession(sessionId); - - OutputStream out = null; - try { - out = session.openWrite(TAG, 0, -1); - final byte[] buffer = new byte[65536]; - int c; - while ((c = in.read(buffer)) != -1) { - out.write(buffer, 0, c); - } - session.fsync(out); - } finally { - IoUtils.closeQuietly(in); - IoUtils.closeQuietly(out); - } - session.commit(createIntentSender(mContext, sessionId)); - } - - private static IntentSender createIntentSender(Context context, int sessionId) { - PendingIntent pendingIntent = PendingIntent.getBroadcast( - context, sessionId, new Intent(ACTION_INSTALL_COMPLETE), 0); - return pendingIntent.getIntentSender(); + private void finishActivity() throws Exception { + mCmdReceiverService.finishActivity(); } }
\ No newline at end of file diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java index 0e8960e94c56..fa8feb048fd6 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java @@ -467,7 +467,8 @@ public class PackageParserTest { pkg.staticSharedLibVersion = 100; pkg.usesStaticLibraries = new ArrayList<>(); pkg.usesStaticLibraries.add("foo23"); - pkg.usesStaticLibrariesCertDigests = new String[] { "digest" }; + pkg.usesStaticLibrariesCertDigests = new String[1][]; + pkg.usesStaticLibrariesCertDigests[0] = new String[] { "digest" }; pkg.usesStaticLibrariesVersions = new int[] { 100 }; pkg.libraryNames = new ArrayList<>(); 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 d12c07a84004..14b1ce1662c7 100644 --- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java @@ -20,6 +20,7 @@ import android.content.Context; import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest; import android.os.PowerManager; import android.os.PowerSaveState; +import android.os.SystemProperties; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; import android.text.TextUtils; @@ -44,17 +45,14 @@ public class PowerManagerServiceTest extends AndroidTestCase { private static final float PRECISION = 0.001f; private static final float BRIGHTNESS_FACTOR = 0.7f; private static final boolean BATTERY_SAVER_ENABLED = true; - private static final String LAST_REBOOT_REASON = "last_reboot_reason"; + private static final String TEST_LAST_REBOOT_PROPERTY = "test.sys.boot.reason"; private @Mock BatterySaverPolicy mBatterySaverPolicy; private PowerManagerService mService; private PowerSaveState mPowerSaveState; private DisplayPowerRequest mDisplayPowerRequest; - private File mTempReason; @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - public void setUp() throws Exception { super.setUp(); MockitoAnnotations.initMocks(this); @@ -68,8 +66,6 @@ public class PowerManagerServiceTest extends AndroidTestCase { .thenReturn(mPowerSaveState); mDisplayPowerRequest = new DisplayPowerRequest(); mService = new PowerManagerService(getContext(), mBatterySaverPolicy); - temporaryFolder.create(); - mTempReason = temporaryFolder.newFile(LAST_REBOOT_REASON); } @SmallTest @@ -82,14 +78,9 @@ public class PowerManagerServiceTest extends AndroidTestCase { @SmallTest public void testGetLastShutdownReasonInternal() { - try { - FileWriter writer = new FileWriter(mTempReason); - writer.append("thermal-shutdown\n"); - writer.close(); - } catch (IOException e) { - e.printStackTrace(); - } - int reason = mService.getLastShutdownReasonInternal(mTempReason); + SystemProperties.set(TEST_LAST_REBOOT_PROPERTY, "shutdown,thermal"); + int reason = mService.getLastShutdownReasonInternal(TEST_LAST_REBOOT_PROPERTY); + SystemProperties.set(TEST_LAST_REBOOT_PROPERTY, ""); assertThat(reason).isEqualTo(PowerManager.SHUTDOWN_REASON_THERMAL_SHUTDOWN); } } diff --git a/services/tests/servicestests/src/com/android/server/testutils/OffsettableClock.java b/services/tests/servicestests/src/com/android/server/testutils/OffsettableClock.java new file mode 100644 index 000000000000..8dabbc4d4356 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/testutils/OffsettableClock.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.testutils; + +import android.os.SystemClock; + +import java.util.function.LongSupplier; + +/** + * A time supplier (in the format of a {@code long} as the amount of milliseconds) similar + * to {@link SystemClock#uptimeMillis()}, but with the ability to {@link #fastForward} + * and {@link #rewind} + * + * Implements {@link LongSupplier} to be interchangeable with {@code SystemClock::uptimeMillis} + * + * Can be provided to {@link TestHandler} to "mock time" for the delayed execution testing + * + * @see OffsettableClock.Stopped for a version of this clock that does not advance on its own + */ +public class OffsettableClock implements LongSupplier { + private long mOffset = 0L; + + /** + * @return Current time in milliseconds, according to this clock + */ + public long now() { + return realNow() + mOffset; + } + + /** + * Can be overriden with a constant for a clock that stands still, and is only ever moved + * manually + */ + public long realNow() { + return SystemClock.uptimeMillis(); + } + + public void fastForward(long timeMs) { + mOffset += timeMs; + } + public void rewind(long timeMs) { + fastForward(-timeMs); + } + public void reset() { + mOffset = 0; + } + + /** @deprecated Only present for {@link LongSupplier} contract */ + @Override + @Deprecated + public long getAsLong() { + return now(); + } + + /** + * An {@link OffsettableClock} that does not advance with real time, and can only be + * advanced manually via {@link #fastForward} + */ + public static class Stopped extends OffsettableClock { + @Override + public long realNow() { + return 0L; + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/testutils/TestHandler.java b/services/tests/servicestests/src/com/android/server/testutils/TestHandler.java new file mode 100644 index 000000000000..2d4bc0f8b7d0 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/testutils/TestHandler.java @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.testutils; + + +import static android.util.ExceptionUtils.getRootCause; +import static android.util.ExceptionUtils.propagate; + +import android.os.Handler; +import android.os.Message; +import android.os.SystemClock; +import android.util.ArrayMap; + +import java.util.Map; +import java.util.PriorityQueue; +import java.util.function.LongSupplier; + +/** + * A test {@link Handler} that stores incoming {@link Message}s and {@link Runnable callbacks} + * in a {@link PriorityQueue} based on time, to be manually processed later in a correct order + * either all together with {@link #flush}, or only those due at the current time with + * {@link #timeAdvance}. + * + * For the latter use case this also supports providing a custom clock (in a format of a + * milliseconds-returning {@link LongSupplier}), that will be used for storing the messages' + * timestamps to be posted at, and checked against during {@link #timeAdvance}. + * + * This allows to test code that uses {@link Handler}'s delayed invocation capabilities, such as + * {@link Handler#sendMessageDelayed} or {@link Handler#postDelayed} without resorting to + * synchronously {@link Thread#sleep}ing in your test. + * + * @see OffsettableClock for a useful custom clock implementation to use with this handler + */ +public class TestHandler extends Handler { + private static final LongSupplier DEFAULT_CLOCK = SystemClock::uptimeMillis; + + private final PriorityQueue<MsgInfo> mMessages = new PriorityQueue<>(); + /** + * Map of: {@code message id -> count of such messages currently pending } + */ + // Boxing is ok here - both msg ids and their pending counts tend to be well below 128 + private final Map<Integer, Integer> mPendingMsgTypeCounts = new ArrayMap<>(); + private final LongSupplier mClock; + + public TestHandler(Callback callback) { + this(callback, DEFAULT_CLOCK); + } + + public TestHandler(Callback callback, LongSupplier clock) { + super(callback); + mClock = clock; + } + + @Override + public boolean sendMessageAtTime(Message msg, long uptimeMillis) { + mPendingMsgTypeCounts.put(msg.what, + mPendingMsgTypeCounts.getOrDefault(msg.what, 0) + 1); + + // uptimeMillis is an absolute time obtained as SystemClock.uptimeMillis() + offsetMillis + // if custom clock is given, recalculate the time with regards to it + if (mClock != DEFAULT_CLOCK) { + uptimeMillis = uptimeMillis - SystemClock.uptimeMillis() + mClock.getAsLong(); + } + + // post a dummy queue entry to keep track of message removal + return super.sendMessageAtTime(msg, Long.MAX_VALUE) + && mMessages.add(new MsgInfo(Message.obtain(msg), uptimeMillis)); + } + + /** @see TestHandler */ + public void timeAdvance() { + long now = mClock.getAsLong(); + while (!mMessages.isEmpty() && mMessages.peek().sendTime <= now) { + dispatch(mMessages.poll()); + } + } + + /** + * Dispatch all messages in order + * + * @see TestHandler + */ + public void flush() { + MsgInfo msg; + while ((msg = mMessages.poll()) != null) { + dispatch(msg); + } + } + + public PriorityQueue<MsgInfo> getPendingMessages() { + return new PriorityQueue<>(mMessages); + } + + private void dispatch(MsgInfo msg) { + int msgId = msg.message.what; + + if (!hasMessages(msgId)) { + // Handler.removeMessages(msgId) must have been called + return; + } + + try { + Integer pendingMsgCount = mPendingMsgTypeCounts.getOrDefault(msgId, 0); + if (pendingMsgCount <= 1) { + removeMessages(msgId); + } + mPendingMsgTypeCounts.put(msgId, pendingMsgCount - 1); + + dispatchMessage(msg.message); + } catch (Throwable t) { + // Append stack trace of this message being posted as a cause for a helpful + // test error message + throw propagate(getRootCause(t).initCause(msg.postPoint)); + } finally { + msg.message.recycle(); + } + } + + private class MsgInfo implements Comparable<MsgInfo> { + public final Message message; + public final long sendTime; + public final RuntimeException postPoint; + + private MsgInfo(Message message, long sendTime) { + this.message = message; + this.sendTime = sendTime; + this.postPoint = new RuntimeException("Message originated from here:"); + } + + @Override + public int compareTo(MsgInfo o) { + return (int) (sendTime - o.sendTime); + } + + @Override + public String toString() { + return "MsgInfo{" + + "message=" + message + + ", sendTime=" + sendTime + + '}'; + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/testutis/TestUtils.java b/services/tests/servicestests/src/com/android/server/testutils/TestUtils.java index 88289888b0dd..b200293ee916 100644 --- a/services/tests/servicestests/src/com/android/server/testutis/TestUtils.java +++ b/services/tests/servicestests/src/com/android/server/testutils/TestUtils.java @@ -13,12 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.server.testutis; +package com.android.server.testutils; import android.test.MoreAsserts; import junit.framework.Assert; +import org.mockito.Mockito; +import org.mockito.stubbing.Answer; + public class TestUtils { private TestUtils() { } @@ -44,4 +47,17 @@ public class TestUtils { Assert.fail("Expected exception type " + expectedExceptionType.getName() + " was not thrown"); } + + /** + * EasyMock-style "strict" mock that throws immediately on any interaction that was not + * explicitly allowed. + * + * You can allow certain method calls on a whitelist basis by stubbing them e.g. with + * {@link Mockito#doAnswer}, {@link Mockito#doNothing}, etc. + */ + public static <T> T strictMock(Class<T> c) { + return Mockito.mock(c, (Answer) invocation -> { + throw new AssertionError("Unexpected invocation: " + invocation); + }); + } } diff --git a/services/tests/servicestests/src/com/android/server/wallpaper/WallpaperServiceTests.java b/services/tests/servicestests/src/com/android/server/wallpaper/WallpaperServiceTests.java index 0d29e8963728..9c010a07135d 100644 --- a/services/tests/servicestests/src/com/android/server/wallpaper/WallpaperServiceTests.java +++ b/services/tests/servicestests/src/com/android/server/wallpaper/WallpaperServiceTests.java @@ -17,10 +17,14 @@ package com.android.server.wallpaper; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import android.app.WallpaperColors; +import android.os.Handler; +import android.os.Message; import android.os.SystemClock; import android.service.wallpaper.WallpaperService; +import android.support.test.annotation.UiThreadTest; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -28,18 +32,31 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.util.concurrent.CountDownLatch; +import java.util.function.Supplier; @SmallTest @RunWith(AndroidJUnit4.class) public class WallpaperServiceTests { + @UiThreadTest @Test public void testNotifyColorsChanged_rateLimit() throws Exception { + long[] clockOffset = {0}; + boolean[] postDelayed = {false}; + Supplier<Long> clockFunction = () -> SystemClock.elapsedRealtime() + clockOffset[0]; + Handler handler = new Handler() { + @Override + public boolean sendMessageAtTime(Message msg, long uptimeMillis) { + postDelayed[0] = true; + return super.sendMessageAtTime(msg, uptimeMillis); + } + }; + CountDownLatch eventCountdown = new CountDownLatch(2); WallpaperService service = new WallpaperService() { @Override public Engine onCreateEngine() { - return new WallpaperService.Engine() { + return new WallpaperService.Engine(clockFunction, handler) { @Override public WallpaperColors onComputeColors() { eventCountdown.countDown(); @@ -59,8 +76,11 @@ public class WallpaperServiceTests { engine.notifyColorsChanged(); assertEquals("OnComputeColors should have been throttled.", 1, eventCountdown.getCount()); - // Called after being deferred. - engine.setClockFunction(() -> SystemClock.elapsedRealtime() + 1500); + // Should have been posted to the handler. + assertTrue("Event should have been delayed", postDelayed[0]); + + // Called again after being deferred. + clockOffset[0] = 1500; engine.notifyColorsChanged(); assertEquals("OnComputeColors should have been deferred.", 0, eventCountdown.getCount()); diff --git a/services/tests/servicestests/src/com/android/server/wm/AppBoundsTests.java b/services/tests/servicestests/src/com/android/server/wm/AppBoundsTests.java deleted file mode 100644 index 432cfc7a22ee..000000000000 --- a/services/tests/servicestests/src/com/android/server/wm/AppBoundsTests.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.server.wm; - -import android.app.ActivityManager; -import android.content.pm.ActivityInfo; -import android.content.res.Configuration; -import android.graphics.Rect; -import android.view.DisplayInfo; -import org.junit.Test; - -import android.platform.test.annotations.Presubmit; -import android.support.test.filters.SmallTest; -import android.support.test.runner.AndroidJUnit4; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; - -/** - * Test class to exercise logic related to {@link android.content.res.Configuration#appBounds}. - * - * Build/Install/Run: - * bit FrameworksServicesTests:com.android.server.wm.AppBoundsTests - */ -@SmallTest -@Presubmit -@org.junit.runner.RunWith(AndroidJUnit4.class) -public class AppBoundsTests extends WindowTestsBase { - private Rect mParentBounds; - - @Override - public void setUp() throws Exception { - super.setUp(); - mParentBounds = new Rect(10 /*left*/, 30 /*top*/, 80 /*right*/, 60 /*bottom*/); - } - - /** - * Ensures that appBounds causes {@link android.content.pm.ActivityInfo.CONFIG_APP_BOUNDS} diff. - */ - @Test - public void testAppBoundsConfigurationDiff() { - final Configuration config = new Configuration(); - final Configuration config2 = new Configuration(); - config.appBounds = new Rect(0, 1, 1, 0); - config2.appBounds = new Rect(1, 2, 2, 1); - - assertEquals(ActivityInfo.CONFIG_SCREEN_SIZE, config.diff(config2)); - assertEquals(0, config.diffPublicOnly(config2)); - } - - /** - * Ensures the configuration app bounds at the root level match the app dimensions. - */ - @Test - public void testRootConfigurationBounds() throws Exception { - final DisplayInfo info = mDisplayContent.getDisplayInfo(); - info.appWidth = 1024; - info.appHeight = 768; - - final Configuration config = sWm.computeNewConfiguration(mDisplayContent.getDisplayId()); - // The bounds should always be positioned in the top left. - assertEquals(config.appBounds.left, 0); - assertEquals(config.appBounds.top, 0); - - // The bounds should equal the defined app width and height - assertEquals(config.appBounds.width(), info.appWidth); - assertEquals(config.appBounds.height(), info.appHeight); - } - - /** - * Ensures that bounds are clipped to their parent. - */ - @Test - public void testBoundsClipping() throws Exception { - final Rect shiftedBounds = new Rect(mParentBounds); - shiftedBounds.offset(10, 10); - final Rect expectedBounds = new Rect(mParentBounds); - expectedBounds.intersect(shiftedBounds); - testStackBoundsConfiguration(null /*stackId*/, mParentBounds, shiftedBounds, - expectedBounds); - } - - /** - * Ensures that empty bounds are not propagated to the configuration. - */ - @Test - public void testEmptyBounds() throws Exception { - final Rect emptyBounds = new Rect(); - testStackBoundsConfiguration(null /*stackId*/, mParentBounds, emptyBounds, - null /*ExpectedBounds*/); - } - - /** - * Ensures that bounds on freeform stacks are not clipped. - */ - @Test - public void testFreeFormBounds() throws Exception { - final Rect freeFormBounds = new Rect(mParentBounds); - freeFormBounds.offset(10, 10); - testStackBoundsConfiguration(ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID, - mParentBounds, freeFormBounds, freeFormBounds); - } - - /** - * Ensures that fully contained bounds are not clipped. - */ - @Test - public void testContainedBounds() throws Exception { - final Rect insetBounds = new Rect(mParentBounds); - insetBounds.inset(5, 5, 5, 5); - testStackBoundsConfiguration(null /*stackId*/, mParentBounds, insetBounds, insetBounds); - } - - /** - * Ensures that full screen free form bounds are clipped - */ - @Test - public void testFullScreenFreeFormBounds() throws Exception { - final Rect fullScreenBounds = new Rect(0, 0, mDisplayInfo.logicalWidth, - mDisplayInfo.logicalHeight); - testStackBoundsConfiguration(null /*stackId*/, mParentBounds, fullScreenBounds, - mParentBounds); - } - - private void testStackBoundsConfiguration(Integer stackId, Rect parentBounds, Rect bounds, - Rect expectedConfigBounds) { - final StackWindowController stackController = stackId != null ? - createStackControllerOnStackOnDisplay(stackId, mDisplayContent) - : createStackControllerOnDisplay(mDisplayContent); - - final Configuration parentConfig = mDisplayContent.getConfiguration(); - parentConfig.setAppBounds(parentBounds); - - final Configuration config = new Configuration(); - stackController.adjustConfigurationForBounds(bounds, null /*insetBounds*/, - new Rect() /*nonDecorBounds*/, new Rect() /*stableBounds*/, false /*overrideWidth*/, - false /*overrideHeight*/, mDisplayInfo.logicalDensityDpi, config, parentConfig); - // Assert that both expected and actual are null or are equal to each other - - assertTrue((expectedConfigBounds == null && config.appBounds == null) - || expectedConfigBounds.equals(config.appBounds)); - } - - /** - * Ensures appBounds are considered in {@link Configuration#compareTo(Configuration)}. - */ - @Test - public void testConfigurationCompareTo() throws Exception { - final Configuration blankConfig = new Configuration(); - - final Configuration config1 = new Configuration(); - config1.appBounds = new Rect(1, 2, 3, 4); - - final Configuration config2 = new Configuration(config1); - - assertEquals(config1.compareTo(config2), 0); - - config2.appBounds.left = 0; - - // Different bounds - assertNotEquals(config1.compareTo(config2), 0); - - // No bounds - assertEquals(config1.compareTo(blankConfig), -1); - assertEquals(blankConfig.compareTo(config1), 1); - - } -} diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java index b09601e698f9..9ad7addab858 100644 --- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java @@ -97,6 +97,24 @@ public class AppWindowTokenTests extends WindowTestsBase { } @Test + public void testGetTopFullscreenWindow() throws Exception { + final WindowTestUtils.TestAppWindowToken token = + new WindowTestUtils.TestAppWindowToken(mDisplayContent); + + assertNull(token.getTopFullscreenWindow()); + + final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, token, "window1"); + final WindowState window11 = createWindow(null, TYPE_APPLICATION, token, "window11"); + final WindowState window12 = createWindow(null, TYPE_APPLICATION, token, "window12"); + assertEquals(window12, token.getTopFullscreenWindow()); + window12.mAttrs.width = 500; + assertEquals(window11, token.getTopFullscreenWindow()); + window11.mAttrs.width = 500; + assertEquals(window1, token.getTopFullscreenWindow()); + token.removeImmediately(); + } + + @Test public void testLandscapeSeascapeRotationByApp() throws Exception { // Some plumbing to get the service ready for rotation updates. sWm.mDisplayReady = true; diff --git a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java index 9d32496c7817..0081214a24da 100644 --- a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java @@ -126,6 +126,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase { boolean mMovedToFullscreen; boolean mAnimationStarted; boolean mSchedulePipModeChangedOnStart; + boolean mForcePipModeChangedCallback; boolean mAnimationEnded; Rect mAnimationEndFinalStackBounds; boolean mSchedulePipModeChangedOnEnd; @@ -140,6 +141,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase { mAnimationStarted = false; mAnimationEnded = false; mAnimationEndFinalStackBounds = null; + mForcePipModeChangedCallback = false; mSchedulePipModeChangedOnStart = false; mSchedulePipModeChangedOnEnd = false; mStackBounds = from; @@ -148,10 +150,11 @@ public class BoundsAnimationControllerTests extends WindowTestsBase { } @Override - public void onAnimationStart(boolean schedulePipModeChangedCallback) { + public void onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate) { mAwaitingAnimationStart = false; mAnimationStarted = true; mSchedulePipModeChangedOnStart = schedulePipModeChangedCallback; + mForcePipModeChangedCallback = forceUpdate; } @Override @@ -232,7 +235,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase { return this; } - BoundsAnimationDriver restart(Rect to) { + BoundsAnimationDriver restart(Rect to, boolean expectStartedAndPipModeChangedCallback) { if (mAnimator == null) { throw new IllegalArgumentException("Call start() to start a new animation"); } @@ -251,8 +254,15 @@ public class BoundsAnimationControllerTests extends WindowTestsBase { assertSame(oldAnimator, mAnimator); } - // No animation start for replacing animation - assertTrue(!mTarget.mAnimationStarted); + if (expectStartedAndPipModeChangedCallback) { + // Replacing animation with pending pip mode changed callback, ensure we update + assertTrue(mTarget.mAnimationStarted); + assertTrue(mTarget.mSchedulePipModeChangedOnStart); + assertTrue(mTarget.mForcePipModeChangedCallback); + } else { + // No animation start for replacing animation + assertTrue(!mTarget.mAnimationStarted); + } mTarget.mAnimationStarted = true; return this; } @@ -467,7 +477,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase { mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING) .expectStarted(!SCHEDULE_PIP_MODE_CHANGED) .update(0.25f) - .restart(BOUNDS_FLOATING) + .restart(BOUNDS_FLOATING, false /* expectStartedAndPipModeChangedCallback */) .end() .expectEnded(SCHEDULE_PIP_MODE_CHANGED, !MOVE_TO_FULLSCREEN); } @@ -478,7 +488,8 @@ public class BoundsAnimationControllerTests extends WindowTestsBase { mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING) .expectStarted(!SCHEDULE_PIP_MODE_CHANGED) .update(0.25f) - .restart(BOUNDS_SMALLER_FLOATING) + .restart(BOUNDS_SMALLER_FLOATING, + false /* expectStartedAndPipModeChangedCallback */) .end() .expectEnded(SCHEDULE_PIP_MODE_CHANGED, !MOVE_TO_FULLSCREEN); } @@ -486,10 +497,12 @@ public class BoundsAnimationControllerTests extends WindowTestsBase { @UiThreadTest @Test public void testFullscreenToFloatingCancelFromAnimationToFullscreenBounds() throws Exception { + // When animating from fullscreen and the animation is interruped, we expect the animation + // start callback to be made, with a forced pip mode change callback mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING) .expectStarted(!SCHEDULE_PIP_MODE_CHANGED) .update(0.25f) - .restart(BOUNDS_FULL) + .restart(BOUNDS_FULL, true /* expectStartedAndPipModeChangedCallback */) .end() .expectEnded(!SCHEDULE_PIP_MODE_CHANGED, MOVE_TO_FULLSCREEN); } @@ -512,7 +525,7 @@ public class BoundsAnimationControllerTests extends WindowTestsBase { mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL) .expectStarted(SCHEDULE_PIP_MODE_CHANGED) .update(0.25f) - .restart(BOUNDS_FULL) + .restart(BOUNDS_FULL, false /* expectStartedAndPipModeChangedCallback */) .end() .expectEnded(!SCHEDULE_PIP_MODE_CHANGED, MOVE_TO_FULLSCREEN); } @@ -523,7 +536,8 @@ public class BoundsAnimationControllerTests extends WindowTestsBase { mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL) .expectStarted(SCHEDULE_PIP_MODE_CHANGED) .update(0.25f) - .restart(BOUNDS_SMALLER_FLOATING) + .restart(BOUNDS_SMALLER_FLOATING, + false /* expectStartedAndPipModeChangedCallback */) .end() .expectEnded(SCHEDULE_PIP_MODE_CHANGED, !MOVE_TO_FULLSCREEN); } diff --git a/services/tests/servicestests/src/com/android/server/am/ConfigurationContainerTests.java b/services/tests/servicestests/src/com/android/server/wm/ConfigurationContainerTests.java index fd2fb4b0d4c5..d441df024599 100644 --- a/services/tests/servicestests/src/com/android/server/am/ConfigurationContainerTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/ConfigurationContainerTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 The Android Open Source Project + * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,33 +14,37 @@ * limitations under the License */ -package com.android.server.am; +package com.android.server.wm; - -import org.junit.Test; -import org.junit.runner.RunWith; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import android.content.res.Configuration; import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; +import org.junit.Test; +import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.List; -import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; -import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; -import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; -import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT; -import static org.junit.Assert.assertEquals; - /** - * Test class for {@link ConfigurationContainer}. Mostly duplicates configuration tests from - * {@link com.android.server.wm.WindowContainerTests}. + * Test class for {@link ConfigurationContainer}. * - * Build: mmma -j32 frameworks/base/services/tests/servicestests - * Install: adb install -r out/target/product/$TARGET_PRODUCT/data/app/FrameworksServicesTests/FrameworksServicesTests.apk - * Run: adb shell am instrument -w -e class com.android.server.am.ConfigurationContainerTests com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner + * Build/Install/Run: + * bit FrameworksServicesTests:com.android.server.wm.ConfigurationContainerTests */ @SmallTest @Presubmit @@ -203,6 +207,62 @@ public class ConfigurationContainerTests { assertEquals(mergedConfig2, child2.getConfiguration()); } + @Test + public void testSetWindowingMode() throws Exception { + final TestConfigurationContainer root = new TestConfigurationContainer(); + root.setWindowingMode(WINDOWING_MODE_UNDEFINED); + final TestConfigurationContainer child = root.addChild(); + child.setWindowingMode(WINDOWING_MODE_FREEFORM); + assertEquals(WINDOWING_MODE_UNDEFINED, root.getWindowingMode()); + assertEquals(WINDOWING_MODE_FREEFORM, child.getWindowingMode()); + + root.setWindowingMode(WINDOWING_MODE_FULLSCREEN); + assertEquals(WINDOWING_MODE_FULLSCREEN, root.getWindowingMode()); + assertEquals(WINDOWING_MODE_FREEFORM, child.getWindowingMode()); + } + + @Test + public void testSetActivityType() throws Exception { + final TestConfigurationContainer root = new TestConfigurationContainer(); + root.setActivityType(ACTIVITY_TYPE_UNDEFINED); + final TestConfigurationContainer child = root.addChild(); + child.setActivityType(ACTIVITY_TYPE_STANDARD); + assertEquals(ACTIVITY_TYPE_UNDEFINED, root.getActivityType()); + assertEquals(ACTIVITY_TYPE_STANDARD, child.getActivityType()); + + boolean gotException = false; + try { + // Can't change activity type once set. + child.setActivityType(ACTIVITY_TYPE_HOME); + } catch (IllegalStateException e) { + gotException = true; + } + assertTrue("Can't change activity type once set.", gotException); + + gotException = false; + try { + // Parent can't change child's activity type once set. + root.setActivityType(ACTIVITY_TYPE_HOME); + } catch (IllegalStateException e) { + gotException = true; + } + assertTrue("Parent can't change activity type once set.", gotException); + assertEquals(ACTIVITY_TYPE_HOME, root.getActivityType()); + + final TestConfigurationContainer child2 = new TestConfigurationContainer(); + child2.setActivityType(ACTIVITY_TYPE_RECENTS); + + gotException = false; + try { + // Can't re-parent to a different activity type. + root.addChild(child2); + } catch (IllegalStateException e) { + gotException = true; + } + assertTrue("Can't re-parent to a different activity type.", gotException); + + } + /** * Contains minimal implementation of {@link ConfigurationContainer}'s abstract behavior needed * for testing. diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java index 91eb55ba3fcf..f732503ec51c 100644 --- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java @@ -350,14 +350,14 @@ public class DisplayContentTests extends WindowTestsBase { createStackControllerOnStackOnDisplay(PINNED_STACK_ID, mDisplayContent); final int initialStackCount = mDisplayContent.getStackCount(); // Ensure that the pinned stack was placed at the end - assertEquals(initialStackCount - 1, mDisplayContent.getStaskPosById(PINNED_STACK_ID)); + assertEquals(initialStackCount - 1, mDisplayContent.getStackPosById(PINNED_STACK_ID)); // By default, this should try to create a new stack on top createTaskStackOnDisplay(mDisplayContent); final int afterStackCount = mDisplayContent.getStackCount(); // Make sure the stack count has increased assertEquals(initialStackCount + 1, afterStackCount); // Ensure that the pinned stack is still on top - assertEquals(afterStackCount - 1, mDisplayContent.getStaskPosById(PINNED_STACK_ID)); + assertEquals(afterStackCount - 1, mDisplayContent.getStackPosById(PINNED_STACK_ID)); } /** diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java index 39c0de82e821..99f2685c6ce7 100644 --- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java +++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java @@ -19,6 +19,7 @@ package com.android.server.wm; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -140,6 +141,29 @@ public class TaskSnapshotPersisterLoaderTest extends TaskSnapshotPersisterTestBa } @Test + public void testLowResolutionPersistAndLoadSnapshot() { + TaskSnapshot a = createSnapshot(0.5f /* reducedResolution */); + assertTrue(a.isReducedResolution()); + mPersister.persistSnapshot(1 , mTestUserId, a); + mPersister.waitForQueueEmpty(); + final File[] files = new File[] { new File(sFilesDir.getPath() + "/snapshots/1.proto"), + new File(sFilesDir.getPath() + "/snapshots/1_reduced.jpg")}; + final File[] nonExistsFiles = new File[] { + new File(sFilesDir.getPath() + "/snapshots/1.jpg"), + }; + assertTrueForFiles(files, File::exists, " must exist"); + assertTrueForFiles(nonExistsFiles, file -> !file.exists(), " must not exist"); + final TaskSnapshot snapshot = mLoader.loadTask(1, mTestUserId, true /* reduced */); + assertNotNull(snapshot); + assertEquals(TEST_INSETS, snapshot.getContentInsets()); + assertNotNull(snapshot.getSnapshot()); + assertEquals(Configuration.ORIENTATION_PORTRAIT, snapshot.getOrientation()); + + final TaskSnapshot snapshotNotExist = mLoader.loadTask(1, mTestUserId, false /* reduced */); + assertNull(snapshotNotExist); + } + + @Test public void testRemoveObsoleteFiles() { mPersister.persistSnapshot(1, mTestUserId, createSnapshot()); mPersister.persistSnapshot(2, mTestUserId, createSnapshot()); diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java index 8146763ae871..b49a0fdf8f38 100644 --- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java +++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java @@ -80,12 +80,16 @@ class TaskSnapshotPersisterTestBase extends WindowTestsBase { } TaskSnapshot createSnapshot() { + return createSnapshot(1f /* scale */); + } + + TaskSnapshot createSnapshot(float scale) { final GraphicBuffer buffer = GraphicBuffer.create(100, 100, PixelFormat.RGBA_8888, USAGE_HW_TEXTURE | USAGE_SW_READ_RARELY | USAGE_SW_READ_RARELY); Canvas c = buffer.lockCanvas(); c.drawColor(Color.RED); buffer.unlockCanvasAndPost(c); return new TaskSnapshot(buffer, ORIENTATION_PORTRAIT, TEST_INSETS, - false /* reducedResolution */, 1f /* scale */); + scale < 1f /* reducedResolution */, scale); } } diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java index 5feda41f9599..52f66ae40cf3 100644 --- a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java @@ -18,6 +18,7 @@ package com.android.server.wm; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; +import android.content.res.Configuration; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.Before; @@ -28,6 +29,7 @@ import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; +import static android.app.ActivityManager.StackId.getWindowingModeForStackId; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -50,8 +52,12 @@ public class TaskStackContainersTests extends WindowTestsBase { @Before public void setUp() throws Exception { super.setUp(); + final Configuration overrideConfig = new Configuration(); + overrideConfig.windowConfiguration.setWindowingMode( + getWindowingModeForStackId(PINNED_STACK_ID)); mPinnedStack = new StackWindowController(PINNED_STACK_ID, null, - mDisplayContent.getDisplayId(), true /* onTop */, new Rect(), sWm).mContainer; + mDisplayContent.getDisplayId(), true /* onTop */, new Rect(), + overrideConfig, sWm).mContainer; // Stack should contain visible app window to be considered visible. final Task pinnedTask = createTaskInStack(mPinnedStack, 0 /* userId */); diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java index 95adc9cd5a1a..9f57f4993ed5 100644 --- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java +++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java @@ -29,6 +29,7 @@ import static org.mockito.Mockito.any; import static org.mockito.Mockito.doAnswer; import android.os.PowerSaveState; +import android.util.proto.ProtoOutputStream; import org.mockito.invocation.InvocationOnMock; import android.annotation.Nullable; @@ -596,6 +597,11 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { } @Override + public void writeToProto(ProtoOutputStream proto, long fieldId) { + + } + + @Override public void dump(String prefix, PrintWriter writer, String[] args) { } diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java new file mode 100644 index 000000000000..3f75b412d100 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + +import org.junit.Test; + +import android.app.WindowConfiguration; +import android.content.res.Configuration; +import android.graphics.Rect; +import android.platform.test.annotations.Presubmit; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; +import android.view.DisplayInfo; + +import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; +import static android.app.WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS; +import static android.app.WindowConfiguration.WINDOW_CONFIG_WINDOWING_MODE; +import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +/** + * Test class to for {@link android.app.WindowConfiguration}. + * + * Build/Install/Run: + * bit FrameworksServicesTests:com.android.server.wm.WindowConfigurationTests + */ +@SmallTest +@Presubmit +@org.junit.runner.RunWith(AndroidJUnit4.class) +public class WindowConfigurationTests extends WindowTestsBase { + private Rect mParentBounds; + + @Override + public void setUp() throws Exception { + super.setUp(); + mParentBounds = new Rect(10 /*left*/, 30 /*top*/, 80 /*right*/, 60 /*bottom*/); + } + + /** Tests {@link android.app.WindowConfiguration#diff(WindowConfiguration, boolean)}. */ + @Test + public void testDiff() { + final Configuration config1 = new Configuration(); + final WindowConfiguration winConfig1 = config1.windowConfiguration; + final Configuration config2 = new Configuration(); + final WindowConfiguration winConfig2 = config2.windowConfiguration; + final Configuration config3 = new Configuration(); + final WindowConfiguration winConfig3 = config3.windowConfiguration; + + winConfig1.setAppBounds(0, 1, 1, 0); + winConfig2.setAppBounds(1, 2, 2, 1); + winConfig3.setAppBounds(winConfig1.getAppBounds()); + + + assertEquals(CONFIG_WINDOW_CONFIGURATION, config1.diff(config2)); + assertEquals(0, config1.diffPublicOnly(config2)); + assertEquals(WINDOW_CONFIG_APP_BOUNDS, + winConfig1.diff(winConfig2, false /* compareUndefined */)); + + winConfig2.setWindowingMode(WINDOWING_MODE_FREEFORM); + assertEquals(WINDOW_CONFIG_APP_BOUNDS | WINDOW_CONFIG_WINDOWING_MODE, + winConfig1.diff(winConfig2, false /* compareUndefined */)); + + assertEquals(0, config1.diff(config3)); + assertEquals(0, config1.diffPublicOnly(config3)); + assertEquals(0, winConfig1.diff(winConfig3, false /* compareUndefined */)); + } + + /** Tests {@link android.app.WindowConfiguration#compareTo(WindowConfiguration)}. */ + @Test + public void testConfigurationCompareTo() throws Exception { + final Configuration blankConfig = new Configuration(); + final WindowConfiguration blankWinConfig = new WindowConfiguration(); + + final Configuration config1 = new Configuration(); + final WindowConfiguration winConfig1 = config1.windowConfiguration; + winConfig1.setAppBounds(1, 2, 3, 4); + + final Configuration config2 = new Configuration(config1); + final WindowConfiguration winConfig2 = config2.windowConfiguration; + + assertEquals(config1.compareTo(config2), 0); + assertEquals(winConfig1.compareTo(winConfig2), 0); + + // Different windowing mode + winConfig2.setWindowingMode(WINDOWING_MODE_FREEFORM); + assertNotEquals(config1.compareTo(config2), 0); + assertNotEquals(winConfig1.compareTo(winConfig2), 0); + winConfig2.setWindowingMode(winConfig1.getWindowingMode()); + + // Different bounds + winConfig2.setAppBounds(0, 2, 3, 4); + assertNotEquals(config1.compareTo(config2), 0); + assertNotEquals(winConfig1.compareTo(winConfig2), 0); + + // No bounds + assertEquals(config1.compareTo(blankConfig), -1); + assertEquals(winConfig1.compareTo(blankWinConfig), -1); + + assertEquals(blankConfig.compareTo(config1), 1); + assertEquals(blankWinConfig.compareTo(winConfig1), 1); + } + + @Test + public void testSetActivityType() throws Exception { + final WindowConfiguration config = new WindowConfiguration(); + config.setActivityType(ACTIVITY_TYPE_HOME); + assertEquals(ACTIVITY_TYPE_HOME, config.getActivityType()); + + boolean gotException = false; + try { + // Can't change activity type once set. + config.setActivityType(ACTIVITY_TYPE_STANDARD); + } catch (IllegalStateException e) { + gotException = true; + } + assertTrue("Can't change activity type once set.", gotException); + } + + /** Ensures the configuration app bounds at the root level match the app dimensions. */ + @Test + public void testAppBounds_RootConfigurationBounds() throws Exception { + final DisplayInfo info = mDisplayContent.getDisplayInfo(); + info.appWidth = 1024; + info.appHeight = 768; + + final Rect appBounds = sWm.computeNewConfiguration( + mDisplayContent.getDisplayId()).windowConfiguration.getAppBounds(); + // The bounds should always be positioned in the top left. + assertEquals(appBounds.left, 0); + assertEquals(appBounds.top, 0); + + // The bounds should equal the defined app width and height + assertEquals(appBounds.width(), info.appWidth); + assertEquals(appBounds.height(), info.appHeight); + } + + /** Ensures that bounds are clipped to their parent. */ + @Test + public void testAppBounds_BoundsClipping() throws Exception { + final Rect shiftedBounds = new Rect(mParentBounds); + shiftedBounds.offset(10, 10); + final Rect expectedBounds = new Rect(mParentBounds); + expectedBounds.intersect(shiftedBounds); + testStackBoundsConfiguration(null /*stackId*/, mParentBounds, shiftedBounds, + expectedBounds); + } + + /** Ensures that empty bounds are not propagated to the configuration. */ + @Test + public void testAppBounds_EmptyBounds() throws Exception { + final Rect emptyBounds = new Rect(); + testStackBoundsConfiguration(null /*stackId*/, mParentBounds, emptyBounds, + null /*ExpectedBounds*/); + } + + /** Ensures that bounds on freeform stacks are not clipped. */ + @Test + public void testAppBounds_FreeFormBounds() throws Exception { + final Rect freeFormBounds = new Rect(mParentBounds); + freeFormBounds.offset(10, 10); + testStackBoundsConfiguration(FREEFORM_WORKSPACE_STACK_ID, mParentBounds, freeFormBounds, + freeFormBounds); + } + + /** Ensures that fully contained bounds are not clipped. */ + @Test + public void testAppBounds_ContainedBounds() throws Exception { + final Rect insetBounds = new Rect(mParentBounds); + insetBounds.inset(5, 5, 5, 5); + testStackBoundsConfiguration(null /*stackId*/, mParentBounds, insetBounds, insetBounds); + } + + /** Ensures that full screen free form bounds are clipped */ + @Test + public void testAppBounds_FullScreenFreeFormBounds() throws Exception { + final Rect fullScreenBounds = new Rect(0, 0, mDisplayInfo.logicalWidth, + mDisplayInfo.logicalHeight); + testStackBoundsConfiguration(null /*stackId*/, mParentBounds, fullScreenBounds, + mParentBounds); + } + + private void testStackBoundsConfiguration(Integer stackId, Rect parentBounds, Rect bounds, + Rect expectedConfigBounds) { + final StackWindowController stackController = stackId != null ? + createStackControllerOnStackOnDisplay(stackId, mDisplayContent) + : createStackControllerOnDisplay(mDisplayContent); + + final Configuration parentConfig = mDisplayContent.getConfiguration(); + parentConfig.windowConfiguration.setAppBounds(parentBounds); + + final Configuration config = new Configuration(); + final WindowConfiguration winConfig = config.windowConfiguration; + stackController.adjustConfigurationForBounds(bounds, null /*insetBounds*/, + new Rect() /*nonDecorBounds*/, new Rect() /*stableBounds*/, false /*overrideWidth*/, + false /*overrideHeight*/, mDisplayInfo.logicalDensityDpi, config, parentConfig); + // Assert that both expected and actual are null or are equal to each other + + assertEquals(expectedConfigBounds, winConfig.getAppBounds()); + } + +} diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java index a7d594cbd256..16b6ca684c78 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java @@ -559,168 +559,6 @@ public class WindowContainerTests extends WindowTestsBase { assertEquals(1, child2223.compareTo(child21)); } - @Test - public void testConfigurationInit() throws Exception { - final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); - - // Check root container initial config. - final TestWindowContainer root = builder.setLayer(0).build(); - assertEquals(Configuration.EMPTY, root.getOverrideConfiguration()); - assertEquals(Configuration.EMPTY, root.getMergedOverrideConfiguration()); - assertEquals(Configuration.EMPTY, root.getConfiguration()); - - // Check child initial config. - final TestWindowContainer child1 = root.addChildWindow(); - assertEquals(Configuration.EMPTY, child1.getOverrideConfiguration()); - assertEquals(Configuration.EMPTY, child1.getMergedOverrideConfiguration()); - assertEquals(Configuration.EMPTY, child1.getConfiguration()); - - // Check child initial config if root has overrides. - final Configuration rootOverrideConfig = new Configuration(); - rootOverrideConfig.fontScale = 1.3f; - root.onOverrideConfigurationChanged(rootOverrideConfig); - final TestWindowContainer child2 = root.addChildWindow(); - assertEquals(Configuration.EMPTY, child2.getOverrideConfiguration()); - assertEquals(rootOverrideConfig, child2.getMergedOverrideConfiguration()); - assertEquals(rootOverrideConfig, child2.getConfiguration()); - - // Check child initial config if root has parent config set. - final Configuration rootParentConfig = new Configuration(); - rootParentConfig.fontScale = 0.8f; - rootParentConfig.orientation = SCREEN_ORIENTATION_LANDSCAPE; - root.onConfigurationChanged(rootParentConfig); - final Configuration rootFullConfig = new Configuration(rootParentConfig); - rootFullConfig.updateFrom(rootOverrideConfig); - - final TestWindowContainer child3 = root.addChildWindow(); - assertEquals(Configuration.EMPTY, child3.getOverrideConfiguration()); - assertEquals(rootOverrideConfig, child3.getMergedOverrideConfiguration()); - assertEquals(rootFullConfig, child3.getConfiguration()); - } - - @Test - public void testConfigurationChangeOnAddRemove() throws Exception { - final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); - - // Init root's config. - final TestWindowContainer root = builder.setLayer(0).build(); - final Configuration rootOverrideConfig = new Configuration(); - rootOverrideConfig.fontScale = 1.3f; - root.onOverrideConfigurationChanged(rootOverrideConfig); - - // Init child's config. - final TestWindowContainer child = root.addChildWindow(); - final Configuration childOverrideConfig = new Configuration(); - childOverrideConfig.densityDpi = 320; - child.onOverrideConfigurationChanged(childOverrideConfig); - final Configuration mergedOverrideConfig = new Configuration(root.getConfiguration()); - mergedOverrideConfig.updateFrom(childOverrideConfig); - - // Check configuration update when child is removed from parent - it should remain same. - root.removeChild(child); - assertEquals(childOverrideConfig, child.getOverrideConfiguration()); - assertEquals(mergedOverrideConfig, child.getMergedOverrideConfiguration()); - assertEquals(mergedOverrideConfig, child.getConfiguration()); - - // It may be paranoia... but let's check if parent's config didn't change after removal. - assertEquals(rootOverrideConfig, root.getOverrideConfiguration()); - assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration()); - assertEquals(rootOverrideConfig, root.getConfiguration()); - - // Init different root - final TestWindowContainer root2 = builder.setLayer(0).build(); - final Configuration rootOverrideConfig2 = new Configuration(); - rootOverrideConfig2.fontScale = 1.1f; - root2.onOverrideConfigurationChanged(rootOverrideConfig2); - - // Check configuration update when child is added to different parent. - mergedOverrideConfig.setTo(rootOverrideConfig2); - mergedOverrideConfig.updateFrom(childOverrideConfig); - root2.addChildWindow(child); - assertEquals(childOverrideConfig, child.getOverrideConfiguration()); - assertEquals(mergedOverrideConfig, child.getMergedOverrideConfiguration()); - assertEquals(mergedOverrideConfig, child.getConfiguration()); - } - - @Test - public void testConfigurationChangePropagation() throws Exception { - final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(); - - // Builds 3-level vertical hierarchy with one window container on each level. - // In addition to different overrides on each level, everyone in hierarchy will have one - // common overridden value - orientation; - - // Init root's config. - final TestWindowContainer root = builder.setLayer(0).build(); - final Configuration rootOverrideConfig = new Configuration(); - rootOverrideConfig.fontScale = 1.3f; - rootOverrideConfig.orientation = SCREEN_ORIENTATION_REVERSE_LANDSCAPE; - root.onOverrideConfigurationChanged(rootOverrideConfig); - - // Init children. - final TestWindowContainer child1 = root.addChildWindow(); - final Configuration childOverrideConfig1 = new Configuration(); - childOverrideConfig1.densityDpi = 320; - childOverrideConfig1.orientation = SCREEN_ORIENTATION_LANDSCAPE; - child1.onOverrideConfigurationChanged(childOverrideConfig1); - - final TestWindowContainer child2 = child1.addChildWindow(); - final Configuration childOverrideConfig2 = new Configuration(); - childOverrideConfig2.screenWidthDp = 150; - childOverrideConfig2.orientation = SCREEN_ORIENTATION_PORTRAIT; - child2.onOverrideConfigurationChanged(childOverrideConfig2); - - // Check configuration on all levels when root override is updated. - rootOverrideConfig.smallestScreenWidthDp = 200; - root.onOverrideConfigurationChanged(rootOverrideConfig); - - final Configuration mergedOverrideConfig1 = new Configuration(rootOverrideConfig); - mergedOverrideConfig1.updateFrom(childOverrideConfig1); - final Configuration mergedConfig1 = new Configuration(mergedOverrideConfig1); - - final Configuration mergedOverrideConfig2 = new Configuration(mergedOverrideConfig1); - mergedOverrideConfig2.updateFrom(childOverrideConfig2); - final Configuration mergedConfig2 = new Configuration(mergedOverrideConfig2); - - assertEquals(rootOverrideConfig, root.getOverrideConfiguration()); - assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration()); - assertEquals(rootOverrideConfig, root.getConfiguration()); - - assertEquals(childOverrideConfig1, child1.getOverrideConfiguration()); - assertEquals(mergedOverrideConfig1, child1.getMergedOverrideConfiguration()); - assertEquals(mergedConfig1, child1.getConfiguration()); - - assertEquals(childOverrideConfig2, child2.getOverrideConfiguration()); - assertEquals(mergedOverrideConfig2, child2.getMergedOverrideConfiguration()); - assertEquals(mergedConfig2, child2.getConfiguration()); - - // Check configuration on all levels when root parent config is updated. - final Configuration rootParentConfig = new Configuration(); - rootParentConfig.screenHeightDp = 100; - rootParentConfig.orientation = SCREEN_ORIENTATION_REVERSE_PORTRAIT; - root.onConfigurationChanged(rootParentConfig); - final Configuration mergedRootConfig = new Configuration(rootParentConfig); - mergedRootConfig.updateFrom(rootOverrideConfig); - - mergedConfig1.setTo(mergedRootConfig); - mergedConfig1.updateFrom(mergedOverrideConfig1); - - mergedConfig2.setTo(mergedConfig1); - mergedConfig2.updateFrom(mergedOverrideConfig2); - - assertEquals(rootOverrideConfig, root.getOverrideConfiguration()); - assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration()); - assertEquals(mergedRootConfig, root.getConfiguration()); - - assertEquals(childOverrideConfig1, child1.getOverrideConfiguration()); - assertEquals(mergedOverrideConfig1, child1.getMergedOverrideConfiguration()); - assertEquals(mergedConfig1, child1.getConfiguration()); - - assertEquals(childOverrideConfig2, child2.getOverrideConfiguration()); - assertEquals(mergedOverrideConfig2, child2.getMergedOverrideConfiguration()); - assertEquals(mergedConfig2, child2.getConfiguration()); - } - /* Used so we can gain access to some protected members of the {@link WindowContainer} class */ private class TestWindowContainer extends WindowContainer<TestWindowContainer> { private final int mLayer; @@ -779,10 +617,6 @@ public class WindowContainerTests extends WindowTestsBase { return addChildWindow(new TestWindowContainerBuilder().setLayer(1)); } - TestWindowContainer getChildAt(int index) { - return mChildren.get(index); - } - @Override void onParentSet() { mOnParentSetCalled = true; diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java index 6e253e743ddb..df3f7553e83c 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java @@ -75,7 +75,7 @@ public class WindowFrameTests extends WindowTestsBase { final Rect mInsetBounds = new Rect(); boolean mFullscreenForTest = true; TaskWithBounds(Rect bounds) { - super(0, mStubStack, 0, sWm, null, null, 0, false, false, new TaskDescription(), null); + super(0, mStubStack, 0, sWm, null, null, 0, false, new TaskDescription(), null); mBounds = bounds; } @Override diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java index 7ff1110e00f7..ebe00ce8d51d 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java @@ -67,7 +67,7 @@ public class WindowTestUtils { public static Task createTaskInStack(WindowManagerService service, TaskStack stack, int userId) { final Task newTask = new Task(sNextTaskId++, stack, userId, service, null, EMPTY, 0, false, - false, new ActivityManager.TaskDescription(), null); + new ActivityManager.TaskDescription(), null); stack.addTask(newTask, POSITION_TOP); return newTask; } @@ -92,7 +92,9 @@ public class WindowTestUtils { boolean mOnTop = false; TestAppWindowToken(DisplayContent dc) { - super(dc.mService, new IApplicationToken.Stub() {}, false, dc, true /* fillsParent */, + super(dc.mService, new IApplicationToken.Stub() { + public String getName() {return null;} + }, false, dc, true /* fillsParent */, null /* overrideConfig */, null /* bounds */); } @@ -173,10 +175,9 @@ public class WindowTestUtils { TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds, Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture, - boolean homeTask, TaskWindowContainerController controller) { + TaskWindowContainerController controller) { super(taskId, stack, userId, service, bounds, overrideConfig, resizeMode, - supportsPictureInPicture, homeTask, new ActivityManager.TaskDescription(), - controller); + supportsPictureInPicture, new ActivityManager.TaskDescription(), controller); } boolean shouldDeferRemoval() { @@ -227,7 +228,7 @@ public class WindowTestUtils { } }, stackController, 0 /* userId */, null /* bounds */, EMPTY /* overrideConfig*/, RESIZE_MODE_UNRESIZEABLE, - false /* supportsPictureInPicture */, false /* homeTask*/, true /* toTop*/, + false /* supportsPictureInPicture */, true /* toTop*/, true /* showForAllUsers */, new ActivityManager.TaskDescription(), stackController.mService); } @@ -235,9 +236,9 @@ public class WindowTestUtils { @Override TestTask createTask(int taskId, TaskStack stack, int userId, Rect bounds, Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture, - boolean homeTask, ActivityManager.TaskDescription taskDescription) { + ActivityManager.TaskDescription taskDescription) { return new TestTask(taskId, stack, userId, mService, bounds, overrideConfig, resizeMode, - supportsPictureInPicture, homeTask, this); + supportsPictureInPicture, this); } } @@ -287,6 +288,10 @@ public class WindowTestUtils { public IBinder asBinder() { return mBinder; } + @Override + public String getName() { + return null; + } } /** Used to track resize reports. */ diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java index 6618a699bee9..bce740bce669 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java @@ -16,9 +16,11 @@ package com.android.server.wm; +import static android.app.ActivityManager.StackId.getWindowingModeForStackId; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.View.VISIBLE; +import android.content.res.Configuration; import android.graphics.Rect; import android.hardware.display.DisplayManagerGlobal; import android.view.Display; @@ -237,8 +239,10 @@ class WindowTestsBase { StackWindowController createStackControllerOnStackOnDisplay(int stackId, DisplayContent dc) { + final Configuration overrideConfig = new Configuration(); + overrideConfig.windowConfiguration.setWindowingMode(getWindowingModeForStackId(stackId)); return new StackWindowController(stackId, null, dc.getDisplayId(), - true /* onTop */, new Rect(), sWm); + true /* onTop */, new Rect(), overrideConfig, sWm); } /** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */ diff --git a/services/tests/servicestests/test-apps/ConnTestApp/Android.mk b/services/tests/servicestests/test-apps/ConnTestApp/Android.mk index 030a709b0215..fbfa28a9e93b 100644 --- a/services/tests/servicestests/test-apps/ConnTestApp/Android.mk +++ b/services/tests/servicestests/test-apps/ConnTestApp/Android.mk @@ -18,6 +18,8 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := tests +LOCAL_COMPATIBILITY_SUITE := device-tests + LOCAL_STATIC_JAVA_LIBRARIES := servicestests-aidl LOCAL_SRC_FILES := $(call all-subdir-java-files) diff --git a/services/tests/servicestests/test-apps/ConnTestApp/AndroidManifest.xml b/services/tests/servicestests/test-apps/ConnTestApp/AndroidManifest.xml index 66714109a761..909e9bb7bcd9 100644 --- a/services/tests/servicestests/test-apps/ConnTestApp/AndroidManifest.xml +++ b/services/tests/servicestests/test-apps/ConnTestApp/AndroidManifest.xml @@ -24,6 +24,8 @@ <application> <activity android:name=".ConnTestActivity" android:exported="true" /> + <service android:name=".CmdReceiverService" + android:exported="true" /> </application> </manifest>
\ No newline at end of file diff --git a/services/tests/servicestests/test-apps/ConnTestApp/src/com/android/servicestests/apps/conntestapp/CmdReceiverService.java b/services/tests/servicestests/test-apps/ConnTestApp/src/com/android/servicestests/apps/conntestapp/CmdReceiverService.java new file mode 100644 index 000000000000..6130f3a3fc76 --- /dev/null +++ b/services/tests/servicestests/test-apps/ConnTestApp/src/com/android/servicestests/apps/conntestapp/CmdReceiverService.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.servicestests.apps.conntestapp; + +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; + +import com.android.servicestests.aidl.ICmdReceiverService; + +public class CmdReceiverService extends Service { + private ICmdReceiverService.Stub mBinder = new ICmdReceiverService.Stub() { + @Override + public void finishActivity() { + ConnTestActivity.finishSelf(); + } + }; + + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } +}
\ No newline at end of file diff --git a/services/tests/servicestests/test-apps/ConnTestApp/src/com/android/servicestests/apps/conntestapp/ConnTestActivity.java b/services/tests/servicestests/test-apps/ConnTestApp/src/com/android/servicestests/apps/conntestapp/ConnTestActivity.java index c5c7add29f93..b26cc7fd0130 100644 --- a/services/tests/servicestests/test-apps/ConnTestApp/src/com/android/servicestests/apps/conntestapp/ConnTestActivity.java +++ b/services/tests/servicestests/test-apps/ConnTestApp/src/com/android/servicestests/apps/conntestapp/ConnTestActivity.java @@ -30,6 +30,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; +import com.android.internal.annotations.GuardedBy; import com.android.servicestests.aidl.INetworkStateObserver; public class ConnTestActivity extends Activity { @@ -39,17 +40,26 @@ public class ConnTestActivity extends Activity { private static final String ACTION_FINISH_ACTIVITY = TEST_PKG + ".FINISH"; private static final String EXTRA_NETWORK_STATE_OBSERVER = TEST_PKG + ".observer"; + private static final Object INSTANCE_LOCK = new Object(); + @GuardedBy("instanceLock") + private static Activity sInstance; + private BroadcastReceiver finishCommandReceiver = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + synchronized (INSTANCE_LOCK) { + sInstance = this; + } + Log.i(TAG, "onCreate called"); notifyNetworkStateObserver(); finishCommandReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { + Log.i(TAG, "finish command received"); ConnTestActivity.this.finish(); } }; @@ -57,13 +67,37 @@ public class ConnTestActivity extends Activity { } @Override + public void onResume() { + super.onResume(); + Log.i(TAG, "onResume called"); + } + + @Override public void onStop() { + Log.i(TAG, "onStop called"); if (finishCommandReceiver != null) { unregisterReceiver(finishCommandReceiver); } super.onStop(); } + @Override + public void finish() { + synchronized (INSTANCE_LOCK) { + sInstance = null; + } + Log.i(TAG, "finish called"); + super.finish(); + } + + public static void finishSelf() { + synchronized (INSTANCE_LOCK) { + if (sInstance != null) { + sInstance.finish(); + } + } + } + private void notifyNetworkStateObserver() { if (getIntent() == null) { return; diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index 774bf438995c..e65d36087ca9 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -434,6 +434,8 @@ public class UsbDeviceManager { try { // Restore default functions. + mCurrentOemFunctions = SystemProperties.get(UsbDeviceManager.getPersistProp(false), + UsbManager.USB_FUNCTION_NONE); if (isNormalBoot()) { mCurrentFunctions = SystemProperties.get(USB_CONFIG_PROPERTY, UsbManager.USB_FUNCTION_NONE); @@ -662,8 +664,7 @@ public class UsbDeviceManager { } if ((!functions.equals(oemFunctions) && - (mCurrentOemFunctions == null || - !mCurrentOemFunctions.equals(oemFunctions))) + !mCurrentOemFunctions.equals(oemFunctions)) || !mCurrentFunctions.equals(functions) || !mCurrentFunctionsApplied || forceRestart) { @@ -1017,7 +1018,7 @@ public class UsbDeviceManager { Slog.v(TAG, "Current user switched to " + msg.arg1 + "; resetting USB host stack for MTP or PTP"); // avoid leaking sensitive data from previous user - setEnabledFunctions(mCurrentFunctions, true, false); + setEnabledFunctions(null, true, false); } mCurrentUser = msg.arg1; } diff --git a/services/usb/java/com/android/server/usb/descriptors/ByteStream.java b/services/usb/java/com/android/server/usb/descriptors/ByteStream.java index d678931fd01a..1e823b63d5b2 100644 --- a/services/usb/java/com/android/server/usb/descriptors/ByteStream.java +++ b/services/usb/java/com/android/server/usb/descriptors/ByteStream.java @@ -15,7 +15,11 @@ */ package com.android.server.usb.descriptors; +// Framework builds and Android Studio builds use different imports for NonNull. +// This one for Framework builds import android.annotation.NonNull; +// this one in the AndroidStudio project +// import android.support.annotation.NonNull; /** * @hide @@ -23,7 +27,7 @@ import android.annotation.NonNull; * but with the capability to "back up" in situations where the parser discovers that a * UsbDescriptor has overrun its length. */ -public class ByteStream { +public final class ByteStream { private static final String TAG = "ByteStream"; /** The byte array being wrapped */ @@ -104,6 +108,20 @@ public class ByteStream { } /** + * @return the next byte from the stream and advances the stream and the read count. Note + * that this is an unsigned byte encoded in a Java int. + * @throws IndexOutOfBoundsException + */ + public int getUnsignedByte() { + if (available() > 0) { + mReadCount++; + return mBytes[mIndex++] & 0x000000FF; + } else { + throw new IndexOutOfBoundsException(); + } + } + + /** * Reads 2 bytes in *little endian format* from the stream and composes a 16-bit integer. * As we are storing the 2-byte value in a 4-byte integer, the upper 2 bytes are always * 0, essentially making the returned value *unsigned*. @@ -111,11 +129,11 @@ public class ByteStream { * next 2 bytes in the stream. * @throws IndexOutOfBoundsException */ - public int unpackUsbWord() { + public int unpackUsbShort() { if (available() >= 2) { - int b0 = getByte(); - int b1 = getByte(); - return ((b1 << 8) & 0x0000FF00) | (b0 & 0x000000FF); + int b0 = getUnsignedByte(); + int b1 = getUnsignedByte(); + return (b1 << 8) | b0; } else { throw new IndexOutOfBoundsException(); } @@ -131,16 +149,32 @@ public class ByteStream { */ public int unpackUsbTriple() { if (available() >= 3) { - int b0 = getByte(); - int b1 = getByte(); - int b2 = getByte(); - return ((b2 << 16) & 0x00FF0000) | ((b1 << 8) & 0x0000FF00) | (b0 & 0x000000FF); + int b0 = getUnsignedByte(); + int b1 = getUnsignedByte(); + int b2 = getUnsignedByte(); + return (b2 << 16) | (b1 << 8) | b0; } else { throw new IndexOutOfBoundsException(); } } /** + * Reads 4 bytes in *little endian format* from the stream and composes a 32-bit integer. + * @return The 32-bit integer encoded by the next 4 bytes in the stream. + * @throws IndexOutOfBoundsException + */ + public int unpackUsbInt() { + if (available() >= 4) { + int b0 = getUnsignedByte(); + int b1 = getUnsignedByte(); + int b2 = getUnsignedByte(); + int b3 = getUnsignedByte(); + return (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; + } else { + throw new IndexOutOfBoundsException(); + } + } + /** * Advances the logical position in the stream. Affects the running count also. * @param numBytes The number of bytes to advance. * @throws IndexOutOfBoundsException diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbACHeader.java b/services/usb/java/com/android/server/usb/descriptors/Usb10ACHeader.java index e31438c58e06..a35b46318e23 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbACHeader.java +++ b/services/usb/java/com/android/server/usb/descriptors/Usb10ACHeader.java @@ -15,18 +15,16 @@ */ package com.android.server.usb.descriptors; +import com.android.server.usb.descriptors.report.ReportCanvas; + /** * @hide * An audio class-specific Interface Header. * see audio10.pdf section 4.3.2 */ -public class UsbACHeader extends UsbACInterface { - private static final String TAG = "ACHeader"; +public final class Usb10ACHeader extends UsbACHeaderInterface { + private static final String TAG = "Usb10ACHeader"; - private int mADCRelease; // 3:2 Audio Device Class Specification Release (BCD). - private int mTotalLength; // 5:2 Total number of bytes returned for the class-specific - // AudioControl interface descriptor. Includes the combined length - // of this descriptor header and all Unit and Terminal descriptors. private byte mNumInterfaces = 0; // 7:1 The number of AudioStreaming and MIDIStreaming // interfaces in the Audio Interface Collection to which this // AudioControl interface belongs: n @@ -34,16 +32,8 @@ public class UsbACHeader extends UsbACInterface { // numbers associate with this endpoint private byte mControls; // Vers 2.0 thing - public UsbACHeader(int length, byte type, byte subtype, byte subclass) { - super(length, type, subtype, subclass); - } - - public int getADCRelease() { - return mADCRelease; - } - - public int getTotalLength() { - return mTotalLength; + public Usb10ACHeader(int length, byte type, byte subtype, byte subclass, int spec) { + super(length, type, subtype, subclass, spec); } public byte getNumInterfaces() { @@ -60,9 +50,8 @@ public class UsbACHeader extends UsbACInterface { @Override public int parseRawDescriptors(ByteStream stream) { - mADCRelease = stream.unpackUsbWord(); - mTotalLength = stream.unpackUsbWord(); + mTotalLength = stream.unpackUsbShort(); if (mADCRelease >= 0x200) { mControls = stream.getByte(); } else { @@ -75,4 +64,30 @@ public class UsbACHeader extends UsbACInterface { return mLength; } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.openList(); + int numInterfaces = getNumInterfaces(); + StringBuilder sb = new StringBuilder(); + sb.append("" + numInterfaces + " Interfaces"); + if (numInterfaces > 0) { + sb.append(" ["); + byte[] interfaceNums = getInterfaceNums(); + if (interfaceNums != null) { + for (int index = 0; index < numInterfaces; index++) { + sb.append("" + interfaceNums[index]); + if (index < numInterfaces - 1) { + sb.append(" "); + } + } + } + sb.append("]"); + } + canvas.writeListItem(sb.toString()); + canvas.writeListItem("Controls: " + ReportCanvas.getHexString(getControls())); + canvas.closeList(); + } } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbACInputTerminal.java b/services/usb/java/com/android/server/usb/descriptors/Usb10ACInputTerminal.java index 653a7de5457e..2363c4dd8009 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbACInputTerminal.java +++ b/services/usb/java/com/android/server/usb/descriptors/Usb10ACInputTerminal.java @@ -15,13 +15,15 @@ */ package com.android.server.usb.descriptors; +import com.android.server.usb.descriptors.report.ReportCanvas; + /** * @hide * An audio class-specific Input Terminal interface. * see audio10.pdf section 4.3.2.1 */ -public class UsbACInputTerminal extends UsbACTerminal { - private static final String TAG = "ACInputTerminal"; +public final class Usb10ACInputTerminal extends UsbACTerminal { + private static final String TAG = "Usb10ACInputTerminal"; private byte mNrChannels; // 7:1 1 Channel (0x01) // Number of logical output channels in the @@ -30,7 +32,7 @@ public class UsbACInputTerminal extends UsbACTerminal { private byte mChannelNames; // 10:1 Unused (0x00) private byte mTerminal; // 11:1 Unused (0x00) - public UsbACInputTerminal(int length, byte type, byte subtype, byte subclass) { + public Usb10ACInputTerminal(int length, byte type, byte subtype, byte subclass) { super(length, type, subtype, subclass); } @@ -55,10 +57,22 @@ public class UsbACInputTerminal extends UsbACTerminal { super.parseRawDescriptors(stream); mNrChannels = stream.getByte(); - mChannelConfig = stream.unpackUsbWord(); + mChannelConfig = stream.unpackUsbShort(); mChannelNames = stream.getByte(); mTerminal = stream.getByte(); return mLength; } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.openList(); + canvas.writeListItem("Associated Terminal: " + + ReportCanvas.getHexString(getAssocTerminal())); + canvas.writeListItem("" + getNrChannels() + " Chans. Config: " + + ReportCanvas.getHexString(getChannelConfig())); + canvas.closeList(); + } } diff --git a/services/usb/java/com/android/server/usb/descriptors/Usb10ACMixerUnit.java b/services/usb/java/com/android/server/usb/descriptors/Usb10ACMixerUnit.java new file mode 100644 index 000000000000..d3486643ede2 --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/Usb10ACMixerUnit.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors; + +import com.android.server.usb.descriptors.report.ReportCanvas; + +/** + * @hide + * An audio class-specific Mixer Interface. + * see audio10.pdf section 4.3.2.3 + */ +public final class Usb10ACMixerUnit extends UsbACMixerUnit { + private static final String TAG = "Usb10ACMixerUnit"; + + private int mChannelConfig; // Spatial location of output channels + private byte mChanNameID; // First channel name string descriptor ID + private byte[] mControls; // bitmasks of which controls are present for each channel + private byte mNameID; // string descriptor ID of mixer name + + public Usb10ACMixerUnit(int length, byte type, byte subtype, byte subClass) { + super(length, type, subtype, subClass); + } + + public int getChannelConfig() { + return mChannelConfig; + } + + public byte getChanNameID() { + return mChanNameID; + } + + public byte[] getControls() { + return mControls; + } + + public byte getNameID() { + return mNameID; + } + + @Override + public int parseRawDescriptors(ByteStream stream) { + super.parseRawDescriptors(stream); + + mChannelConfig = stream.unpackUsbShort(); + mChanNameID = stream.getByte(); + + int controlArraySize = calcControlArraySize(mNumInputs, mNumOutputs); + mControls = new byte[controlArraySize]; + for (int index = 0; index < controlArraySize; index++) { + mControls[index] = stream.getByte(); + } + + mNameID = stream.getByte(); + + return mLength; + } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.writeParagraph("Mixer Unit", false); + canvas.openList(); + + canvas.writeListItem("Unit ID: " + ReportCanvas.getHexString(getUnitID())); + byte numInputs = getNumInputs(); + byte[] inputIDs = getInputIDs(); + canvas.openListItem(); + canvas.write("Num Inputs: " + numInputs + " ["); + for (int input = 0; input < numInputs; input++) { + canvas.write("" + ReportCanvas.getHexString(inputIDs[input])); + if (input < numInputs - 1) { + canvas.write(" "); + } + } + canvas.write("]"); + canvas.closeListItem(); + + canvas.writeListItem("Num Outputs: " + getNumOutputs()); + canvas.writeListItem("Channel Config: " + ReportCanvas.getHexString(getChannelConfig())); + + byte[] controls = getControls(); + canvas.openListItem(); + canvas.write("Controls: " + controls.length + " ["); + for (int ctrl = 0; ctrl < controls.length; ctrl++) { + canvas.write("" + controls[ctrl]); + if (ctrl < controls.length - 1) { + canvas.write(" "); + } + } + canvas.write("]"); + canvas.closeListItem(); + canvas.closeList(); + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbACOutputTerminal.java b/services/usb/java/com/android/server/usb/descriptors/Usb10ACOutputTerminal.java index f957e3dbe217..9f2f09ec146c 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbACOutputTerminal.java +++ b/services/usb/java/com/android/server/usb/descriptors/Usb10ACOutputTerminal.java @@ -15,18 +15,20 @@ */ package com.android.server.usb.descriptors; +import com.android.server.usb.descriptors.report.ReportCanvas; + /** * @hide * An audio class-specific Output Terminal Interface. * see audio10.pdf section 4.3.2.2 */ -public class UsbACOutputTerminal extends UsbACTerminal { - private static final String TAG = "ACOutputTerminal"; +public final class Usb10ACOutputTerminal extends UsbACTerminal { + private static final String TAG = "Usb10ACOutputTerminal"; private byte mSourceID; // 7:1 From Input Terminal. (0x01) private byte mTerminal; // 8:1 Unused. - public UsbACOutputTerminal(int length, byte type, byte subtype, byte subClass) { + public Usb10ACOutputTerminal(int length, byte type, byte subtype, byte subClass) { super(length, type, subtype, subClass); } @@ -46,4 +48,13 @@ public class UsbACOutputTerminal extends UsbACTerminal { mTerminal = stream.getByte(); return mLength; } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.openList(); + canvas.writeListItem("Source ID: " + ReportCanvas.getHexString(getSourceID())); + canvas.closeList(); + } } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbASFormatI.java b/services/usb/java/com/android/server/usb/descriptors/Usb10ASFormatI.java index 347a6cffb525..1523bb528a03 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbASFormatI.java +++ b/services/usb/java/com/android/server/usb/descriptors/Usb10ASFormatI.java @@ -15,13 +15,15 @@ */ package com.android.server.usb.descriptors; +import com.android.server.usb.descriptors.report.ReportCanvas; + /** * @hide * An audio class-specific Format I interface. * see Frmts10.pdf section 2.2 */ -public class UsbASFormatI extends UsbASFormat { - private static final String TAG = "ASFormatI"; +public final class Usb10ASFormatI extends UsbASFormat { + private static final String TAG = "Usb10ASFormatI"; private byte mNumChannels; // 4:1 private byte mSubframeSize; // 5:1 frame size in bytes @@ -31,7 +33,7 @@ public class UsbASFormatI extends UsbASFormat { // min & max rates otherwise mSamFreqType rates. // All 3-byte values. All rates in Hz - public UsbASFormatI(int length, byte type, byte subtype, byte formatType, byte subclass) { + public Usb10ASFormatI(int length, byte type, byte subtype, byte formatType, byte subclass) { super(length, type, subtype, formatType, subclass); } @@ -51,11 +53,24 @@ public class UsbASFormatI extends UsbASFormat { return mSampleFreqType; } + @Override public int[] getSampleRates() { return mSampleRates; } @Override + public int[] getBitDepths() { + int[] depths = {mBitResolution}; + return depths; + } + + @Override + public int[] getChannelCounts() { + int[] counts = {mNumChannels}; + return counts; + } + + @Override public int parseRawDescriptors(ByteStream stream) { mNumChannels = stream.getByte(); mSubframeSize = stream.getByte(); @@ -74,4 +89,28 @@ public class UsbASFormatI extends UsbASFormat { return mLength; } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.openList(); + canvas.writeListItem("" + getNumChannels() + " Channels."); + canvas.writeListItem("Subframe Size: " + getSubframeSize()); + canvas.writeListItem("Bit Resolution: " + getBitResolution()); + byte sampleFreqType = getSampleFreqType(); + int[] sampleRates = getSampleRates(); + canvas.writeListItem("Sample Freq Type: " + sampleFreqType); + canvas.openList(); + if (sampleFreqType == 0) { + canvas.writeListItem("min: " + sampleRates[0]); + canvas.writeListItem("max: " + sampleRates[1]); + } else { + for (int index = 0; index < sampleFreqType; index++) { + canvas.writeListItem("" + sampleRates[index]); + } + } + canvas.closeList(); + canvas.closeList(); + } } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbASFormatII.java b/services/usb/java/com/android/server/usb/descriptors/Usb10ASFormatII.java index abdc62145aa2..b1e7680ee1b9 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbASFormatII.java +++ b/services/usb/java/com/android/server/usb/descriptors/Usb10ASFormatII.java @@ -15,13 +15,15 @@ */ package com.android.server.usb.descriptors; +import com.android.server.usb.descriptors.report.ReportCanvas; + /** * @hide * An audio class-specific Format II interface. * see Frmts10.pdf section 2.3 */ -public class UsbASFormatII extends UsbASFormat { - private static final String TAG = "ASFormatII"; +public final class Usb10ASFormatII extends UsbASFormat { + private static final String TAG = "Usb10ASFormatII"; private int mMaxBitRate; // 4:2 Indicates the maximum number of bits per second this // interface can handle. Expressed in kbits/s. @@ -36,7 +38,7 @@ public class UsbASFormatII extends UsbASFormat { // the min & max rates. otherwise mSamFreqType rates. // All 3-byte values. All rates in Hz - public UsbASFormatII(int length, byte type, byte subtype, byte formatType, byte subclass) { + public Usb10ASFormatII(int length, byte type, byte subtype, byte formatType, byte subclass) { super(length, type, subtype, formatType, subclass); } @@ -58,8 +60,8 @@ public class UsbASFormatII extends UsbASFormat { @Override public int parseRawDescriptors(ByteStream stream) { - mMaxBitRate = stream.unpackUsbWord(); - mSamplesPerFrame = stream.unpackUsbWord(); + mMaxBitRate = stream.unpackUsbShort(); + mSamplesPerFrame = stream.unpackUsbShort(); mSamFreqType = stream.getByte(); int numFreqs = mSamFreqType == 0 ? 2 : mSamFreqType; mSampleRates = new int[numFreqs]; @@ -69,4 +71,29 @@ public class UsbASFormatII extends UsbASFormat { return mLength; } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.openList(); + canvas.writeListItem("Max Bit Rate: " + getMaxBitRate()); + canvas.writeListItem("Samples Per Frame: " + getMaxBitRate()); + byte sampleFreqType = getSamFreqType(); + int[] sampleRates = getSampleRates(); + canvas.writeListItem("Sample Freq Type: " + sampleFreqType); + canvas.openList(); + if (sampleFreqType == 0) { + canvas.writeListItem("min: " + sampleRates[0]); + canvas.writeListItem("max: " + sampleRates[1]); + } else { + for (int index = 0; index < sampleFreqType; index++) { + canvas.writeListItem("" + sampleRates[index]); + } + } + canvas.closeList(); + + canvas.closeList(); + } + } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbASGeneral.java b/services/usb/java/com/android/server/usb/descriptors/Usb10ASGeneral.java index c4f42d318213..2d4f604ed1a1 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbASGeneral.java +++ b/services/usb/java/com/android/server/usb/descriptors/Usb10ASGeneral.java @@ -15,13 +15,16 @@ */ package com.android.server.usb.descriptors; +import com.android.server.usb.descriptors.report.ReportCanvas; +import com.android.server.usb.descriptors.report.UsbStrings; + /** * @hide * An audio class-specific General interface. * see audio10.pdf section 4.5.2 */ -public class UsbASGeneral extends UsbACInterface { - private static final String TAG = "ACGeneral"; +public final class Usb10ASGeneral extends UsbACInterface { + private static final String TAG = "Usb10ASGeneral"; // audio10.pdf - section 4.5.2 private byte mTerminalLink; // 3:1 The Terminal ID of the Terminal to which the endpoint @@ -31,7 +34,7 @@ public class UsbASGeneral extends UsbACInterface { private int mFormatTag; // 5:2 The Audio Data Format that has to be used to communicate // with this interface. - public UsbASGeneral(int length, byte type, byte subtype, byte subclass) { + public Usb10ASGeneral(int length, byte type, byte subtype, byte subclass) { super(length, type, subtype, subclass); } @@ -51,8 +54,20 @@ public class UsbASGeneral extends UsbACInterface { public int parseRawDescriptors(ByteStream stream) { mTerminalLink = stream.getByte(); mDelay = stream.getByte(); - mFormatTag = stream.unpackUsbWord(); + mFormatTag = stream.unpackUsbShort(); return mLength; } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.openList(); + canvas.writeListItem("Delay: " + mDelay); + canvas.writeListItem("Terminal Link: " + mTerminalLink); + canvas.writeListItem("Format: " + UsbStrings.getAudioFormatName(mFormatTag) + " - " + + ReportCanvas.getHexString(mFormatTag)); + canvas.closeList(); + } } diff --git a/services/usb/java/com/android/server/usb/descriptors/Usb20ACHeader.java b/services/usb/java/com/android/server/usb/descriptors/Usb20ACHeader.java new file mode 100644 index 000000000000..eefae3d51b3f --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/Usb20ACHeader.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors; + +import com.android.server.usb.descriptors.report.ReportCanvas; + +/** + * @hide + * An audio class-specific Header descriptor. + * see Audio20.pdf section 4.7.2 Class-Specific AC Interface Descriptor + */ +public final class Usb20ACHeader extends UsbACHeaderInterface { + private static final String TAG = "Usb20ACHeader"; + + private byte mCategory; // 5:1 Constant, indicating the primary use of this audio function. + // See audio20.pdf Appendix A.7, “Audio Function Category Codes.” + private byte mControls; // 8:1 See audio20.pdf Table 4-5. + + public Usb20ACHeader(int length, byte type, byte subtype, byte subclass, int spec) { + super(length, type, subtype, subclass, spec); + } + + public byte getCategory() { + return mCategory; + } + + public byte getControls() { + return mControls; + } + + @Override + public int parseRawDescriptors(ByteStream stream) { + mCategory = stream.getByte(); + mTotalLength = stream.unpackUsbShort(); + mControls = stream.getByte(); + + return mLength; + } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.openList(); + canvas.writeListItem("Category: " + ReportCanvas.getHexString(getCategory())); + canvas.writeListItem("Controls: " + ReportCanvas.getHexString(getControls())); + canvas.closeList(); + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/Usb20ACInputTerminal.java b/services/usb/java/com/android/server/usb/descriptors/Usb20ACInputTerminal.java new file mode 100644 index 000000000000..3e2ac39c0aca --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/Usb20ACInputTerminal.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors; + +import com.android.server.usb.descriptors.report.ReportCanvas; + +/** + * @hide + * An audio class-specific Input Terminal interface. + * see Audio20.pdf section 3.13.2 Input Terminal + */ +public final class Usb20ACInputTerminal extends UsbACTerminal { + private static final String TAG = "Usb20ACInputTerminal"; + + // See Audio20.pdf - Table 4-9 + // Always 17 bytes + private byte mClkSourceID; // 7:1 - ID of the Clock Entity to which this Input + // Terminal is connected. + private byte mNumChannels; // 8:1 - Number of logical output channels in the + // Terminal’s output audio channel cluster. + private int mChanConfig; // 9:4 - Describes the spatial location of the + // logical channels. + private byte mChanNames; // 13:1 - Index of a string descriptor, describing the + // name of the first logical channel. + private int mControls; // 14:2 - Bitmask (see Audio20.pdf Table 4-9) + private byte mTerminalName; // 16:1 - Index of a string descriptor, describing the + // Input Terminal. + + public Usb20ACInputTerminal(int length, byte type, byte subtype, byte subclass) { + super(length, type, subtype, subclass); + } + + public byte getClkSourceID() { + return mClkSourceID; + } + + public byte getNumChannels() { + return mNumChannels; + } + + public int getChanConfig() { + return mChanConfig; + } + + public int getControls() { + return mControls; + } + + @Override + public int parseRawDescriptors(ByteStream stream) { + super.parseRawDescriptors(stream); + + mClkSourceID = stream.getByte(); + mNumChannels = stream.getByte(); + mChanConfig = stream.unpackUsbInt(); + mChanNames = stream.getByte(); + mControls = stream.unpackUsbShort(); + mTerminalName = stream.getByte(); + + return mLength; + } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.openList(); + canvas.writeListItem("Clock Source: " + getClkSourceID()); + canvas.writeListItem("" + getNumChannels() + " Channels. Config: " + + ReportCanvas.getHexString(getChanConfig())); + canvas.closeList(); + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/Usb20ACMixerUnit.java b/services/usb/java/com/android/server/usb/descriptors/Usb20ACMixerUnit.java new file mode 100644 index 000000000000..1b267a67752b --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/Usb20ACMixerUnit.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors; + +/** + * @hide + * An audio class-specific Mixer Unit interface. + * see Audio20.pdf section 4.7.2.6 Mixer Unit Descriptor + */ +public final class Usb20ACMixerUnit extends UsbACMixerUnit { + private static final String TAG = "Usb20ACMixerUnit"; + + private int mChanConfig; // 6+p:4 Describes the spatial location of the + // logical channels. + private byte mChanNames; // 10+p:1 Index of a string descriptor, describing the + // name of the first logical channel. + private byte[] mControls; // 11+p:N bitmasks of which controls are present for each channel + // for N, see UsbACMixerUnit.calcControlArraySize() + private byte mControlsMask; // 11+p+N:1 bitmasks of which controls are present for each channel + private byte mNameID; // 12+p+N:1 Index of a string descriptor, describing the + // Mixer Unit. + + public Usb20ACMixerUnit(int length, byte type, byte subtype, byte subClass) { + super(length, type, subtype, subClass); + } + + @Override + public int parseRawDescriptors(ByteStream stream) { + super.parseRawDescriptors(stream); + + mChanConfig = stream.unpackUsbInt(); + mChanNames = stream.getByte(); + int controlArraySize = calcControlArraySize(mNumInputs, mNumOutputs); + mControls = new byte[controlArraySize]; + for (int index = 0; index < controlArraySize; index++) { + mControls[index] = stream.getByte(); + } + mControlsMask = stream.getByte(); + mNameID = stream.getByte(); + + return mLength; + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/Usb20ACOutputTerminal.java b/services/usb/java/com/android/server/usb/descriptors/Usb20ACOutputTerminal.java new file mode 100644 index 000000000000..67478aad8a59 --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/Usb20ACOutputTerminal.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors; + +import com.android.server.usb.descriptors.report.ReportCanvas; + +/** + * @hide + * An audio class-specific Output Terminal interface. + * see Audio20.pdf section 3.13.3 Output Terminal + */ +public final class Usb20ACOutputTerminal extends UsbACTerminal { + private static final String TAG = "Usb20ACOutputTerminal"; + + // Audio20.pdf - section 4.7.2.5, Table 4-10 + // Always 12 bytes + private byte mSourceID; // 7:1 - ID of the Unit or Terminal to which this + // Terminal is connected. + private byte mClkSoureID; // 8:1 - ID of the Clock Entity to which this Output + // Terminal is connected. + private int mControls; // 9:2 - see Audio20.pdf Table 4-10 + private byte mTerminalID; // 11:1 - Index of a string descriptor, describing the + + public Usb20ACOutputTerminal(int length, byte type, byte subtype, byte subClass) { + super(length, type, subtype, subClass); + } + + public byte getSourceID() { + return mSourceID; + } + + public byte getClkSourceID() { + return mClkSoureID; + } + + public int getControls() { + return mControls; + } + + public byte getTerminalID() { + return mTerminalID; + } + + @Override + public int parseRawDescriptors(ByteStream stream) { + super.parseRawDescriptors(stream); + + mSourceID = stream.getByte(); + mClkSoureID = stream.getByte(); + mControls = stream.unpackUsbShort(); + mTerminalID = stream.getByte(); + + return mLength; + } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.openList(); + canvas.writeListItem("Clock Source ID: " + getClkSourceID()); + canvas.writeListItem("Controls: " + ReportCanvas.getHexString(getControls())); + canvas.writeListItem("Terminal Name ID: " + getTerminalID()); + canvas.closeList(); + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/Usb20ASFormatI.java b/services/usb/java/com/android/server/usb/descriptors/Usb20ASFormatI.java new file mode 100644 index 000000000000..c03199619e74 --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/Usb20ASFormatI.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors; + +import com.android.server.usb.descriptors.report.ReportCanvas; + +/** + * @hide + * An audio class-specific Format I interface. + * see Frmts20.pdf section 2.3.1.6 Type I Format Type Descriptor + */ +public final class Usb20ASFormatI extends UsbASFormat { + private static final String TAG = "Usb20ASFormatI"; + + // Frmts20.pdf Table 2-2: Type I Format Type Descriptor + private byte mSubSlotSize; // 4:1 The number of bytes occupied by one + // audio subslot. Can be 1, 2, 3 or 4. + private byte mBitResolution; // 5:1 The number of effectively used bits from + // the available bits in an audio subslot. + + public Usb20ASFormatI(int length, byte type, byte subtype, byte formatType, byte subclass) { + super(length, type, subtype, formatType, subclass); + } + + /** + * TBD + */ + public byte getSubSlotSize() { + return mSubSlotSize; + } + + /** + * TBD + */ + public byte getBitResolution() { + return mBitResolution; + } + + @Override + public int parseRawDescriptors(ByteStream stream) { + mSubSlotSize = stream.getByte(); + mBitResolution = stream.getByte(); + + return mLength; + } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.openList(); + canvas.writeListItem("Subslot Size: " + getSubSlotSize()); + canvas.writeListItem("Bit Resolution: " + getBitResolution()); + canvas.closeList(); + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/Usb20ASFormatII.java b/services/usb/java/com/android/server/usb/descriptors/Usb20ASFormatII.java new file mode 100644 index 000000000000..dc44ff063964 --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/Usb20ASFormatII.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors; + +import com.android.server.usb.descriptors.report.ReportCanvas; + +/** + * @hide + * An audio class-specific Format II interface. + * see Frmts20.pdf section 2.3.2.6 Type II Format Type Descriptor + */ +public final class Usb20ASFormatII extends UsbASFormat { + private static final String TAG = "Usb20ASFormatII"; + + // Frmts20.pdf Table 2-3: Type II Format Type Descriptor + private int mMaxBitRate; // 4:2 Indicates the maximum number of bits per + // second this interface can handle in kbits/s. + private int mSlotsPerFrame; // 6:2 Indicates the number of PCM audio slots + // contained in one encoded audio frame. + + /** + * TBD + */ + public Usb20ASFormatII(int length, byte type, byte subtype, byte formatType, byte subclass) { + super(length, type, subtype, formatType, subclass); + } + + /** + * TBD + */ + public int getmaxBitRate() { + return mMaxBitRate; + } + + /** + * TBD + */ + public int getSlotsPerFrame() { + return mSlotsPerFrame; + } + + @Override + public int parseRawDescriptors(ByteStream stream) { + mMaxBitRate = stream.unpackUsbShort(); + mSlotsPerFrame = stream.unpackUsbShort(); + + return mLength; + } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.openList(); + canvas.writeListItem("Max Bit Rate: " + getmaxBitRate()); + canvas.writeListItem("slots Per Frame: " + getSlotsPerFrame()); + canvas.closeList(); + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/Usb20ASFormatIIEx.java b/services/usb/java/com/android/server/usb/descriptors/Usb20ASFormatIIEx.java new file mode 100644 index 000000000000..d7dfba396984 --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/Usb20ASFormatIIEx.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors; + +import com.android.server.usb.descriptors.report.ReportCanvas; + +/** + * @hide + * An audio class-specific Format II interface. + * see Frmts20.pdf section 2.4.2.1 Extended Type II Format Type Descriptor + */ +public final class Usb20ASFormatIIEx extends UsbASFormat { + private static final String TAG = "Usb20ASFormatIIEx"; + + // Frmts20.pdf Table 2-7: Extended Type II Format Type Descriptor + private int mMaxBitRate; // 4:2 Indicates the maximum number of bits per + // second this interface can handle in kbits/s + private int mSamplesPerFrame; // 6:2 Indicates the number of PCM audio + // samples contained in one encoded audio frame. + private byte mHeaderLength; // 8:1 Size of the Packet Header, in bytes. + private byte mSidebandProtocol; // 9:1 Constant, identifying the Side Band + // Protocol used for the Packet Header content. + + public Usb20ASFormatIIEx(int length, byte type, byte subtype, byte formatType, byte subclass) { + super(length, type, subtype, formatType, subclass); + } + + public int getMaxBitRate() { + return mMaxBitRate; + } + + public int getSamplesPerFrame() { + return mSamplesPerFrame; + } + + public byte getHeaderLength() { + return mHeaderLength; + } + + public byte getSidebandProtocol() { + return mSidebandProtocol; + } + + @Override + public int parseRawDescriptors(ByteStream stream) { + mMaxBitRate = stream.unpackUsbShort(); + mSamplesPerFrame = stream.unpackUsbShort(); + mHeaderLength = stream.getByte(); + mSidebandProtocol = stream.getByte(); + + return mLength; + } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.openList(); + canvas.writeListItem("Max Bit Rate: " + getMaxBitRate()); + canvas.writeListItem("Samples Per Frame: " + getSamplesPerFrame()); + canvas.writeListItem("Header Length: " + getHeaderLength()); + canvas.writeListItem("Sideband Protocol: " + getSidebandProtocol()); + canvas.closeList(); + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/Usb20ASFormatIII.java b/services/usb/java/com/android/server/usb/descriptors/Usb20ASFormatIII.java new file mode 100644 index 000000000000..b44a216703f8 --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/Usb20ASFormatIII.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors; + +import com.android.server.usb.descriptors.report.ReportCanvas; + +/** + * @hide + * An audio class-specific Format III interface. + * see Frmts20.pdf section 2.3.1.6 2.3.3.1 Type III Format Type Descriptor + */ +public final class Usb20ASFormatIII extends UsbASFormat { + private static final String TAG = "Usb20ASFormatIII"; + + // frmts20.pdf Table 2-4: Type III Format Type Descriptor + private byte mSubslotSize; // 4:1 The number of bytes occupied by one + // audio subslot. Must be set to two. + private byte mBitResolution; // 5:1 The number of effectively used bits from + // the available bits in an audio subframe. + + public Usb20ASFormatIII(int length, byte type, byte subtype, byte formatType, byte subclass) { + super(length, type, subtype, formatType, subclass); + } + + public byte getSubslotSize() { + return mSubslotSize; + } + + public byte getBitResolution() { + return mBitResolution; + } + + @Override + public int parseRawDescriptors(ByteStream stream) { + mSubslotSize = stream.getByte(); + mBitResolution = stream.getByte(); + + return mLength; + } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.openList(); + canvas.writeListItem("Subslot Size: " + getSubslotSize()); + canvas.writeListItem("Bit Resolution: " + getBitResolution()); + canvas.closeList(); + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/Usb20ASGeneral.java b/services/usb/java/com/android/server/usb/descriptors/Usb20ASGeneral.java new file mode 100644 index 000000000000..18d48a009098 --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/Usb20ASGeneral.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors; + +import com.android.server.usb.descriptors.report.ReportCanvas; + +/** + * Audio20.pdf - 4.9.2 Class-Specific AS Interface Descriptor + * 16 bytes + */ +public final class Usb20ASGeneral extends UsbACInterface { + private static final String TAG = "Usb20ASGeneral"; + + // Audio20.pdf - Table 4-27 + private byte mTerminalLink; // 3:1 The Terminal ID of the Terminal to which + // this interface is connected. + private byte mControls; // 4:1 see audio20.pdf Table 4-27 + private byte mFormatType; // 5:1 Constant identifying the Format Type the + // AudioStreaming interface is using. + private int mFormats; // 6:4 The Audio Data Format(s) that can be + // used to communicate with this interface. + // See the USB Audio Data Formats + // document for further details. + private byte mNumChannels; // 10:1 Number of physical channels in the AS + // Interface audio channel cluster. + private int mChannelConfig; // 11:4 Describes the spatial location of the + // physical channels. + private byte mChannelNames; // 15:1 Index of a string descriptor, describing the + // name of the first physical channel. + + public Usb20ASGeneral(int length, byte type, byte subtype, byte subclass) { + super(length, type, subtype, subclass); + } + + public byte getTerminalLink() { + return mTerminalLink; + } + + public byte getControls() { + return mControls; + } + + public byte getFormatType() { + return mFormatType; + } + + public int getFormats() { + return mFormats; + } + + public byte getNumChannels() { + return mNumChannels; + } + + public int getChannelConfig() { + return mChannelConfig; + } + + public byte getChannelNames() { + return mChannelNames; + } + + @Override + public int parseRawDescriptors(ByteStream stream) { + + mTerminalLink = stream.getByte(); + mControls = stream.getByte(); + mFormatType = stream.getByte(); + mFormats = stream.unpackUsbInt(); + mNumChannels = stream.getByte(); + mChannelConfig = stream.unpackUsbInt(); + mChannelNames = stream.getByte(); + + return mLength; + } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.openList(); + canvas.writeListItem("Terminal Link: " + getTerminalLink()); + canvas.writeListItem("Controls: " + ReportCanvas.getHexString(getControls())); + canvas.writeListItem("Format Type: " + ReportCanvas.getHexString(getFormatType())); + canvas.writeListItem("Formats: " + ReportCanvas.getHexString(getFormats())); + canvas.writeListItem("Num Channels: " + getNumChannels()); + canvas.writeListItem("Channel Config: " + ReportCanvas.getHexString(getChannelConfig())); + canvas.writeListItem("Channel Names String ID: " + getChannelNames()); + canvas.closeList(); + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbACAudioControlEndpoint.java b/services/usb/java/com/android/server/usb/descriptors/UsbACAudioControlEndpoint.java index 96fcc6a0b8db..6e1ce07536c5 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbACAudioControlEndpoint.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbACAudioControlEndpoint.java @@ -21,7 +21,7 @@ package com.android.server.usb.descriptors; * audio10.pdf section 4.4.2.1 */ public class UsbACAudioControlEndpoint extends UsbACEndpoint { - private static final String TAG = "ACAudioControlEndpoint"; + private static final String TAG = "UsbACAudioControlEndpoint"; private byte mAddress; // 2:1 The address of the endpoint on the USB device. // D7: Direction. 1 = IN endpoint @@ -64,7 +64,7 @@ public class UsbACAudioControlEndpoint extends UsbACEndpoint { mAddress = stream.getByte(); mAttribs = stream.getByte(); - mMaxPacketSize = stream.unpackUsbWord(); + mMaxPacketSize = stream.unpackUsbShort(); mInterval = stream.getByte(); return mLength; diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbACAudioStreamEndpoint.java b/services/usb/java/com/android/server/usb/descriptors/UsbACAudioStreamEndpoint.java index d387883d3049..d35190298df6 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbACAudioStreamEndpoint.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbACAudioStreamEndpoint.java @@ -21,7 +21,7 @@ package com.android.server.usb.descriptors; * see audio10.pdf section 3.7.2 */ public class UsbACAudioStreamEndpoint extends UsbACEndpoint { - private static final String TAG = "ACAudioStreamEndpoint"; + private static final String TAG = "UsbACAudioStreamEndpoint"; //TODO data fields... public UsbACAudioStreamEndpoint(int length, byte type, byte subclass) { diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbACEndpoint.java b/services/usb/java/com/android/server/usb/descriptors/UsbACEndpoint.java index 223496ab016e..4a6839d943ff 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbACEndpoint.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbACEndpoint.java @@ -23,7 +23,7 @@ import android.util.Log; * see audio10.pdf section 4.4.1.2 */ abstract class UsbACEndpoint extends UsbDescriptor { - private static final String TAG = "ACEndpoint"; + private static final String TAG = "UsbACEndpoint"; protected final byte mSubclass; // from the mSubclass member of the "enclosing" // Interface Descriptor, not the stream. @@ -50,7 +50,7 @@ abstract class UsbACEndpoint extends UsbDescriptor { } public static UsbDescriptor allocDescriptor(UsbDescriptorParser parser, - int length, byte type) { + int length, byte type) { UsbInterfaceDescriptor interfaceDesc = parser.getCurInterface(); byte subClass = interfaceDesc.getUsbSubclass(); switch (subClass) { diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbACFeatureUnit.java b/services/usb/java/com/android/server/usb/descriptors/UsbACFeatureUnit.java index 739fe5503a1d..ab3903b402d9 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbACFeatureUnit.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbACFeatureUnit.java @@ -20,8 +20,8 @@ package com.android.server.usb.descriptors; * An audio class-specific Feature Unit Interface * see audio10.pdf section 3.5.5 */ -public class UsbACFeatureUnit extends UsbACInterface { - private static final String TAG = "ACFeatureUnit"; +public final class UsbACFeatureUnit extends UsbACInterface { + private static final String TAG = "UsbACFeatureUnit"; // audio10.pdf section 4.3.2.5 public static final int CONTROL_MASK_MUTE = 0x0001; diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbACHeaderInterface.java b/services/usb/java/com/android/server/usb/descriptors/UsbACHeaderInterface.java new file mode 100644 index 000000000000..01a355e2c6e4 --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/UsbACHeaderInterface.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors; + +import com.android.server.usb.descriptors.report.ReportCanvas; + +/** + * @hide + * An audio class-specific Interface Header super class. + * see audio10.pdf section 4.3.2 & Audio20.pdf section 4.7.2 + */ +public abstract class UsbACHeaderInterface extends UsbACInterface { + private static final String TAG = "UsbACHeaderInterface"; + + protected int mADCRelease; // Audio Device Class Specification Release (BCD). + protected int mTotalLength; // Total number of bytes returned for the class-specific + // AudioControl interface descriptor. Includes the combined length + // of this descriptor header and all Unit and Terminal descriptors. + + public UsbACHeaderInterface( + int length, byte type, byte subtype, byte subclass, int adcRelease) { + super(length, type, subtype, subclass); + mADCRelease = adcRelease; + } + + public int getADCRelease() { + return mADCRelease; + } + + public int getTotalLength() { + return mTotalLength; + } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.openList(); + canvas.writeListItem("Release: " + ReportCanvas.getBCDString(getADCRelease())); + canvas.writeListItem("Total Length: " + getTotalLength()); + canvas.closeList(); + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbACInterface.java b/services/usb/java/com/android/server/usb/descriptors/UsbACInterface.java index 0ab7fccd2c3b..df6c53fa9f52 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbACInterface.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbACInterface.java @@ -17,13 +17,16 @@ package com.android.server.usb.descriptors; import android.util.Log; +import com.android.server.usb.descriptors.report.ReportCanvas; +import com.android.server.usb.descriptors.report.UsbStrings; + /** * @hide * An audio class-specific Interface. * see audio10.pdf section 4.3.2 */ public abstract class UsbACInterface extends UsbDescriptor { - private static final String TAG = "ACInterface"; + private static final String TAG = "UsbACInterface"; // Audio Control Subtypes public static final byte ACI_UNDEFINED = 0; @@ -35,6 +38,11 @@ public abstract class UsbACInterface extends UsbDescriptor { public static final byte ACI_FEATURE_UNIT = 6; public static final byte ACI_PROCESSING_UNIT = 7; public static final byte ACI_EXTENSION_UNIT = 8; + // Not handled yet + public static final byte ACI_CLOCK_SOURCE = 0x0A; + public static final byte ACI_CLOCK_SELECTOR = 0x0B; + public static final byte ACI_CLOCK_MULTIPLIER = 0x0C; + public static final byte ACI_SAMPLE_RATE_CONVERTER = 0x0D; // Audio Streaming Subtypes public static final byte ASI_UNDEFINED = 0; @@ -87,17 +95,39 @@ public abstract class UsbACInterface extends UsbDescriptor { return mSubclass; } - private static UsbDescriptor allocAudioControlDescriptor(ByteStream stream, - int length, byte type, byte subtype, byte subClass) { + private static UsbDescriptor allocAudioControlDescriptor(UsbDescriptorParser parser, + ByteStream stream, int length, byte type, byte subtype, byte subClass) { switch (subtype) { case ACI_HEADER: - return new UsbACHeader(length, type, subtype, subClass); + { + int acInterfaceSpec = stream.unpackUsbShort(); + parser.setACInterfaceSpec(acInterfaceSpec); + if (acInterfaceSpec == UsbDeviceDescriptor.USBSPEC_2_0) { + return new Usb20ACHeader(length, type, subtype, subClass, acInterfaceSpec); + } else { + return new Usb10ACHeader(length, type, subtype, subClass, acInterfaceSpec); + } + } case ACI_INPUT_TERMINAL: - return new UsbACInputTerminal(length, type, subtype, subClass); + { + int acInterfaceSpec = parser.getACInterfaceSpec(); + if (acInterfaceSpec == UsbDeviceDescriptor.USBSPEC_2_0) { + return new Usb20ACInputTerminal(length, type, subtype, subClass); + } else { + return new Usb10ACInputTerminal(length, type, subtype, subClass); + } + } case ACI_OUTPUT_TERMINAL: - return new UsbACOutputTerminal(length, type, subtype, subClass); + { + int acInterfaceSpec = parser.getACInterfaceSpec(); + if (acInterfaceSpec == UsbDeviceDescriptor.USBSPEC_2_0) { + return new Usb20ACOutputTerminal(length, type, subtype, subClass); + } else { + return new Usb10ACOutputTerminal(length, type, subtype, subClass); + } + } case ACI_SELECTOR_UNIT: return new UsbACSelectorUnit(length, type, subtype, subClass); @@ -106,7 +136,14 @@ public abstract class UsbACInterface extends UsbDescriptor { return new UsbACFeatureUnit(length, type, subtype, subClass); case ACI_MIXER_UNIT: - return new UsbACMixerUnit(length, type, subtype, subClass); + { + int acInterfaceSpec = parser.getACInterfaceSpec(); + if (acInterfaceSpec == UsbDeviceDescriptor.USBSPEC_2_0) { + return new Usb20ACMixerUnit(length, type, subtype, subClass); + } else { + return new Usb10ACMixerUnit(length, type, subtype, subClass); + } + } case ACI_PROCESSING_UNIT: case ACI_EXTENSION_UNIT: @@ -115,18 +152,24 @@ public abstract class UsbACInterface extends UsbDescriptor { default: Log.w(TAG, "Unknown Audio Class Interface subtype:0x" + Integer.toHexString(subtype)); - return null; + return new UsbACInterfaceUnparsed(length, type, subtype, subClass); } } - private static UsbDescriptor allocAudioStreamingDescriptor(ByteStream stream, - int length, byte type, byte subtype, byte subClass) { + private static UsbDescriptor allocAudioStreamingDescriptor(UsbDescriptorParser parser, + ByteStream stream, int length, byte type, byte subtype, byte subClass) { + //int spec = parser.getUsbSpec(); + int acInterfaceSpec = parser.getACInterfaceSpec(); switch (subtype) { case ASI_GENERAL: - return new UsbASGeneral(length, type, subtype, subClass); + if (acInterfaceSpec == UsbDeviceDescriptor.USBSPEC_2_0) { + return new Usb20ASGeneral(length, type, subtype, subClass); + } else { + return new Usb10ASGeneral(length, type, subtype, subClass); + } case ASI_FORMAT_TYPE: - return UsbASFormat.allocDescriptor(stream, length, type, subtype, subClass); + return UsbASFormat.allocDescriptor(parser, stream, length, type, subtype, subClass); case ASI_FORMAT_SPECIFIC: case ASI_UNDEFINED: @@ -155,7 +198,6 @@ public abstract class UsbACInterface extends UsbDescriptor { // Fall through until we implement that descriptor case MSI_UNDEFINED: - // break; Fall through until we implement this descriptor default: Log.w(TAG, "Unknown MIDI Streaming Interface subtype:0x" + Integer.toHexString(subtype)); @@ -173,10 +215,12 @@ public abstract class UsbACInterface extends UsbDescriptor { byte subClass = interfaceDesc.getUsbSubclass(); switch (subClass) { case AUDIO_AUDIOCONTROL: - return allocAudioControlDescriptor(stream, length, type, subtype, subClass); + return allocAudioControlDescriptor( + parser, stream, length, type, subtype, subClass); case AUDIO_AUDIOSTREAMING: - return allocAudioStreamingDescriptor(stream, length, type, subtype, subClass); + return allocAudioStreamingDescriptor( + parser, stream, length, type, subtype, subClass); case AUDIO_MIDISTREAMING: return allocMidiStreamingDescriptor(length, type, subtype, subClass); @@ -187,4 +231,21 @@ public abstract class UsbACInterface extends UsbDescriptor { return null; } } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + byte subClass = getSubclass(); + String subClassName = UsbStrings.getACInterfaceSubclassName(subClass); + + byte subtype = getSubtype(); + String subTypeName = UsbStrings.getACControlInterfaceName(subtype); + + canvas.openList(); + canvas.writeListItem("Subclass: " + ReportCanvas.getHexString(subClass) + + " " + subClassName); + canvas.writeListItem("Subtype: " + ReportCanvas.getHexString(subtype) + " " + subTypeName); + canvas.closeList(); + } } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbACInterfaceUnparsed.java b/services/usb/java/com/android/server/usb/descriptors/UsbACInterfaceUnparsed.java new file mode 100644 index 000000000000..9e00a7976dfd --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/UsbACInterfaceUnparsed.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors; + +/** + * @hide + * A holder class for as yet unparsed audio-class interfaces. + */ +public final class UsbACInterfaceUnparsed extends UsbACInterface { + private static final String TAG = "UsbACInterfaceUnparsed"; + + public UsbACInterfaceUnparsed(int length, byte type, byte subtype, byte subClass) { + super(length, type, subtype, subClass); + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbACMidiEndpoint.java b/services/usb/java/com/android/server/usb/descriptors/UsbACMidiEndpoint.java index 9c072426cc49..9c314575ccc4 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbACMidiEndpoint.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbACMidiEndpoint.java @@ -15,13 +15,15 @@ */ package com.android.server.usb.descriptors; +import com.android.server.usb.descriptors.report.ReportCanvas; + /** * @hide * An audio class-specific Midi Endpoint. * see midi10.pdf section 6.2.2 */ -public class UsbACMidiEndpoint extends UsbACEndpoint { - private static final String TAG = "ACMidiEndpoint"; +public final class UsbACMidiEndpoint extends UsbACEndpoint { + private static final String TAG = "UsbACMidiEndpoint"; private byte mNumJacks; private byte[] mJackIds; @@ -49,4 +51,15 @@ public class UsbACMidiEndpoint extends UsbACEndpoint { } return mLength; } -} + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.writeHeader(3, "AC Midi Endpoint: " + ReportCanvas.getHexString(getType()) + + " Length: " + getLength()); + canvas.openList(); + canvas.writeListItem("" + getNumJacks() + " Jacks."); + canvas.closeList(); + } +}
\ No newline at end of file diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbACMixerUnit.java b/services/usb/java/com/android/server/usb/descriptors/UsbACMixerUnit.java index 552b5ae308d6..88faed962a54 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbACMixerUnit.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbACMixerUnit.java @@ -15,23 +15,14 @@ */ package com.android.server.usb.descriptors; -/** - * @hide - * An audio class-specific Mixer Interface. - * see audio10.pdf section 4.3.2.3 - */ public class UsbACMixerUnit extends UsbACInterface { - private static final String TAG = "ACMixerUnit"; + private static final String TAG = "UsbACMixerUnit"; - private byte mUnitID; // 3:1 - private byte mNumInputs; // 4:1 Number of Input Pins of this Unit. - private byte[] mInputIDs; // 5...:1 ID of the Unit or Terminal to which the Input Pins - // are connected. - private byte mNumOutputs; // The number of output channels - private int mChannelConfig; // Spacial location of output channels - private byte mChanNameID; // First channel name string descriptor ID - private byte[] mControls; // bitmasks of which controls are present for each channel - private byte mNameID; // string descriptor ID of mixer name + protected byte mUnitID; // 3:1 + protected byte mNumInputs; // 4:1 Number of Input Pins of this Unit. + protected byte[] mInputIDs; // 5...:1 ID of the Unit or Terminal to which the Input Pins + // are connected. + protected byte mNumOutputs; // The number of output channels public UsbACMixerUnit(int length, byte type, byte subtype, byte subClass) { super(length, type, subtype, subClass); @@ -53,20 +44,9 @@ public class UsbACMixerUnit extends UsbACInterface { return mNumOutputs; } - public int getChannelConfig() { - return mChannelConfig; - } - - public byte getChanNameID() { - return mChanNameID; - } - - public byte[] getControls() { - return mControls; - } - - public byte getNameID() { - return mNameID; + protected static int calcControlArraySize(int numInputs, int numOutputs) { + int totalChannels = numInputs * numOutputs; + return (totalChannels + 7) / 8; } @Override @@ -78,22 +58,6 @@ public class UsbACMixerUnit extends UsbACInterface { mInputIDs[input] = stream.getByte(); } mNumOutputs = stream.getByte(); - mChannelConfig = stream.unpackUsbWord(); - mChanNameID = stream.getByte(); - - int controlArraySize; - int totalChannels = mNumInputs * mNumOutputs; - if (totalChannels % 8 == 0) { - controlArraySize = totalChannels / 8; - } else { - controlArraySize = totalChannels / 8 + 1; - } - mControls = new byte[controlArraySize]; - for (int index = 0; index < controlArraySize; index++) { - mControls[index] = stream.getByte(); - } - - mNameID = stream.getByte(); return mLength; } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbACSelectorUnit.java b/services/usb/java/com/android/server/usb/descriptors/UsbACSelectorUnit.java index b1f60bdcf6ed..b16bc575e806 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbACSelectorUnit.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbACSelectorUnit.java @@ -15,13 +15,15 @@ */ package com.android.server.usb.descriptors; +// import com.android.server.usb.descriptors.report.ReportCanvas; + /** * @hide * An audio class-specific Selector Unit Interface. * see audio10.pdf section 4.3.2.4 */ -public class UsbACSelectorUnit extends UsbACInterface { - private static final String TAG = "ACSelectorUnit"; +public final class UsbACSelectorUnit extends UsbACInterface { + private static final String TAG = "UsbACSelectorUnit"; private byte mUnitID; // 3:1 Constant uniquely identifying the Unit within the audio function. // This value is used in all requests to address this Unit. @@ -62,4 +64,11 @@ public class UsbACSelectorUnit extends UsbACInterface { return mLength; } + +// @Override +// public void report(ReportCanvas canvas) { +// super.report(canvas); +// +// //TODO +// } } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbACTerminal.java b/services/usb/java/com/android/server/usb/descriptors/UsbACTerminal.java index ea80208ee3f3..2836508581d8 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbACTerminal.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbACTerminal.java @@ -15,10 +15,15 @@ */ package com.android.server.usb.descriptors; +import com.android.server.usb.descriptors.report.ReportCanvas; +import com.android.server.usb.descriptors.report.UsbStrings; + /** * @hide */ public abstract class UsbACTerminal extends UsbACInterface { + private static final String TAG = "UsbACTerminal"; + // Note that these fields are the same for both the // audio class-specific Output Terminal Interface.(audio10.pdf section 4.3.2.2) // and audio class-specific Input Terminal interface.(audio10.pdf section 4.3.2.1) @@ -46,9 +51,21 @@ public abstract class UsbACTerminal extends UsbACInterface { @Override public int parseRawDescriptors(ByteStream stream) { mTerminalID = stream.getByte(); - mTerminalType = stream.unpackUsbWord(); + mTerminalType = stream.unpackUsbShort(); mAssocTerminal = stream.getByte(); return mLength; } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.openList(); + int terminalType = getTerminalType(); + canvas.writeListItem("Type: " + ReportCanvas.getHexString(terminalType) + ": " + + UsbStrings.getTerminalName(terminalType)); + canvas.writeListItem("ID: " + ReportCanvas.getHexString(getTerminalID())); + canvas.closeList(); + } } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbASFormat.java b/services/usb/java/com/android/server/usb/descriptors/UsbASFormat.java index d7c84c6a0965..305ae2f27372 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbASFormat.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbASFormat.java @@ -15,19 +15,30 @@ */ package com.android.server.usb.descriptors; +import com.android.server.usb.descriptors.report.ReportCanvas; +import com.android.server.usb.descriptors.report.UsbStrings; + /** * @hide * An audio class-specific Format Interface. * Subclasses: UsbACFormatI and UsbACFormatII. * see audio10.pdf section 4.5.3 & & Frmts10.pdf */ -public abstract class UsbASFormat extends UsbACInterface { - private static final String TAG = "ASFormat"; +public class UsbASFormat extends UsbACInterface { + private static final String TAG = "UsbASFormat"; private final byte mFormatType; // 3:1 FORMAT_TYPE_* - public static final byte FORMAT_TYPE_I = 1; - public static final byte FORMAT_TYPE_II = 2; + public static final byte FORMAT_TYPE_I = 1; + public static final byte FORMAT_TYPE_II = 2; + // these showed up in USB 2.0 + public static final byte FORMAT_TYPE_III = 3; + public static final byte FORMAT_TYPE_IV = 4; + + // "extended" formats + public static final byte EXT_FORMAT_TYPE_I = (byte) 0x81; + public static final byte EXT_FORMAT_TYPE_II = (byte) 0x82; + public static final byte EXT_FORMAT_TYPE_III = (byte) 0x83; public UsbASFormat(int length, byte type, byte subtype, byte formatType, byte mSubclass) { super(length, type, subtype, mSubclass); @@ -38,27 +49,59 @@ public abstract class UsbASFormat extends UsbACInterface { return mFormatType; } + public int[] getSampleRates() { + return null; + } + + public int[] getBitDepths() { + return null; + } + + public int[] getChannelCounts() { + return null; + } + /** * Allocates the audio-class format subtype associated with the format type read from the * stream. */ - public static UsbDescriptor allocDescriptor(ByteStream stream, int length, byte type, + public static UsbDescriptor allocDescriptor(UsbDescriptorParser parser, + ByteStream stream, int length, byte type, byte subtype, byte subclass) { byte formatType = stream.getByte(); - //TODO - // There is an issue parsing format descriptors on (some) USB 2.0 pro-audio interfaces - // Since we don't need this info for headset detection, just skip these descriptors - // for now to avoid the (low) possibility of an IndexOutOfBounds exception. + int acInterfaceSpec = parser.getACInterfaceSpec(); + switch (formatType) { -// case FORMAT_TYPE_I: -// return new UsbASFormatI(length, type, subtype, formatType, subclass); -// -// case FORMAT_TYPE_II: -// return new UsbASFormatII(length, type, subtype, formatType, subclass); + case FORMAT_TYPE_I: + if (acInterfaceSpec == UsbDeviceDescriptor.USBSPEC_2_0) { + return new Usb20ASFormatI(length, type, subtype, formatType, subclass); + } else { + return new Usb10ASFormatI(length, type, subtype, formatType, subclass); + } + + case FORMAT_TYPE_II: + if (acInterfaceSpec == UsbDeviceDescriptor.USBSPEC_2_0) { + return new Usb20ASFormatII(length, type, subtype, formatType, subclass); + } else { + return new Usb10ASFormatII(length, type, subtype, formatType, subclass); + } + + // USB 2.0 Exclusive Format Types + case FORMAT_TYPE_III: + return new Usb20ASFormatIII(length, type, subtype, formatType, subclass); + case FORMAT_TYPE_IV: + //TODO - implement this type. default: - return null; + return new UsbASFormat(length, type, subtype, formatType, subclass); } } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.write(UsbStrings.getFormatName(getFormatType())); + } } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbBinaryParser.java b/services/usb/java/com/android/server/usb/descriptors/UsbBinaryParser.java index 185cee20b090..9710ac67870f 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbBinaryParser.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbBinaryParser.java @@ -25,7 +25,7 @@ import com.android.server.usb.descriptors.report.UsbStrings; * A class that just walks the descriptors and does a hex dump of the contained values. * Usefull as a debugging tool. */ -public class UsbBinaryParser { +public final class UsbBinaryParser { private static final String TAG = "UsbBinaryParser"; private static final boolean LOGGING = false; @@ -33,7 +33,7 @@ public class UsbBinaryParser { // Log if (LOGGING) { - Log.i(TAG, "l:" + length + " t:" + Integer.toHexString(type) + " " + Log.i(TAG, "l: " + length + " t: " + Integer.toHexString(type) + " " + UsbStrings.getDescriptorName(type)); StringBuilder sb = new StringBuilder(); for (int index = 2; index < length; index++) { @@ -43,7 +43,7 @@ public class UsbBinaryParser { } else { // Screen Dump builder.append("<p>"); - builder.append("<b> l:" + length + builder.append("<b> l: " + length + " t:0x" + Integer.toHexString(type) + " " + UsbStrings.getDescriptorName(type) + "</b><br>"); for (int index = 2; index < length; index++) { diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbConfigDescriptor.java b/services/usb/java/com/android/server/usb/descriptors/UsbConfigDescriptor.java index 8ae6d0f1ee7e..75279c61c4f0 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbConfigDescriptor.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbConfigDescriptor.java @@ -15,13 +15,15 @@ */ package com.android.server.usb.descriptors; +import com.android.server.usb.descriptors.report.ReportCanvas; + /** * @hide * An USB Config Descriptor. * see usb11.pdf section 9.6.2 */ -public class UsbConfigDescriptor extends UsbDescriptor { - private static final String TAG = "Config"; +public final class UsbConfigDescriptor extends UsbDescriptor { + private static final String TAG = "UsbConfigDescriptor"; private int mTotalLength; // 2:2 Total length in bytes of data returned private byte mNumInterfaces; // 4:1 Number of Interfaces @@ -35,6 +37,7 @@ public class UsbConfigDescriptor extends UsbDescriptor { UsbConfigDescriptor(int length, byte type) { super(length, type); + mHierarchyLevel = 2; } public int getTotalLength() { @@ -63,7 +66,7 @@ public class UsbConfigDescriptor extends UsbDescriptor { @Override public int parseRawDescriptors(ByteStream stream) { - mTotalLength = stream.unpackUsbWord(); + mTotalLength = stream.unpackUsbShort(); mNumInterfaces = stream.getByte(); mConfigValue = stream.getByte(); mConfigIndex = stream.getByte(); @@ -72,4 +75,15 @@ public class UsbConfigDescriptor extends UsbDescriptor { return mLength; } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.openList(); + canvas.writeListItem("Config # " + getConfigValue()); + canvas.writeListItem(getNumInterfaces() + " Interfaces."); + canvas.writeListItem("Attributes: " + ReportCanvas.getHexString(getAttribs())); + canvas.closeList(); + } } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptor.java b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptor.java index 63b2d7f6aed7..8c7565b790d2 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptor.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptor.java @@ -19,6 +19,10 @@ import android.hardware.usb.UsbConstants; import android.hardware.usb.UsbDeviceConnection; import android.util.Log; +import com.android.server.usb.descriptors.report.ReportCanvas; +import com.android.server.usb.descriptors.report.Reporting; +import com.android.server.usb.descriptors.report.UsbStrings; + /* * Some notes about UsbDescriptor and its subclasses. * @@ -33,8 +37,10 @@ import android.util.Log; * @hide * Common superclass for all USB Descriptors. */ -public abstract class UsbDescriptor { - private static final String TAG = "Descriptor"; +public abstract class UsbDescriptor implements Reporting { + private static final String TAG = "UsbDescriptor"; + + protected int mHierarchyLevel; protected final int mLength; // 0:1 bLength Number Size of the Descriptor in Bytes (18 bytes) // we store this as an int because Java bytes are SIGNED. @@ -50,11 +56,15 @@ public abstract class UsbDescriptor { public static final int STATUS_PARSED_OK = 1; public static final int STATUS_PARSED_UNDERRUN = 2; public static final int STATUS_PARSED_OVERRUN = 3; + public static final int STATUS_PARSE_EXCEPTION = 4; + private int mStatus = STATUS_UNPARSED; private static String[] sStatusStrings = { "UNPARSED", "PARSED - OK", "PARSED - UNDERRUN", "PARSED - OVERRUN"}; + private int mOverUnderRunCount; + // Descriptor Type IDs public static final byte DESCRIPTORTYPE_DEVICE = 0x01; // 1 public static final byte DESCRIPTORTYPE_CONFIG = 0x02; // 2 @@ -147,6 +157,10 @@ public abstract class UsbDescriptor { mStatus = status; } + public int getOverUnderRunCount() { + return mOverUnderRunCount; + } + public String getStatusString() { return sStatusStrings[mStatus]; } @@ -165,14 +179,16 @@ public abstract class UsbDescriptor { // Too cold... stream.advance(mLength - bytesRead); mStatus = STATUS_PARSED_UNDERRUN; + mOverUnderRunCount = mLength - bytesRead; Log.w(TAG, "UNDERRUN t:0x" + Integer.toHexString(mType) - + " r:" + bytesRead + " < l:" + mLength); + + " r: " + bytesRead + " < l: " + mLength); } else if (bytesRead > mLength) { // Too hot... stream.reverse(bytesRead - mLength); mStatus = STATUS_PARSED_OVERRUN; + mOverUnderRunCount = bytesRead - mLength; Log.w(TAG, "OVERRRUN t:0x" + Integer.toHexString(mType) - + " r:" + bytesRead + " > l:" + mLength); + + " r: " + bytesRead + " > l: " + mLength); } else { // Just right! mStatus = STATUS_PARSED_OK; @@ -220,4 +236,43 @@ public abstract class UsbDescriptor { } return usbStr; } + + private void reportParseStatus(ReportCanvas canvas) { + int status = getStatus(); + switch (status) { + case UsbDescriptor.STATUS_PARSED_OK: + break; // no need to report + + case UsbDescriptor.STATUS_UNPARSED: + case UsbDescriptor.STATUS_PARSED_UNDERRUN: + case UsbDescriptor.STATUS_PARSED_OVERRUN: + canvas.writeParagraph("status: " + getStatusString() + + " [" + getOverUnderRunCount() + "]", true); + break; + } + } + + @Override + public void report(ReportCanvas canvas) { + String descTypeStr = UsbStrings.getDescriptorName(getType()); + String text = descTypeStr + ": " + ReportCanvas.getHexString(getType()) + + " Len: " + getLength(); + if (mHierarchyLevel != 0) { + canvas.writeHeader(mHierarchyLevel, text); + } else { + canvas.writeParagraph(text, false); + } + + if (getStatus() != STATUS_PARSED_OK) { + reportParseStatus(canvas); + } + } + + @Override + public void shortReport(ReportCanvas canvas) { + String descTypeStr = UsbStrings.getDescriptorName(getType()); + String text = descTypeStr + ": " + ReportCanvas.getHexString(getType()) + + " Len: " + getLength(); + canvas.writeParagraph(text, false); + } } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java index d4a0ac4a0da3..ad7bde5c275e 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java @@ -23,8 +23,8 @@ import java.util.ArrayList; * @hide * Class for parsing a binary stream of USB Descriptors. */ -public class UsbDescriptorParser { - private static final String TAG = "DescriptorParser"; +public final class UsbDescriptorParser { + private static final String TAG = "UsbDescriptorParser"; // Descriptor Objects private ArrayList<UsbDescriptor> mDescriptors = new ArrayList<UsbDescriptor>(); @@ -32,9 +32,35 @@ public class UsbDescriptorParser { private UsbDeviceDescriptor mDeviceDescriptor; private UsbInterfaceDescriptor mCurInterfaceDescriptor; + // The AudioClass spec implemented by the AudioClass Interfaces + // This may well be different than the overall USB Spec. + // Obtained from the first AudioClass Header descriptor. + private int mACInterfacesSpec = UsbDeviceDescriptor.USBSPEC_1_0; + public UsbDescriptorParser() {} /** + * @return the USB Spec value associated with the Device descriptor for the + * descriptors stream being parsed. + * + * @throws IllegalArgumentException + */ + public int getUsbSpec() { + if (mDeviceDescriptor != null) { + return mDeviceDescriptor.getSpec(); + } else { + throw new IllegalArgumentException(); + } + } + + public void setACInterfaceSpec(int spec) { + mACInterfacesSpec = spec; + } + + public int getACInterfaceSpec() { + return mACInterfacesSpec; + } + /** * The probability (as returned by getHeadsetProbability() at which we conclude * the peripheral is a headset. */ @@ -44,7 +70,7 @@ public class UsbDescriptorParser { private UsbDescriptor allocDescriptor(ByteStream stream) { stream.resetReadCount(); - int length = (int) stream.getByte() & 0x000000FF; + int length = stream.getUnsignedByte(); byte type = stream.getByte(); UsbDescriptor descriptor = null; @@ -99,7 +125,7 @@ public class UsbDescriptorParser { if (descriptor == null) { // Unknown Descriptor - Log.i(TAG, "Unknown Descriptor len:" + length + " type:0x" + Log.i(TAG, "Unknown Descriptor len: " + length + " type:0x" + Integer.toHexString(type)); descriptor = new UsbUnknown(length, type); } @@ -135,14 +161,15 @@ public class UsbDescriptorParser { try { descriptor.parseRawDescriptors(stream); - // Its OK to add the invalid descriptor as the postParse() - // routine will mark it as invalid. - mDescriptors.add(descriptor); - // Clean up descriptor.postParse(stream); } catch (Exception ex) { Log.e(TAG, "Exception parsing USB descriptors.", ex); + + // Clean up + descriptor.setStatus(UsbDescriptor.STATUS_PARSE_EXCEPTION); + } finally { + mDescriptors.add(descriptor); } } } @@ -197,7 +224,7 @@ public class UsbDescriptorParser { list.add(descriptor); } } else { - Log.w(TAG, "Unrecognized Interface l:" + descriptor.getLength() + Log.w(TAG, "Unrecognized Interface l: " + descriptor.getLength() + " t:0x" + Integer.toHexString(descriptor.getType())); } } @@ -220,7 +247,7 @@ public class UsbDescriptorParser { list.add(descriptor); } } else { - Log.w(TAG, "Unrecognized Audio Interface l:" + descriptor.getLength() + Log.w(TAG, "Unrecognized Audio Interface l: " + descriptor.getLength() + " t:0x" + Integer.toHexString(descriptor.getType())); } } @@ -251,7 +278,7 @@ public class UsbDescriptorParser { return true; } } else { - Log.w(TAG, "Undefined Audio Class Interface l:" + descriptor.getLength() + Log.w(TAG, "Undefined Audio Class Interface l: " + descriptor.getLength() + " t:0x" + Integer.toHexString(descriptor.getType())); } } @@ -274,8 +301,8 @@ public class UsbDescriptorParser { acDescriptors = getACInterfaceDescriptors(UsbACInterface.ACI_INPUT_TERMINAL, UsbACInterface.AUDIO_AUDIOCONTROL); for (UsbDescriptor descriptor : acDescriptors) { - if (descriptor instanceof UsbACInputTerminal) { - UsbACInputTerminal inDescr = (UsbACInputTerminal) descriptor; + if (descriptor instanceof UsbACTerminal) { + UsbACTerminal inDescr = (UsbACTerminal) descriptor; if (inDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_IN_MIC || inDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_BIDIR_HEADSET || inDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_BIDIR_UNDEFINED @@ -284,7 +311,7 @@ public class UsbDescriptorParser { break; } } else { - Log.w(TAG, "Undefined Audio Input terminal l:" + descriptor.getLength() + Log.w(TAG, "Undefined Audio Input terminal l: " + descriptor.getLength() + " t:0x" + Integer.toHexString(descriptor.getType())); } } @@ -295,8 +322,8 @@ public class UsbDescriptorParser { getACInterfaceDescriptors(UsbACInterface.ACI_OUTPUT_TERMINAL, UsbACInterface.AUDIO_AUDIOCONTROL); for (UsbDescriptor descriptor : acDescriptors) { - if (descriptor instanceof UsbACOutputTerminal) { - UsbACOutputTerminal outDescr = (UsbACOutputTerminal) descriptor; + if (descriptor instanceof UsbACTerminal) { + UsbACTerminal outDescr = (UsbACTerminal) descriptor; if (outDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_OUT_SPEAKER || outDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_OUT_HEADPHONES @@ -305,7 +332,7 @@ public class UsbDescriptorParser { break; } } else { - Log.w(TAG, "Undefined Audio Output terminal l:" + descriptor.getLength() + Log.w(TAG, "Undefined Audio Output terminal l: " + descriptor.getLength() + " t:0x" + Integer.toHexString(descriptor.getType())); } } @@ -328,6 +355,8 @@ public class UsbDescriptorParser { * to count on the peripheral being a headset. */ public boolean isInputHeadset() { + // TEMP + Log.i(TAG, "---- isInputHeadset() prob:" + (getInputHeadsetProbability() * 100f) + "%"); return getInputHeadsetProbability() >= IN_HEADSET_TRIGGER; } @@ -348,8 +377,8 @@ public class UsbDescriptorParser { getACInterfaceDescriptors(UsbACInterface.ACI_OUTPUT_TERMINAL, UsbACInterface.AUDIO_AUDIOCONTROL); for (UsbDescriptor descriptor : acDescriptors) { - if (descriptor instanceof UsbACOutputTerminal) { - UsbACOutputTerminal outDescr = (UsbACOutputTerminal) descriptor; + if (descriptor instanceof UsbACTerminal) { + UsbACTerminal outDescr = (UsbACTerminal) descriptor; if (outDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_OUT_SPEAKER || outDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_OUT_HEADPHONES @@ -358,7 +387,7 @@ public class UsbDescriptorParser { break; } } else { - Log.w(TAG, "Undefined Audio Output terminal l:" + descriptor.getLength() + Log.w(TAG, "Undefined Audio Output terminal l: " + descriptor.getLength() + " t:0x" + Integer.toHexString(descriptor.getType())); } } @@ -381,6 +410,8 @@ public class UsbDescriptorParser { * to count on the peripheral being a headset. */ public boolean isOutputHeadset() { + // TEMP + Log.i(TAG, "---- isOutputHeadset() prob:" + (getOutputHeadsetProbability() * 100f) + "%"); return getOutputHeadsetProbability() >= OUT_HEADSET_TRIGGER; } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java b/services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java index 90848caba852..c8fa69451ac8 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java @@ -15,13 +15,20 @@ */ package com.android.server.usb.descriptors; +import com.android.server.usb.descriptors.report.ReportCanvas; +import com.android.server.usb.descriptors.report.UsbStrings; + /** * @hide * A USB Device Descriptor. * see usb11.pdf section 9.6.1 */ -/* public */ public class UsbDeviceDescriptor extends UsbDescriptor { - private static final String TAG = "Device"; +public final class UsbDeviceDescriptor extends UsbDescriptor { + private static final String TAG = "UsbDeviceDescriptor"; + + public static final int USBSPEC_1_0 = 0x0100; + public static final int USBSPEC_1_1 = 0x0110; + public static final int USBSPEC_2_0 = 0x0200; private int mSpec; // 2:2 bcdUSB 2 BCD USB Specification Number - BCD private byte mDevClass; // 4:1 class code @@ -39,6 +46,7 @@ package com.android.server.usb.descriptors; UsbDeviceDescriptor(int length, byte type) { super(length, type); + mHierarchyLevel = 1; } public int getSpec() { @@ -91,14 +99,14 @@ package com.android.server.usb.descriptors; @Override public int parseRawDescriptors(ByteStream stream) { - mSpec = stream.unpackUsbWord(); + mSpec = stream.unpackUsbShort(); mDevClass = stream.getByte(); mDevSubClass = stream.getByte(); mProtocol = stream.getByte(); mPacketSize = stream.getByte(); - mVendorID = stream.unpackUsbWord(); - mProductID = stream.unpackUsbWord(); - mDeviceRelease = stream.unpackUsbWord(); + mVendorID = stream.unpackUsbShort(); + mProductID = stream.unpackUsbShort(); + mDeviceRelease = stream.unpackUsbShort(); mMfgIndex = stream.getByte(); mProductIndex = stream.getByte(); mSerialNum = stream.getByte(); @@ -106,4 +114,35 @@ package com.android.server.usb.descriptors; return mLength; } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.openList(); + + int spec = getSpec(); + canvas.writeListItem("Spec: " + ReportCanvas.getBCDString(spec)); + + byte devClass = getDevClass(); + String classStr = UsbStrings.getClassName(devClass); + byte devSubClass = getDevSubClass(); + String subClasStr = UsbStrings.getClassName(devSubClass); + canvas.writeListItem("Class " + devClass + ": " + classStr + " Subclass" + + devSubClass + ": " + subClasStr); + canvas.writeListItem("Vendor ID: " + getVendorID() + + " Product ID: " + getProductID() + + " Product Release: " + ReportCanvas.getBCDString(getDeviceRelease())); + + byte mfgIndex = getMfgIndex(); + String manufacturer = + UsbDescriptor.getUsbDescriptorString(canvas.getConnection(), mfgIndex); + byte productIndex = getProductIndex(); + String product = + UsbDescriptor.getUsbDescriptorString(canvas.getConnection(), productIndex); + + canvas.writeListItem("Manufacturer " + mfgIndex + ": " + manufacturer + + " Product " + productIndex + ": " + product); + canvas.closeList(); + } } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java b/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java index def670093e6e..6322fbe8b45b 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java @@ -15,36 +15,38 @@ */ package com.android.server.usb.descriptors; +import com.android.server.usb.descriptors.report.ReportCanvas; + /** * @hide * A Usb Endpoint Descriptor. * see usb11.pdf section 9.6.4 */ public class UsbEndpointDescriptor extends UsbDescriptor { - private static final String TAG = "EndPoint"; + private static final String TAG = "UsbEndpointDescriptor"; - public static final byte MASK_ENDPOINT_ADDRESS = 0b0001111; - public static final byte MASK_ENDPOINT_DIRECTION = (byte) 0b10000000; - public static final byte DIRECTION_OUTPUT = 0x00; - public static final byte DIRECTION_INPUT = (byte) 0x80; + public static final byte MASK_ENDPOINT_ADDRESS = 0b0001111; + public static final byte MASK_ENDPOINT_DIRECTION = (byte) 0b10000000; + public static final byte DIRECTION_OUTPUT = 0x00; + public static final byte DIRECTION_INPUT = (byte) 0x80; public static final byte MASK_ATTRIBS_TRANSTYPE = 0b00000011; - public static final byte TRANSTYPE_CONTROL = 0x00; - public static final byte TRANSTYPE_ISO = 0x01; - public static final byte TRANSTYPE_BULK = 0x02; - public static final byte TRANSTYPE_INTERRUPT = 0x03; - - public static final byte MASK_ATTRIBS_SYNCTYPE = 0b00001100; - public static final byte SYNCTYPE_NONE = 0b00000000; - public static final byte SYNCTYPE_ASYNC = 0b00000100; - public static final byte SYNCTYPE_ADAPTSYNC = 0b00001000; - public static final byte SYNCTYPE_RESERVED = 0b00001100; - - public static final byte MASK_ATTRIBS_USEAGE = 0b00110000; - public static final byte USEAGE_DATA = 0b00000000; - public static final byte USEAGE_FEEDBACK = 0b00010000; - public static final byte USEAGE_EXPLICIT = 0b00100000; - public static final byte USEAGE_RESERVED = 0b00110000; + public static final byte TRANSTYPE_CONTROL = 0x00; + public static final byte TRANSTYPE_ISO = 0x01; + public static final byte TRANSTYPE_BULK = 0x02; + public static final byte TRANSTYPE_INTERRUPT = 0x03; + + public static final byte MASK_ATTRIBS_SYNCTYPE = 0b00001100; + public static final byte SYNCTYPE_NONE = 0b00000000; + public static final byte SYNCTYPE_ASYNC = 0b00000100; + public static final byte SYNCTYPE_ADAPTSYNC = 0b00001000; + public static final byte SYNCTYPE_RESERVED = 0b00001100; + + public static final byte MASK_ATTRIBS_USEAGE = 0b00110000; + public static final byte USEAGE_DATA = 0b00000000; + public static final byte USEAGE_FEEDBACK = 0b00010000; + public static final byte USEAGE_EXPLICIT = 0b00100000; + public static final byte USEAGE_RESERVED = 0b00110000; private byte mEndpointAddress; // 2:1 Endpoint Address // Bits 0..3b Endpoint Number. @@ -76,6 +78,7 @@ public class UsbEndpointDescriptor extends UsbDescriptor { public UsbEndpointDescriptor(int length, byte type) { super(length, type); + mHierarchyLevel = 4; } public byte getEndpointAddress() { @@ -106,7 +109,7 @@ public class UsbEndpointDescriptor extends UsbDescriptor { public int parseRawDescriptors(ByteStream stream) { mEndpointAddress = stream.getByte(); mAttributes = stream.getByte(); - mPacketSize = stream.unpackUsbWord(); + mPacketSize = stream.unpackUsbShort(); mInterval = stream.getByte(); if (mLength == 9) { mRefresh = stream.getByte(); @@ -114,4 +117,76 @@ public class UsbEndpointDescriptor extends UsbDescriptor { } return mLength; } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.openList(); + + byte address = getEndpointAddress(); + canvas.writeListItem("Address: " + + ReportCanvas.getHexString(address & UsbEndpointDescriptor.MASK_ENDPOINT_ADDRESS) + + ((address & UsbEndpointDescriptor.MASK_ENDPOINT_DIRECTION) + == UsbEndpointDescriptor.DIRECTION_OUTPUT ? " [out]" : " [in]")); + + byte attributes = getAttributes(); + canvas.openListItem(); + canvas.write("Attributes: " + ReportCanvas.getHexString(attributes) + " "); + switch (attributes & UsbEndpointDescriptor.MASK_ATTRIBS_TRANSTYPE) { + case UsbEndpointDescriptor.TRANSTYPE_CONTROL: + canvas.write("Control"); + break; + case UsbEndpointDescriptor.TRANSTYPE_ISO: + canvas.write("Iso"); + break; + case UsbEndpointDescriptor.TRANSTYPE_BULK: + canvas.write("Bulk"); + break; + case UsbEndpointDescriptor.TRANSTYPE_INTERRUPT: + canvas.write("Interrupt"); + break; + } + canvas.closeListItem(); + + // These flags are only relevant for ISO transfer type + if ((attributes & UsbEndpointDescriptor.MASK_ATTRIBS_TRANSTYPE) + == UsbEndpointDescriptor.TRANSTYPE_ISO) { + canvas.openListItem(); + canvas.write("Aync: "); + switch (attributes & UsbEndpointDescriptor.MASK_ATTRIBS_SYNCTYPE) { + case UsbEndpointDescriptor.SYNCTYPE_NONE: + canvas.write("NONE"); + break; + case UsbEndpointDescriptor.SYNCTYPE_ASYNC: + canvas.write("ASYNC"); + break; + case UsbEndpointDescriptor.SYNCTYPE_ADAPTSYNC: + canvas.write("ADAPTIVE ASYNC"); + break; + } + canvas.closeListItem(); + + canvas.openListItem(); + canvas.write("Useage: "); + switch (attributes & UsbEndpointDescriptor.MASK_ATTRIBS_USEAGE) { + case UsbEndpointDescriptor.USEAGE_DATA: + canvas.write("DATA"); + break; + case UsbEndpointDescriptor.USEAGE_FEEDBACK: + canvas.write("FEEDBACK"); + break; + case UsbEndpointDescriptor.USEAGE_EXPLICIT: + canvas.write("EXPLICIT FEEDBACK"); + break; + case UsbEndpointDescriptor.USEAGE_RESERVED: + canvas.write("RESERVED"); + break; + } + canvas.closeListItem(); + } + canvas.writeListItem("Package Size: " + getPacketSize()); + canvas.writeListItem("Interval: " + getInterval()); + canvas.closeList(); + } } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbHIDDescriptor.java b/services/usb/java/com/android/server/usb/descriptors/UsbHIDDescriptor.java index 56c07ec9a071..b4cc87e096df 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbHIDDescriptor.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbHIDDescriptor.java @@ -15,13 +15,15 @@ */ package com.android.server.usb.descriptors; +import com.android.server.usb.descriptors.report.ReportCanvas; + /** * @hide * A USB HID (Human Interface Descriptor). * see HID1_11.pdf - 6.2.1 */ -public class UsbHIDDescriptor extends UsbDescriptor { - private static final String TAG = "HID"; +public final class UsbHIDDescriptor extends UsbDescriptor { + private static final String TAG = "UsbHIDDescriptor"; private int mRelease; // 2:2 the HID Class Specification release. private byte mCountryCode; // 4:1 country code of the localized hardware. @@ -35,6 +37,7 @@ public class UsbHIDDescriptor extends UsbDescriptor { public UsbHIDDescriptor(int length, byte type) { super(length, type); + mHierarchyLevel = 3; } public int getRelease() { @@ -59,12 +62,24 @@ public class UsbHIDDescriptor extends UsbDescriptor { @Override public int parseRawDescriptors(ByteStream stream) { - mRelease = stream.unpackUsbWord(); + mRelease = stream.unpackUsbShort(); mCountryCode = stream.getByte(); mNumDescriptors = stream.getByte(); mDescriptorType = stream.getByte(); - mDescriptorLen = stream.unpackUsbWord(); + mDescriptorLen = stream.unpackUsbShort(); return mLength; } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.openList(); + canvas.writeListItem("Spec: " + ReportCanvas.getBCDString(getRelease())); + canvas.writeListItem("Type: " + ReportCanvas.getBCDString(getDescriptorType())); + canvas.writeListItem("" + getNumDescriptors() + " Descriptors Len: " + + getDescriptorLen()); + canvas.closeList(); + } } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbInterfaceAssoc.java b/services/usb/java/com/android/server/usb/descriptors/UsbInterfaceAssoc.java index 4b18a01b1c8b..d680e543693a 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbInterfaceAssoc.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbInterfaceAssoc.java @@ -15,14 +15,16 @@ */ package com.android.server.usb.descriptors; +// import com.android.server.usb.descriptors.report.ReportCanvas; + /** * @hide * A USB Interface Association Descriptor. * found this one here: http://www.usb.org/developers/docs/whitepapers/iadclasscode_r10.pdf * also: https://msdn.microsoft.com/en-us/library/windows/hardware/ff540054(v=vs.85).aspx */ -public class UsbInterfaceAssoc extends UsbDescriptor { - private static final String TAG = "InterfaceAssoc"; +public final class UsbInterfaceAssoc extends UsbDescriptor { + private static final String TAG = "UsbInterfaceAssoc"; private byte mFirstInterface; private byte mInterfaceCount; @@ -70,4 +72,11 @@ public class UsbInterfaceAssoc extends UsbDescriptor { return mLength; } + + // TODO - Report fields +// @Override +// public void report(ReportCanvas canvas) { +// super.report(canvas); +// +// } } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbInterfaceDescriptor.java b/services/usb/java/com/android/server/usb/descriptors/UsbInterfaceDescriptor.java index 21b5e0cbaa1b..4eef6caf5a60 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbInterfaceDescriptor.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbInterfaceDescriptor.java @@ -15,13 +15,16 @@ */ package com.android.server.usb.descriptors; +import com.android.server.usb.descriptors.report.ReportCanvas; +import com.android.server.usb.descriptors.report.UsbStrings; + /** * @hide * A common super-class for all USB Interface Descritor subtypes. * see usb11.pdf section 9.6.3 */ public class UsbInterfaceDescriptor extends UsbDescriptor { - private static final String TAG = "Interface"; + private static final String TAG = "UsbInterfaceDescriptor"; protected byte mInterfaceNumber; // 2:1 Number of Interface protected byte mAlternateSetting; // 3:1 Value used to select alternative setting @@ -33,6 +36,7 @@ public class UsbInterfaceDescriptor extends UsbDescriptor { UsbInterfaceDescriptor(int length, byte type) { super(length, type); + mHierarchyLevel = 3; } @Override @@ -75,4 +79,27 @@ public class UsbInterfaceDescriptor extends UsbDescriptor { public byte getDescrIndex() { return mDescrIndex; } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + byte usbClass = getUsbClass(); + byte usbSubclass = getUsbSubclass(); + byte protocol = getProtocol(); + String className = UsbStrings.getClassName(usbClass); + String subclassName = ""; + if (usbClass == UsbDescriptor.CLASSID_AUDIO) { + subclassName = UsbStrings.getAudioSubclassName(usbSubclass); + } + + canvas.openList(); + canvas.writeListItem("Interface #" + getInterfaceNumber()); + canvas.writeListItem("Class: " + ReportCanvas.getHexString(usbClass) + ": " + className); + canvas.writeListItem("Subclass: " + + ReportCanvas.getHexString(usbSubclass) + ": " + subclassName); + canvas.writeListItem("Protocol: " + protocol + ": " + ReportCanvas.getHexString(protocol)); + canvas.writeListItem("Endpoints: " + getNumEndpoints()); + canvas.closeList(); + } } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbMSMidiHeader.java b/services/usb/java/com/android/server/usb/descriptors/UsbMSMidiHeader.java index 4452b23cb6ae..85a3e6802ff7 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbMSMidiHeader.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbMSMidiHeader.java @@ -15,13 +15,15 @@ */ package com.android.server.usb.descriptors; +import com.android.server.usb.descriptors.report.ReportCanvas; + /** * @hide * An audio class-specific Midi Streaming Interface. * see midi10.pdf section 6.1.2.1 */ -public class UsbMSMidiHeader extends UsbACInterface { - private static final String TAG = "MSMidiHeader"; +public final class UsbMSMidiHeader extends UsbACInterface { + private static final String TAG = "UsbMSMidiHeader"; public UsbMSMidiHeader(int length, byte type, byte subtype, byte subclass) { super(length, type, subtype, subclass); @@ -33,4 +35,13 @@ public class UsbMSMidiHeader extends UsbACInterface { stream.advance(mLength - stream.getReadCount()); return mLength; } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.writeHeader(3, "MS Midi Header: " + ReportCanvas.getHexString(getType()) + + " SubType: " + ReportCanvas.getHexString(getSubclass()) + + " Length: " + getLength()); + } } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbMSMidiInputJack.java b/services/usb/java/com/android/server/usb/descriptors/UsbMSMidiInputJack.java index 2d33ba7727dd..1d5cbf2b5c99 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbMSMidiInputJack.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbMSMidiInputJack.java @@ -15,13 +15,15 @@ */ package com.android.server.usb.descriptors; +import com.android.server.usb.descriptors.report.ReportCanvas; + /** * @hide * An audio class-specific Midi Input Jack Interface. * see midi10.pdf section B.4.3 */ -public class UsbMSMidiInputJack extends UsbACInterface { - private static final String TAG = "MSMidiInputJack"; +public final class UsbMSMidiInputJack extends UsbACInterface { + private static final String TAG = "UsbMSMidiInputJack"; UsbMSMidiInputJack(int length, byte type, byte subtype, byte subclass) { super(length, type, subtype, subclass); @@ -33,4 +35,13 @@ public class UsbMSMidiInputJack extends UsbACInterface { stream.advance(mLength - stream.getReadCount()); return mLength; } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.writeHeader(3, "MS Midi Input Jack: " + ReportCanvas.getHexString(getType()) + + " SubType: " + ReportCanvas.getHexString(getSubclass()) + + " Length: " + getLength()); + } } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbMSMidiOutputJack.java b/services/usb/java/com/android/server/usb/descriptors/UsbMSMidiOutputJack.java index bd2dc11d57df..9f50240a94ca 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbMSMidiOutputJack.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbMSMidiOutputJack.java @@ -15,13 +15,15 @@ */ package com.android.server.usb.descriptors; +import com.android.server.usb.descriptors.report.ReportCanvas; + /** * @hide * An audio class-specific Midi Output Jack Interface. * see midi10.pdf section B.4.4 */ -public class UsbMSMidiOutputJack extends UsbACInterface { - private static final String TAG = "MSMidiOutputJack"; +public final class UsbMSMidiOutputJack extends UsbACInterface { + private static final String TAG = "UsbMSMidiOutputJack"; public UsbMSMidiOutputJack(int length, byte type, byte subtype, byte subclass) { super(length, type, subtype, subclass); @@ -33,4 +35,13 @@ public class UsbMSMidiOutputJack extends UsbACInterface { stream.advance(mLength - stream.getReadCount()); return mLength; } + + @Override + public void report(ReportCanvas canvas) { + super.report(canvas); + + canvas.writeHeader(3, "MS Midi Output Jack: " + ReportCanvas.getHexString(getType()) + + " SubType: " + ReportCanvas.getHexString(getSubclass()) + + " Length: " + getLength()); + } } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbTerminalTypes.java b/services/usb/java/com/android/server/usb/descriptors/UsbTerminalTypes.java index b5214625126a..9bd6cb942888 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbTerminalTypes.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbTerminalTypes.java @@ -20,8 +20,8 @@ package com.android.server.usb.descriptors; * A class for decoding information in Terminal Descriptors. * see termt10.pdf */ -public class UsbTerminalTypes { - private static final String TAG = "TerminalTypes"; +public final class UsbTerminalTypes { + private static final String TAG = "UsbTerminalTypes"; // USB public static final int TERMINAL_USB_STREAMING = 0x0101; diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbUnknown.java b/services/usb/java/com/android/server/usb/descriptors/UsbUnknown.java index a6fe8bba3508..6e6dccf00613 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbUnknown.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbUnknown.java @@ -19,8 +19,8 @@ package com.android.server.usb.descriptors; * @hide * A holder for any unrecognized descriptor encountered in the descriptor stream. */ -public class UsbUnknown extends UsbDescriptor { - static final String TAG = "Unknown"; +public final class UsbUnknown extends UsbDescriptor { + static final String TAG = "UsbUnknown"; public UsbUnknown(int length, byte type) { super(length, type); diff --git a/services/usb/java/com/android/server/usb/descriptors/report/HTMLReportCanvas.java b/services/usb/java/com/android/server/usb/descriptors/report/HTMLReportCanvas.java new file mode 100644 index 000000000000..99ebccade735 --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/report/HTMLReportCanvas.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors.report; + +import android.hardware.usb.UsbDeviceConnection; + +/** + * @hide + * A concrete implementation of ReportCanvas class which generates HTML. + */ +public final class HTMLReportCanvas extends ReportCanvas { + private static final String TAG = "HTMLReportCanvas"; + + private final StringBuilder mStringBuilder; + + /** + * Constructor. Connects HTML output to the provided StringBuilder. + * @param connection The USB connection object used to retrieve strings + * from the USB device. + * @param stringBuilder Generated output gets written into this object. + */ + public HTMLReportCanvas(UsbDeviceConnection connection, StringBuilder stringBuilder) { + super(connection); + + mStringBuilder = stringBuilder; + } + + @Override + public void write(String text) { + mStringBuilder.append(text); + } + + @Override + public void openHeader(int level) { + mStringBuilder.append("<h").append(level).append('>'); + } + + @Override + public void closeHeader(int level) { + mStringBuilder.append("</h").append(level).append('>'); + } + + // we can be cleverer (more clever?) with styles, but this will do for now. + @Override + public void openParagraph(boolean emphasis) { + if (emphasis) { + mStringBuilder.append("<p style=\"color:red\">"); + } else { + mStringBuilder.append("<p>"); + } + } + + @Override + public void closeParagraph() { + mStringBuilder.append("</p>"); + } + + @Override + public void writeParagraph(String text, boolean inRed) { + openParagraph(inRed); + mStringBuilder.append(text); + closeParagraph(); + } + + @Override + public void openList() { + mStringBuilder.append("<ul>"); + } + + @Override + public void closeList() { + mStringBuilder.append("</ul>"); + } + + @Override + public void openListItem() { + mStringBuilder.append("<li>"); + } + + @Override + public void closeListItem() { + mStringBuilder.append("</li>"); + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/report/HTMLReporter.java b/services/usb/java/com/android/server/usb/descriptors/report/HTMLReporter.java deleted file mode 100644 index c98789d880a0..000000000000 --- a/services/usb/java/com/android/server/usb/descriptors/report/HTMLReporter.java +++ /dev/null @@ -1,572 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.server.usb.descriptors.report; - -import android.hardware.usb.UsbDeviceConnection; - -import com.android.server.usb.descriptors.UsbACAudioControlEndpoint; -import com.android.server.usb.descriptors.UsbACAudioStreamEndpoint; -import com.android.server.usb.descriptors.UsbACFeatureUnit; -import com.android.server.usb.descriptors.UsbACHeader; -import com.android.server.usb.descriptors.UsbACInputTerminal; -import com.android.server.usb.descriptors.UsbACInterface; -import com.android.server.usb.descriptors.UsbACMidiEndpoint; -import com.android.server.usb.descriptors.UsbACMixerUnit; -import com.android.server.usb.descriptors.UsbACOutputTerminal; -import com.android.server.usb.descriptors.UsbACSelectorUnit; -import com.android.server.usb.descriptors.UsbACTerminal; -import com.android.server.usb.descriptors.UsbASFormat; -import com.android.server.usb.descriptors.UsbASFormatI; -import com.android.server.usb.descriptors.UsbASFormatII; -import com.android.server.usb.descriptors.UsbASGeneral; -import com.android.server.usb.descriptors.UsbConfigDescriptor; -import com.android.server.usb.descriptors.UsbDescriptor; -import com.android.server.usb.descriptors.UsbDeviceDescriptor; -import com.android.server.usb.descriptors.UsbEndpointDescriptor; -import com.android.server.usb.descriptors.UsbHIDDescriptor; -import com.android.server.usb.descriptors.UsbInterfaceAssoc; -import com.android.server.usb.descriptors.UsbInterfaceDescriptor; -import com.android.server.usb.descriptors.UsbMSMidiHeader; -import com.android.server.usb.descriptors.UsbMSMidiInputJack; -import com.android.server.usb.descriptors.UsbMSMidiOutputJack; -import com.android.server.usb.descriptors.UsbUnknown; - -/** - * Implements the Reporter inteface to provide HTML reporting for UsbDescriptor subclasses. - */ -public class HTMLReporter implements Reporter { - private final StringBuilder mStringBuilder; - private final UsbDeviceConnection mConnection; - - public HTMLReporter(StringBuilder stringBuilder, UsbDeviceConnection connection) { - mStringBuilder = stringBuilder; - mConnection = connection; - } - - /* - * HTML Helpers - */ - private void writeHeader(int level, String text) { - mStringBuilder - .append("<h").append(level).append('>') - .append(text) - .append("</h").append(level).append('>'); - } - - private void openParagraph() { - mStringBuilder.append("<p>"); - } - - private void closeParagraph() { - mStringBuilder.append("</p>"); - } - - private void writeParagraph(String text) { - openParagraph(); - mStringBuilder.append(text); - closeParagraph(); - } - - private void openList() { - mStringBuilder.append("<ul>"); - } - - private void closeList() { - mStringBuilder.append("</ul>"); - } - - private void openListItem() { - mStringBuilder.append("<li>"); - } - - private void closeListItem() { - mStringBuilder.append("</li>"); - } - - private void writeListItem(String text) { - openListItem(); - mStringBuilder.append(text); - closeListItem(); - } - - /* - * Data Formating Helpers - */ - private static String getHexString(byte value) { - return "0x" + Integer.toHexString(((int) value) & 0xFF).toUpperCase(); - } - - private static String getBCDString(int value) { - int major = value >> 8; - int minor = (value >> 4) & 0x0F; - int subminor = value & 0x0F; - - return "" + major + "." + minor + subminor; - } - - private static String getHexString(int value) { - int intValue = value & 0xFFFF; - return "0x" + Integer.toHexString(intValue).toUpperCase(); - } - - private void dumpHexArray(byte[] rawData, StringBuilder builder) { - if (rawData != null) { - // Assume the type and Length and perhaps sub-type have been displayed - openParagraph(); - for (int index = 0; index < rawData.length; index++) { - builder.append(getHexString(rawData[index]) + " "); - } - closeParagraph(); - } - } - - /** - * Decode ACTUAL UsbDescriptor sub classes and call type-specific report methods. - */ - @Override - public void report(UsbDescriptor descriptor) { - if (descriptor instanceof UsbDeviceDescriptor) { - tsReport((UsbDeviceDescriptor) descriptor); - } else if (descriptor instanceof UsbConfigDescriptor) { - tsReport((UsbConfigDescriptor) descriptor); - } else if (descriptor instanceof UsbInterfaceDescriptor) { - tsReport((UsbInterfaceDescriptor) descriptor); - } else if (descriptor instanceof UsbEndpointDescriptor) { - tsReport((UsbEndpointDescriptor) descriptor); - } else if (descriptor instanceof UsbHIDDescriptor) { - tsReport((UsbHIDDescriptor) descriptor); - } else if (descriptor instanceof UsbACAudioControlEndpoint) { - tsReport((UsbACAudioControlEndpoint) descriptor); - } else if (descriptor instanceof UsbACAudioStreamEndpoint) { - tsReport((UsbACAudioStreamEndpoint) descriptor); - } else if (descriptor instanceof UsbACHeader) { - tsReport((UsbACHeader) descriptor); - } else if (descriptor instanceof UsbACFeatureUnit) { - tsReport((UsbACFeatureUnit) descriptor); - } else if (descriptor instanceof UsbACInputTerminal) { - tsReport((UsbACInputTerminal) descriptor); - } else if (descriptor instanceof UsbACOutputTerminal) { - tsReport((UsbACOutputTerminal) descriptor); - } else if (descriptor instanceof UsbACMidiEndpoint) { - tsReport((UsbACMidiEndpoint) descriptor); - } else if (descriptor instanceof UsbACMixerUnit) { - tsReport((UsbACMixerUnit) descriptor); - } else if (descriptor instanceof UsbACSelectorUnit) { - tsReport((UsbACSelectorUnit) descriptor); - } else if (descriptor instanceof UsbASFormatI) { - tsReport((UsbASFormatI) descriptor); - } else if (descriptor instanceof UsbASFormatII) { - tsReport((UsbASFormatII) descriptor); - } else if (descriptor instanceof UsbASFormat) { - tsReport((UsbASFormat) descriptor); - } else if (descriptor instanceof UsbASGeneral) { - tsReport((UsbASGeneral) descriptor); - } else if (descriptor instanceof UsbInterfaceAssoc) { - tsReport((UsbInterfaceAssoc) descriptor); - } else if (descriptor instanceof UsbMSMidiHeader) { - tsReport((UsbMSMidiHeader) descriptor); - } else if (descriptor instanceof UsbMSMidiInputJack) { - tsReport((UsbMSMidiInputJack) descriptor); - } else if (descriptor instanceof UsbMSMidiOutputJack) { - tsReport((UsbMSMidiOutputJack) descriptor); - } else if (descriptor instanceof UsbUnknown) { - tsReport((UsbUnknown) descriptor); - } else if (descriptor instanceof UsbACInterface) { - tsReport((UsbACInterface) descriptor); - } else if (descriptor instanceof UsbDescriptor) { - tsReport((UsbDescriptor) descriptor); - } - } - - // - // Type-specific report() implementations - // - private void tsReport(UsbDescriptor descriptor) { - int length = descriptor.getLength(); - byte type = descriptor.getType(); - int status = descriptor.getStatus(); - - String descTypeStr = UsbStrings.getDescriptorName(type); - writeParagraph(descTypeStr + ":" + type + " l:" + length + " s:" + status); - } - - private void tsReport(UsbDeviceDescriptor descriptor) { - writeHeader(1, "Device len:" + descriptor.getLength()); - openList(); - - int spec = descriptor.getSpec(); - writeListItem("spec:" + getBCDString(spec)); - - byte devClass = descriptor.getDevClass(); - String classStr = UsbStrings.getClassName(devClass); - byte devSubClass = descriptor.getDevSubClass(); - String subClasStr = UsbStrings.getClassName(devSubClass); - writeListItem("class " + devClass + ":" + classStr + " subclass" - + devSubClass + ":" + subClasStr); - writeListItem("vendorID:" + descriptor.getVendorID() - + " prodID:" + descriptor.getProductID() - + " prodRel:" + getBCDString(descriptor.getDeviceRelease())); - - byte mfgIndex = descriptor.getMfgIndex(); - String manufacturer = UsbDescriptor.getUsbDescriptorString(mConnection, mfgIndex); - byte productIndex = descriptor.getProductIndex(); - String product = UsbDescriptor.getUsbDescriptorString(mConnection, productIndex); - - writeListItem("mfg " + mfgIndex + ":" + manufacturer - + " prod " + productIndex + ":" + product); - closeList(); - } - - private void tsReport(UsbConfigDescriptor descriptor) { - writeHeader(2, "Config #" + descriptor.getConfigValue() - + " len:" + descriptor.getLength()); - - openList(); - writeListItem(descriptor.getNumInterfaces() + " interfaces."); - writeListItem("attribs:" + getHexString(descriptor.getAttribs())); - closeList(); - } - - private void tsReport(UsbInterfaceDescriptor descriptor) { - byte usbClass = descriptor.getUsbClass(); - byte usbSubclass = descriptor.getUsbSubclass(); - String descr = UsbStrings.getDescriptorName(descriptor.getType()); - String className = UsbStrings.getClassName(usbClass); - String subclassName = ""; - if (usbClass == UsbDescriptor.CLASSID_AUDIO) { - subclassName = UsbStrings.getAudioSubclassName(usbSubclass); - } - - writeHeader(2, descr + " #" + descriptor.getInterfaceNumber() - + " len:" + descriptor.getLength()); - String descrStr = - UsbDescriptor.getUsbDescriptorString(mConnection, descriptor.getDescrIndex()); - if (descrStr.length() > 0) { - mStringBuilder.append("<br>" + descrStr); - } - openList(); - writeListItem("class " + getHexString(usbClass) + ":" + className - + " subclass " + getHexString(usbSubclass) + ":" + subclassName); - writeListItem("" + descriptor.getNumEndpoints() + " endpoints"); - closeList(); - } - - private void tsReport(UsbEndpointDescriptor descriptor) { - writeHeader(3, "Endpoint " + getHexString(descriptor.getType()) - + " len:" + descriptor.getLength()); - openList(); - - byte address = descriptor.getEndpointAddress(); - writeListItem("address:" - + getHexString(address & UsbEndpointDescriptor.MASK_ENDPOINT_ADDRESS) - + ((address & UsbEndpointDescriptor.MASK_ENDPOINT_DIRECTION) - == UsbEndpointDescriptor.DIRECTION_OUTPUT ? " [out]" : " [in]")); - - byte attributes = descriptor.getAttributes(); - openListItem(); - mStringBuilder.append("attribs:" + getHexString(attributes) + " "); - switch (attributes & UsbEndpointDescriptor.MASK_ATTRIBS_TRANSTYPE) { - case UsbEndpointDescriptor.TRANSTYPE_CONTROL: - mStringBuilder.append("Control"); - break; - case UsbEndpointDescriptor.TRANSTYPE_ISO: - mStringBuilder.append("Iso"); - break; - case UsbEndpointDescriptor.TRANSTYPE_BULK: - mStringBuilder.append("Bulk"); - break; - case UsbEndpointDescriptor.TRANSTYPE_INTERRUPT: - mStringBuilder.append("Interrupt"); - break; - } - closeListItem(); - - // These flags are only relevant for ISO transfer type - if ((attributes & UsbEndpointDescriptor.MASK_ATTRIBS_TRANSTYPE) - == UsbEndpointDescriptor.TRANSTYPE_ISO) { - openListItem(); - mStringBuilder.append("sync:"); - switch (attributes & UsbEndpointDescriptor.MASK_ATTRIBS_SYNCTYPE) { - case UsbEndpointDescriptor.SYNCTYPE_NONE: - mStringBuilder.append("NONE"); - break; - case UsbEndpointDescriptor.SYNCTYPE_ASYNC: - mStringBuilder.append("ASYNC"); - break; - case UsbEndpointDescriptor.SYNCTYPE_ADAPTSYNC: - mStringBuilder.append("ADAPTIVE ASYNC"); - break; - } - closeListItem(); - - openListItem(); - mStringBuilder.append("useage:"); - switch (attributes & UsbEndpointDescriptor.MASK_ATTRIBS_USEAGE) { - case UsbEndpointDescriptor.USEAGE_DATA: - mStringBuilder.append("DATA"); - break; - case UsbEndpointDescriptor.USEAGE_FEEDBACK: - mStringBuilder.append("FEEDBACK"); - break; - case UsbEndpointDescriptor.USEAGE_EXPLICIT: - mStringBuilder.append("EXPLICIT FEEDBACK"); - break; - case UsbEndpointDescriptor.USEAGE_RESERVED: - mStringBuilder.append("RESERVED"); - break; - } - closeListItem(); - } - writeListItem("package size:" + descriptor.getPacketSize()); - writeListItem("interval:" + descriptor.getInterval()); - closeList(); - } - - private void tsReport(UsbHIDDescriptor descriptor) { - String descr = UsbStrings.getDescriptorName(descriptor.getType()); - writeHeader(2, descr + " len:" + descriptor.getLength()); - openList(); - writeListItem("spec:" + getBCDString(descriptor.getRelease())); - writeListItem("type:" + getBCDString(descriptor.getDescriptorType())); - writeListItem("descriptor.getNumDescriptors() descriptors len:" - + descriptor.getDescriptorLen()); - closeList(); - } - - private void tsReport(UsbACAudioControlEndpoint descriptor) { - writeHeader(3, "AC Audio Control Endpoint:" + getHexString(descriptor.getType()) - + " length:" + descriptor.getLength()); - } - - private void tsReport(UsbACAudioStreamEndpoint descriptor) { - writeHeader(3, "AC Audio Streaming Endpoint:" - + getHexString(descriptor.getType()) - + " length:" + descriptor.getLength()); - } - - private void tsReport(UsbACHeader descriptor) { - tsReport((UsbACInterface) descriptor); - - openList(); - writeListItem("spec:" + getBCDString(descriptor.getADCRelease())); - int numInterfaces = descriptor.getNumInterfaces(); - writeListItem("" + numInterfaces + " interfaces"); - if (numInterfaces > 0) { - openListItem(); - mStringBuilder.append("["); - byte[] interfaceNums = descriptor.getInterfaceNums(); - if (numInterfaces != 0 && interfaceNums != null) { - for (int index = 0; index < numInterfaces; index++) { - mStringBuilder.append("" + interfaceNums[index]); - if (index < numInterfaces - 1) { - mStringBuilder.append(" "); - } - } - } - mStringBuilder.append("]"); - closeListItem(); - } - writeListItem("controls:" + getHexString(descriptor.getControls())); - closeList(); - } - - private void tsReport(UsbACFeatureUnit descriptor) { - tsReport((UsbACInterface) descriptor); - } - - private void tsReport(UsbACInterface descriptor) { - String subClassName = - descriptor.getSubclass() == UsbDescriptor.AUDIO_AUDIOCONTROL - ? "AC Control" - : "AC Streaming"; - byte subtype = descriptor.getSubtype(); - String subTypeStr = UsbStrings.getACControlInterfaceName(subtype); - writeHeader(4, subClassName + " - " + getHexString(subtype) - + ":" + subTypeStr + " len:" + descriptor.getLength()); - } - - private void tsReport(UsbACTerminal descriptor) { - tsReport((UsbACInterface) descriptor); - } - - private void tsReport(UsbACInputTerminal descriptor) { - tsReport((UsbACTerminal) descriptor); - - openList(); - writeListItem("ID:" + getHexString(descriptor.getTerminalID())); - int terminalType = descriptor.getTerminalType(); - writeListItem("Type:<b>" + getHexString(terminalType) + ":" - + UsbStrings.getTerminalName(terminalType) + "</b>"); - writeListItem("AssocTerminal:" + getHexString(descriptor.getAssocTerminal())); - writeListItem("" + descriptor.getNrChannels() + " chans. config:" - + getHexString(descriptor.getChannelConfig())); - closeList(); - } - - private void tsReport(UsbACOutputTerminal descriptor) { - tsReport((UsbACTerminal) descriptor); - - openList(); - writeListItem("ID:" + getHexString(descriptor.getTerminalID())); - int terminalType = descriptor.getTerminalType(); - writeListItem("Type:<b>" + getHexString(terminalType) + ":" - + UsbStrings.getTerminalName(terminalType) + "</b>"); - writeListItem("AssocTerminal:" + getHexString(descriptor.getAssocTerminal())); - writeListItem("Source:" + getHexString(descriptor.getSourceID())); - closeList(); - } - - private void tsReport(UsbACMidiEndpoint descriptor) { - writeHeader(3, "AC Midi Endpoint:" + getHexString(descriptor.getType()) - + " length:" + descriptor.getLength()); - openList(); - writeListItem("" + descriptor.getNumJacks() + " jacks."); - closeList(); - } - - private void tsReport(UsbACMixerUnit descriptor) { - tsReport((UsbACInterface) descriptor); - openList(); - - writeListItem("Unit ID:" + getHexString(descriptor.getUnitID())); - byte numInputs = descriptor.getNumInputs(); - byte[] inputIDs = descriptor.getInputIDs(); - openListItem(); - mStringBuilder.append("Num Inputs:" + numInputs + " ["); - for (int input = 0; input < numInputs; input++) { - mStringBuilder.append("" + getHexString(inputIDs[input])); - if (input < numInputs - 1) { - mStringBuilder.append(" "); - } - } - mStringBuilder.append("]"); - closeListItem(); - - writeListItem("Num Outputs:" + descriptor.getNumOutputs()); - writeListItem("Chan Config:" + getHexString(descriptor.getChannelConfig())); - - byte[] controls = descriptor.getControls(); - openListItem(); - mStringBuilder.append("controls:" + controls.length + " ["); - for (int ctrl = 0; ctrl < controls.length; ctrl++) { - mStringBuilder.append("" + controls[ctrl]); - if (ctrl < controls.length - 1) { - mStringBuilder.append(" "); - } - } - mStringBuilder.append("]"); - closeListItem(); - closeList(); - // byte mChanNameID; // First channel name string descriptor ID - // byte mNameID; // string descriptor ID of mixer name - } - - private void tsReport(UsbACSelectorUnit descriptor) { - tsReport((UsbACInterface) descriptor); - } - - private void tsReport(UsbASFormat descriptor) { - writeHeader(4, "AC Streaming Format " - + (descriptor.getFormatType() == UsbASFormat.FORMAT_TYPE_I ? "I" : "II") - + " - " + getHexString(descriptor.getSubtype()) + ":" - + " len:" + descriptor.getLength()); - } - - private void tsReport(UsbASFormatI descriptor) { - tsReport((UsbASFormat) descriptor); - openList(); - writeListItem("chans:" + descriptor.getNumChannels()); - writeListItem("subframe size:" + descriptor.getSubframeSize()); - writeListItem("bit resolution:" + descriptor.getBitResolution()); - byte sampleFreqType = descriptor.getSampleFreqType(); - int[] sampleRates = descriptor.getSampleRates(); - writeListItem("sample freq type:" + sampleFreqType); - if (sampleFreqType == 0) { - openList(); - writeListItem("min:" + sampleRates[0]); - writeListItem("max:" + sampleRates[1]); - closeList(); - } else { - openList(); - for (int index = 0; index < sampleFreqType; index++) { - writeListItem("" + sampleRates[index]); - } - closeList(); - } - closeList(); - } - - private void tsReport(UsbASFormatII descriptor) { - tsReport((UsbASFormat) descriptor); - openList(); - writeListItem("max bit rate:" + descriptor.getMaxBitRate()); - writeListItem("samples per frame:" + descriptor.getMaxBitRate()); - byte sampleFreqType = descriptor.getSamFreqType(); - int[] sampleRates = descriptor.getSampleRates(); - writeListItem("sample freq type:" + sampleFreqType); - if (sampleFreqType == 0) { - openList(); - writeListItem("min:" + sampleRates[0]); - writeListItem("max:" + sampleRates[1]); - closeList(); - } else { - openList(); - for (int index = 0; index < sampleFreqType; index++) { - writeListItem("" + sampleRates[index]); - } - closeList(); - } - - closeList(); - } - - private void tsReport(UsbASGeneral descriptor) { - tsReport((UsbACInterface) descriptor); - openList(); - int formatTag = descriptor.getFormatTag(); - writeListItem("fmt:" + UsbStrings.getAudioFormatName(formatTag) + " - " - + getHexString(formatTag)); - closeList(); - } - - private void tsReport(UsbInterfaceAssoc descriptor) { - tsReport((UsbDescriptor) descriptor); - } - - private void tsReport(UsbMSMidiHeader descriptor) { - writeHeader(3, "MS Midi Header:" + getHexString(descriptor.getType()) - + " subType:" + getHexString(descriptor.getSubclass()) - + " length:" + descriptor.getSubclass()); - } - - private void tsReport(UsbMSMidiInputJack descriptor) { - writeHeader(3, "MS Midi Input Jack:" + getHexString(descriptor.getType()) - + " subType:" + getHexString(descriptor.getSubclass()) - + " length:" + descriptor.getSubclass()); - } - - private void tsReport(UsbMSMidiOutputJack descriptor) { - writeHeader(3, "MS Midi Output Jack:" + getHexString(descriptor.getType()) - + " subType:" + getHexString(descriptor.getSubclass()) - + " length:" + descriptor.getSubclass()); - } - - private void tsReport(UsbUnknown descriptor) { - writeParagraph("<i><b>Unknown Descriptor " + getHexString(descriptor.getType()) - + " len:" + descriptor.getLength() + "</b></i>"); - dumpHexArray(descriptor.getRawData(), mStringBuilder); - } -} diff --git a/services/usb/java/com/android/server/usb/descriptors/report/ReportCanvas.java b/services/usb/java/com/android/server/usb/descriptors/report/ReportCanvas.java new file mode 100644 index 000000000000..9e0adf55d87b --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/report/ReportCanvas.java @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors.report; + +import android.hardware.usb.UsbDeviceConnection; + +/** + * @hide + * Defines a class for generating report data in a variety of potential formats. + */ +public abstract class ReportCanvas { + private static final String TAG = "ReportCanvas"; + + private final UsbDeviceConnection mConnection; + + /** + * Constructor. + * @param connection The USB connection object used to retrieve strings + * from the USB device. + */ + public ReportCanvas(UsbDeviceConnection connection) { + mConnection = connection; + } + + /** + * @returns the UsbDeviceConnection member (mConnection). + */ + public UsbDeviceConnection getConnection() { + return mConnection; + } + + /** + * Writes a plain string to the output. + */ + public abstract void write(String text); + + /** + * Opens a "header" formatted section in the output. + * @param level Specifies the logical level of the header. + */ + public abstract void openHeader(int level); + + /** + * Closes a "header" formatted section in the output. + * @param level Specifies the logical level of the header. + */ + public abstract void closeHeader(int level); + + /** + * Writes a "header" formatted string to the output. + * @param level Specifies the logical level of the header. + * @param text Specifies the text to display in the header. + */ + public void writeHeader(int level, String text) { + openHeader(level); + write(text); + closeHeader(level); + } + + /** + * Opens a paragraph construct in the output. + * @param emphasis Specifies whether the text in the paragraph should + * be displayed with "emphasis" formatting. + */ + public abstract void openParagraph(boolean emphasis); + + /** + * Closes a paragraph construct in the output. + */ + public abstract void closeParagraph(); + + /** + * Writes a paragraph construct to the output. + * @param text The text to display with "paragraph" formatting. + * @param emphasis Specifies whether the text in the paragraph should + * be displayed with "emphasis" formatting. + */ + public abstract void writeParagraph(String text, boolean emphasis); + + /** + * Opens a "list" formatted section in the output. + */ + public abstract void openList(); + + /** + * Closes a "list" formatted section in the output. + */ + public abstract void closeList(); + + /** + * Opens a "list item" formatted section in the output. + */ + public abstract void openListItem(); + + /** + * Closes a "list item" formatted section in the output. + */ + public abstract void closeListItem(); + + /** + * Writes a "list item" formatted section in the output. + * @param text Specifies the text of the list item. + */ + public void writeListItem(String text) { + openListItem(); + write(text); + closeListItem(); + } + + /* + * Data Formating Helpers + */ + /** + * Generates a hex representation of the specified byte value. + * @param value The value to format. + */ + //TODO Look into renaming the "getHexString()" functions to be more + // representative of the types they handle. + public static String getHexString(byte value) { + return "0x" + Integer.toHexString(((int) value) & 0xFF).toUpperCase(); + } + + /** + * Generates a string representing a USB Binary-Coded Decimal value. + * @param valueBCD The value to format. + */ + public static String getBCDString(int valueBCD) { + int major = (valueBCD >> 8) & 0x0F; + int minor = (valueBCD >> 4) & 0x0F; + int subminor = valueBCD & 0x0F; + + return "" + major + "." + minor + subminor; + } + + /** + * Generates a hex representation of the specified 16-bit integer value. + * @param value The value to format. + */ + //TODO Look into renaming the "getHexString()" functions to be more + // representative of the types they handle. + public static String getHexString(int value) { + int intValue = value & 0xFFFF; + return "0x" + Integer.toHexString(intValue).toUpperCase(); + } + + /** + * Writes out the specified byte array to the provided StringBuilder. + * @param rawData The byte values. + * @param builder The StringBuilder to write text into. + */ + public void dumpHexArray(byte[] rawData, StringBuilder builder) { + if (rawData != null) { + // Assume the type and Length and perhaps sub-type have been displayed + openParagraph(false); + for (int index = 0; index < rawData.length; index++) { + builder.append(getHexString(rawData[index]) + " "); + } + closeParagraph(); + } + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/report/Reporter.java b/services/usb/java/com/android/server/usb/descriptors/report/Reporter.java deleted file mode 100644 index 2944c10796f6..000000000000 --- a/services/usb/java/com/android/server/usb/descriptors/report/Reporter.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.server.usb.descriptors.report; - -import com.android.server.usb.descriptors.UsbDescriptor; - -/** - * Declares the Reporter interface to provide HTML reporting for UsbDescriptor (sub)classes. - * - * NOTE: It is the responsibility of the implementor of this interface to correctly - * interpret/decode the SPECIFIC UsbDescriptor subclass (perhaps with 'instanceof') that is - * passed and handle that in the appropriate manner. This appears to be a - * not very object-oriented approach, and that is true. This approach DOES however move the - * complexity and 'plumbing' of reporting into the Reporter implementation and avoids needing - * a (trivial) type-specific call to 'report()' in each UsbDescriptor (sub)class, instead - * having just one in the top-level UsbDescriptor class. It also removes the need to add new - * type-specific 'report()' methods to be added to Reporter interface whenever a - * new UsbDescriptor subclass is defined. This seems like a pretty good trade-off. - * - * See HTMLReporter.java in this package for an example of type decoding. - */ -public interface Reporter { - /** - * Generate report for this UsbDescriptor descriptor - */ - void report(UsbDescriptor descriptor); -} diff --git a/services/usb/java/com/android/server/usb/descriptors/report/Reporting.java b/services/usb/java/com/android/server/usb/descriptors/report/Reporting.java index c13111b3e81c..be7c12e4a521 100644 --- a/services/usb/java/com/android/server/usb/descriptors/report/Reporting.java +++ b/services/usb/java/com/android/server/usb/descriptors/report/Reporting.java @@ -16,12 +16,16 @@ package com.android.server.usb.descriptors.report; /** - * Declares the interface for classes that provide reporting functionality. - * (This is the double-indirection aspect of the "Visitor" pattern. + * @hide */ public interface Reporting { /** - * Declares the report method that UsbDescriptor subclasses call. + * TBD */ - void report(Reporter reporter); + void report(ReportCanvas canvas); + + /** + * TBD + */ + void shortReport(ReportCanvas canvas); } diff --git a/services/usb/java/com/android/server/usb/descriptors/report/TextReportCanvas.java b/services/usb/java/com/android/server/usb/descriptors/report/TextReportCanvas.java new file mode 100644 index 000000000000..33746ba82bc6 --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/report/TextReportCanvas.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors.report; + +import android.hardware.usb.UsbDeviceConnection; + +/** + * @hide + * A concrete implementation of ReportCanvas class which generates "Plain Text" output. + */ +public final class TextReportCanvas extends ReportCanvas { + private static final String TAG = "TextReportCanvas"; + + private final StringBuilder mStringBuilder; + private int mListIndent; + private static final int LIST_INDENT_AMNT = 2; + + /** + * Constructor. Connects plain-text output to the provided StringBuilder. + * @param connection The USB connection object used to retrieve strings + * from the USB device. + * @param stringBuilder Generated output gets written into this object. + */ + public TextReportCanvas(UsbDeviceConnection connection, StringBuilder stringBuilder) { + super(connection); + + mStringBuilder = stringBuilder; + } + + @Override + public void write(String text) { + mStringBuilder.append(text); + } + + @Override + public void openHeader(int level) { + mStringBuilder.append("[" + level + " - "); + } + + @Override + public void closeHeader(int level) { + mStringBuilder.append("]\n"); + } + + @Override + public void openParagraph(boolean inRed) { + } + + @Override + public void closeParagraph() { + mStringBuilder.append("\n"); + } + + @Override + public void writeParagraph(String text, boolean inRed) { + openParagraph(inRed); + if (inRed) { + mStringBuilder.append("*" + text + "*"); + } else { + mStringBuilder.append(text); + } + closeParagraph(); + } + + private void writeListIndent() { + for (int space = 0; space < mListIndent; space++) { + mStringBuilder.append(" "); + } + } + + @Override + public void openList() { + mListIndent += LIST_INDENT_AMNT; + writeListIndent(); + mStringBuilder.append("---->\n"); + } + + @Override + public void closeList() { + writeListIndent(); + mListIndent -= LIST_INDENT_AMNT; + mStringBuilder.append("<----\n"); + } + + @Override + public void openListItem() { + writeListIndent(); + mStringBuilder.append(" - "); + } + + @Override + public void closeListItem() { + mStringBuilder.append("\n"); + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/report/UsbStrings.java b/services/usb/java/com/android/server/usb/descriptors/report/UsbStrings.java index 0461150abd27..ff58a2672b3f 100644 --- a/services/usb/java/com/android/server/usb/descriptors/report/UsbStrings.java +++ b/services/usb/java/com/android/server/usb/descriptors/report/UsbStrings.java @@ -16,6 +16,7 @@ package com.android.server.usb.descriptors.report; import com.android.server.usb.descriptors.UsbACInterface; +import com.android.server.usb.descriptors.UsbASFormat; import com.android.server.usb.descriptors.UsbDescriptor; import com.android.server.usb.descriptors.UsbTerminalTypes; @@ -25,7 +26,7 @@ import java.util.HashMap; * @hide * A class to provide human-readable strings for various USB constants. */ -public class UsbStrings { +public final class UsbStrings { private static final String TAG = "UsbStrings"; private static HashMap<Byte, String> sDescriptorNames; @@ -35,6 +36,7 @@ public class UsbStrings { private static HashMap<Byte, String> sAudioSubclassNames; private static HashMap<Integer, String> sAudioEncodingNames; private static HashMap<Integer, String> sTerminalNames; + private static HashMap<Integer, String> sFormatNames; private static void initDescriptorNames() { sDescriptorNames = new HashMap<Byte, String>(); @@ -70,6 +72,11 @@ public class UsbStrings { sACControlInterfaceNames.put(UsbACInterface.ACI_FEATURE_UNIT, "Feature Unit"); sACControlInterfaceNames.put(UsbACInterface.ACI_PROCESSING_UNIT, "Processing Unit"); sACControlInterfaceNames.put(UsbACInterface.ACI_EXTENSION_UNIT, "Extension Unit"); + sACControlInterfaceNames.put(UsbACInterface.ACI_CLOCK_SOURCE, "Clock Source"); + sACControlInterfaceNames.put(UsbACInterface.ACI_CLOCK_SELECTOR, "Clock Selector"); + sACControlInterfaceNames.put(UsbACInterface.ACI_CLOCK_MULTIPLIER, "Clock Multiplier"); + sACControlInterfaceNames.put(UsbACInterface.ACI_SAMPLE_RATE_CONVERTER, + "Sample Rate Converter"); } private static void initACStreamingInterfaceNames() { @@ -213,6 +220,29 @@ public class UsbStrings { ? name : "Unknown Terminal Type 0x" + Integer.toHexString(terminalType); } + + private static void initFormatNames() { + sFormatNames = new HashMap<Integer, String>(); + + sFormatNames.put((int) UsbASFormat.FORMAT_TYPE_I, "FORMAT_TYPE_I"); + sFormatNames.put((int) UsbASFormat.FORMAT_TYPE_II, "FORMAT_TYPE_II"); + sFormatNames.put((int) UsbASFormat.FORMAT_TYPE_III, "FORMAT_TYPE_III"); + sFormatNames.put((int) UsbASFormat.FORMAT_TYPE_IV, "FORMAT_TYPE_IV"); + sFormatNames.put((int) UsbASFormat.EXT_FORMAT_TYPE_I, "EXT_FORMAT_TYPE_I"); + sFormatNames.put((int) UsbASFormat.EXT_FORMAT_TYPE_II, "EXT_FORMAT_TYPE_II"); + sFormatNames.put((int) UsbASFormat.EXT_FORMAT_TYPE_III, "EXT_FORMAT_TYPE_III"); + } + + /** + * Retrieves the name for the specified format (encoding) type ID. + */ + public static String getFormatName(int format) { + String name = sFormatNames.get(format); + return name != null + ? name + : "Unknown Format Type 0x" + Integer.toHexString(format); + } + /** * Initializes string tables. */ @@ -224,10 +254,11 @@ public class UsbStrings { initAudioSubclassNames(); initAudioEncodingNames(); initTerminalNames(); + initFormatNames(); } /** - * Initializes string tables. + * Deinitializes string tables. */ public static void releaseUsbStrings() { sDescriptorNames = null; @@ -309,4 +340,11 @@ public class UsbStrings { : "Unknown Format (encoding) ID [0x" + Integer.toHexString(formatID) + ":" + formatID + "]"; } + + /** + * Retrieves the name for the specified USB audio interface subclass ID. + */ + public static String getACInterfaceSubclassName(byte subClassID) { + return subClassID == UsbDescriptor.AUDIO_AUDIOCONTROL ? "AC Control" : "AC Streaming"; + } } diff --git a/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsACInterfaceNode.java b/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsACInterfaceNode.java new file mode 100644 index 000000000000..49caca5c8dd0 --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsACInterfaceNode.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors.tree; + +import com.android.server.usb.descriptors.UsbACInterface; +import com.android.server.usb.descriptors.report.ReportCanvas; + +/** + * @hide + * A tree node containing some sort-of Audio Class Descriptor. + */ +public final class UsbDescriptorsACInterfaceNode extends UsbDescriptorsTreeNode { + private static final String TAG = "UsbDescriptorsACInterfaceNode"; + + private final UsbACInterface mACInterface; + + /** + * Constructor. + * @param acInterface The Audio Class Inteface object wrapped by this tree node. + */ + public UsbDescriptorsACInterfaceNode(UsbACInterface acInterface) { + mACInterface = acInterface; + } + + @Override + public void report(ReportCanvas canvas) { + canvas.openListItem(); + canvas.writeParagraph("AC Interface type:0x" + + Integer.toHexString(mACInterface.getSubtype()), false); + mACInterface.report(canvas); + canvas.closeListItem(); + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsConfigNode.java b/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsConfigNode.java new file mode 100644 index 000000000000..64f9496ae7c8 --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsConfigNode.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors.tree; + +import com.android.server.usb.descriptors.UsbConfigDescriptor; +import com.android.server.usb.descriptors.report.ReportCanvas; + +import java.util.ArrayList; + +/** + * @hide + * Represents a configuration in the descriptors tree. + */ +public final class UsbDescriptorsConfigNode extends UsbDescriptorsTreeNode { + private static final String TAG = "UsbDescriptorsConfigNode"; + + private final UsbConfigDescriptor mConfigDescriptor; + + private final ArrayList<UsbDescriptorsInterfaceNode> mInterfaceNodes = new ArrayList<>(); + + /** + * Constructor. + * @param configDescriptor The Config Descriptor object wrapped by this tree node. + */ + public UsbDescriptorsConfigNode(UsbConfigDescriptor configDescriptor) { + mConfigDescriptor = configDescriptor; + } + + /** + * Adds the inteface node logical contained in this configuration. + * @param interfaceNode The inteface treenode to assocate with this configuration. + */ + public void addInterfaceNode(UsbDescriptorsInterfaceNode interfaceNode) { + mInterfaceNodes.add(interfaceNode); + } + + @Override + public void report(ReportCanvas canvas) { + mConfigDescriptor.report(canvas); + + canvas.openList(); + + // Interfaces + for (UsbDescriptorsInterfaceNode node : mInterfaceNodes) { + node.report(canvas); + } + + canvas.closeList(); + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsDeviceNode.java b/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsDeviceNode.java new file mode 100644 index 000000000000..898a06ecdafc --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsDeviceNode.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors.tree; + +import com.android.server.usb.descriptors.UsbDeviceDescriptor; +import com.android.server.usb.descriptors.report.ReportCanvas; + +import java.util.ArrayList; + +/** + * @hide + * A class to contain THE device descriptor at the root of the tree. + */ +public final class UsbDescriptorsDeviceNode extends UsbDescriptorsTreeNode { + private static final String TAG = "UsbDescriptorsDeviceNode"; + + private final UsbDeviceDescriptor mDeviceDescriptor; + + private final ArrayList<UsbDescriptorsConfigNode> mConfigNodes = new ArrayList<>(); + + /** + * Constructor. + * @param deviceDescriptor The Device Descriptor object wrapped by this tree node. + */ + public UsbDescriptorsDeviceNode(UsbDeviceDescriptor deviceDescriptor) { + mDeviceDescriptor = deviceDescriptor; + } + + /** + * Adds a Configuration node to the assocated device node. + */ + public void addConfigDescriptorNode(UsbDescriptorsConfigNode configNode) { + mConfigNodes.add(configNode); + } + + @Override + public void report(ReportCanvas canvas) { + mDeviceDescriptor.report(canvas); + for (UsbDescriptorsConfigNode node : mConfigNodes) { + node.report(canvas); + } + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsEndpointNode.java b/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsEndpointNode.java new file mode 100644 index 000000000000..72864172147e --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsEndpointNode.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors.tree; + +import com.android.server.usb.descriptors.UsbEndpointDescriptor; +import com.android.server.usb.descriptors.report.ReportCanvas; + +/** + * @hide + * Represents an endpoint in the descriptors tree. + */ +public final class UsbDescriptorsEndpointNode extends UsbDescriptorsTreeNode { + private static final String TAG = "UsbDescriptorsEndpointNode"; + + private final UsbEndpointDescriptor mEndpointDescriptor; + + /** + * Constructor. + * @param endpointDescriptor The Device Descriptor object wrapped by this tree node. + */ + public UsbDescriptorsEndpointNode(UsbEndpointDescriptor endpointDescriptor) { + mEndpointDescriptor = endpointDescriptor; + } + + @Override + public void report(ReportCanvas canvas) { + mEndpointDescriptor.report(canvas); + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsInterfaceNode.java b/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsInterfaceNode.java new file mode 100644 index 000000000000..d49d88db9882 --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsInterfaceNode.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors.tree; + +import com.android.server.usb.descriptors.UsbInterfaceDescriptor; +import com.android.server.usb.descriptors.report.ReportCanvas; + +import java.util.ArrayList; + +/** + * @hide + * Represents an interface in the descriptors tree. + */ +public final class UsbDescriptorsInterfaceNode extends UsbDescriptorsTreeNode { + private static final String TAG = "UsbDescriptorsInterfaceNode"; + + private final UsbInterfaceDescriptor mInterfaceDescriptor; + + private final ArrayList<UsbDescriptorsEndpointNode> mEndpointNodes = new ArrayList<>(); + private final ArrayList<UsbDescriptorsACInterfaceNode> mACInterfaceNodes = new ArrayList<>(); + + /** + * Constructor. + * @param interfaceDescriptor The Interface Descriptor object wrapped by this tree node. + */ + public UsbDescriptorsInterfaceNode(UsbInterfaceDescriptor interfaceDescriptor) { + mInterfaceDescriptor = interfaceDescriptor; + } + + /** + * Adds an endpoint descriptor as a child of this interface node. + * @param endpointNode The endpoint descriptor node to add to this interface node. + */ + public void addEndpointNode(UsbDescriptorsEndpointNode endpointNode) { + mEndpointNodes.add(endpointNode); + } + + /** + * Adds an Audio-class interface descriptor as a child of this interface node. + * @param acInterfaceNode The audio-class descriptor node to add to this interface node. + */ + public void addACInterfaceNode(UsbDescriptorsACInterfaceNode acInterfaceNode) { + mACInterfaceNodes.add(acInterfaceNode); + } + + @Override + public void report(ReportCanvas canvas) { + mInterfaceDescriptor.report(canvas); + + // Audio Class Interfaces + if (mACInterfaceNodes.size() > 0) { + canvas.writeParagraph("Audio Class Interfaces", false); + canvas.openList(); + for (UsbDescriptorsACInterfaceNode node : mACInterfaceNodes) { + node.report(canvas); + } + canvas.closeList(); + } + + // Endpoints + if (mEndpointNodes.size() > 0) { + canvas.writeParagraph("Endpoints", false); + canvas.openList(); + for (UsbDescriptorsEndpointNode node : mEndpointNodes) { + node.report(canvas); + } + canvas.closeList(); + } + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsTree.java b/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsTree.java new file mode 100644 index 000000000000..1aa30fa94f42 --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsTree.java @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors.tree; + +import com.android.server.usb.descriptors.UsbACInterface; +import com.android.server.usb.descriptors.UsbConfigDescriptor; +import com.android.server.usb.descriptors.UsbDescriptor; +import com.android.server.usb.descriptors.UsbDescriptorParser; +import com.android.server.usb.descriptors.UsbDeviceDescriptor; +import com.android.server.usb.descriptors.UsbEndpointDescriptor; +import com.android.server.usb.descriptors.UsbInterfaceDescriptor; +import com.android.server.usb.descriptors.report.ReportCanvas; + +import java.util.ArrayList; + +/* + * The general layout of the tree looks like this, though no guarentee about + * ordering of descriptors beyond the Device -> Config -> Interface. + * + * Device Descriptor + * +- Config Descriptor + * +- Interface Descriptor + * | +- Audio Class Interface + * | +- Audio Class Interface + * | +- Audio Class Interface + * | +- Endpoint Descriptor + * | +- Endpoint Descriptor + * +- Interface Descriptor + * +- Endpoint Descriptor + */ +/** + * @hide + * + * A class which builds a tree representation from the results of a (linear) + * parse of USB descriptors. + * + * @see {@link com.android.server.usb.descriptors.UsbDescriptorsParser UsbDescriptorsParser} + */ +public final class UsbDescriptorsTree { + private static final String TAG = "UsbDescriptorsTree"; + + private UsbDescriptorsDeviceNode mDeviceNode; + private UsbDescriptorsConfigNode mConfigNode; // being parsed + private UsbDescriptorsInterfaceNode mInterfaceNode; // being parsed + + /** + * Adds THE device descriptor as the root of the tree. + */ + private void addDeviceDescriptor(UsbDeviceDescriptor deviceDescriptor) { + mDeviceNode = new UsbDescriptorsDeviceNode(deviceDescriptor); + } + + /** + * Adds A config descriptor to the tree. + */ + private void addConfigDescriptor(UsbConfigDescriptor configDescriptor) { + mConfigNode = new UsbDescriptorsConfigNode(configDescriptor); + mDeviceNode.addConfigDescriptorNode(mConfigNode); + } + + /** + * Adds AN interface descriptor to the current configuration in the tree. + */ + private void addInterfaceDescriptor(UsbInterfaceDescriptor interfaceDescriptor) { + mInterfaceNode = new UsbDescriptorsInterfaceNode(interfaceDescriptor); + mConfigNode.addInterfaceNode(mInterfaceNode); + } + + /** + * Adds an endpoint descriptor to the current interface in the tree. + */ + private void addEndpointDescriptor(UsbEndpointDescriptor endpointDescriptor) { + mInterfaceNode.addEndpointNode(new UsbDescriptorsEndpointNode(endpointDescriptor)); + } + + /** + * Adds an audio-class interface descriptor to the current interface in the tree. + */ + private void addACInterface(UsbACInterface acInterface) { + mInterfaceNode.addACInterfaceNode(new UsbDescriptorsACInterfaceNode(acInterface)); + } + + /** + * Parses the linear descriptor list contained in the parser argument, into a tree + * representation corresponding to the logical structure of the USB descriptors. + */ + public void parse(UsbDescriptorParser parser) { + + ArrayList<UsbDescriptor> descriptors = parser.getDescriptors(); + + for (int descrIndex = 0; descrIndex < descriptors.size(); descrIndex++) { + UsbDescriptor descriptor = descriptors.get(descrIndex); + switch (descriptor.getType()) { + // + // Basic Descriptors + // + case UsbDescriptor.DESCRIPTORTYPE_DEVICE: + addDeviceDescriptor((UsbDeviceDescriptor) descriptor); + break; + + case UsbDescriptor.DESCRIPTORTYPE_CONFIG: + addConfigDescriptor((UsbConfigDescriptor) descriptor); + break; + + case UsbDescriptor.DESCRIPTORTYPE_INTERFACE: + addInterfaceDescriptor((UsbInterfaceDescriptor) descriptor); + break; + + case UsbDescriptor.DESCRIPTORTYPE_ENDPOINT: + addEndpointDescriptor((UsbEndpointDescriptor) descriptor); + break; + + // + // Audio Class Descriptors + // + case UsbDescriptor.DESCRIPTORTYPE_AUDIO_INTERFACE: + addACInterface((UsbACInterface) descriptor); + break; + + case UsbDescriptor.DESCRIPTORTYPE_AUDIO_ENDPOINT: + break; + } + } + } + + /** + * Generate a report of the descriptors tree. + */ + public void report(ReportCanvas canvas) { + mDeviceNode.report(canvas); + } +} diff --git a/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsTreeNode.java b/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsTreeNode.java new file mode 100644 index 000000000000..aca3cd907372 --- /dev/null +++ b/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsTreeNode.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.usb.descriptors.tree; + +import com.android.server.usb.descriptors.report.ReportCanvas; +import com.android.server.usb.descriptors.report.Reporting; + +/** + * @hide + * A shared super class for UsbDescriptor tree nodes. + */ +public class UsbDescriptorsTreeNode implements Reporting { + private static final String TAG = "UsbDescriptorsTreeNode"; + + /** + * Implements generate a comprehehensive report of descriptor. + */ + @Override + public void report(ReportCanvas canvas) { + } + + /** + * Implements generate an abreviated report of descriptor. + */ + @Override + public void shortReport(ReportCanvas canvas) { + } +} diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index 4ffacfd7056a..1569ac32128b 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -183,7 +183,7 @@ public class VoiceInteractionManagerService extends SystemService { private final boolean mEnableService; VoiceInteractionManagerServiceStub() { - mEnableService = shouldEnableService(mContext.getResources()); + mEnableService = shouldEnableService(mContext); } // TODO: VI Make sure the caller is the current user or profile @@ -348,10 +348,15 @@ public class VoiceInteractionManagerService extends SystemService { } } - private boolean shouldEnableService(Resources res) { - // VoiceInteractionService should not be enabled on low ram devices unless it has the config flag. - return !ActivityManager.isLowRamDeviceStatic() || - getForceVoiceInteractionServicePackage(res) != null; + private boolean shouldEnableService(Context context) { + // VoiceInteractionService should not be enabled on any low RAM devices + // or devices that have not declared the recognition feature, unless the + // device's configuration has explicitly set the config flag for a fixed + // voice interaction service. + return (!ActivityManager.isLowRamDeviceStatic() + && context.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_VOICE_RECOGNIZERS)) || + getForceVoiceInteractionServicePackage(context.getResources()) != null; } private String getForceVoiceInteractionServicePackage(Resources res) { diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index c1289d3f1401..e13bd6193719 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -1089,12 +1089,17 @@ public final class Call { * @return A string containing text sent by the remote user, or {@code null} if the * conversation has been terminated or if there was an error while reading. */ - public String read() throws IOException { - int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE); - if (numRead < 0) { + public String read() { + try { + int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE); + if (numRead < 0) { + return null; + } + return new String(mReadBuffer, 0, numRead); + } catch (IOException e) { + Log.w(this, "Exception encountered when reading from InputStreamReader: %s", e); return null; } - return new String(mReadBuffer, 0, numRead); } /** @@ -1105,7 +1110,11 @@ public final class Call { */ public String readImmediately() throws IOException { if (mReceiveStream.ready()) { - return read(); + int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE); + if (numRead < 0) { + return null; + } + return new String(mReadBuffer, 0, numRead); } else { return null; } diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java index db4939171aa6..5fcff18aa5be 100644 --- a/telecomm/java/android/telecom/Conference.java +++ b/telecomm/java/android/telecom/Conference.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Bundle; +import android.os.SystemClock; import android.telecom.Connection.VideoProvider; import android.util.ArraySet; @@ -81,6 +82,7 @@ public abstract class Conference extends Conferenceable { private int mConnectionProperties; private String mDisconnectMessage; private long mConnectTimeMillis = CONNECT_TIME_NOT_SPECIFIED; + private long mConnectElapsedTimeMillis = CONNECT_TIME_NOT_SPECIFIED; private StatusHints mStatusHints; private Bundle mExtras; private Set<String> mPreviousExtraKeys; @@ -582,7 +584,11 @@ public abstract class Conference extends Conferenceable { } /** - * Sets the connection start time of the {@code Conference}. + * Sets the connection start time of the {@code Conference}. Should be specified in wall-clock + * time returned by {@link System#currentTimeMillis()}. + * <p> + * When setting the connection time, you should always set the connection elapsed time via + * {@link #setConnectionElapsedTime(long)}. * * @param connectionTimeMillis The connection time, in milliseconds. */ @@ -591,6 +597,20 @@ public abstract class Conference extends Conferenceable { } /** + * Sets the elapsed time since system boot when the {@link Conference} was connected. + * This is used to determine the duration of the {@link Conference}. + * <p> + * When setting the connection elapsed time, you should always set the connection time via + * {@link #setConnectionTime(long)}. + * + * @param connectionElapsedTime The connection time, as measured by + * {@link SystemClock#elapsedRealtime()}. + */ + public final void setConnectionElapsedTime(long connectionElapsedTime) { + mConnectElapsedTimeMillis = connectionElapsedTime; + } + + /** * @hide * @deprecated Use {@link #getConnectionTime}. */ @@ -612,6 +632,21 @@ public abstract class Conference extends Conferenceable { } /** + * Retrieves the connection start time of the {@link Conference}, if specified. A value of + * {@link #CONNECT_TIME_NOT_SPECIFIED} indicates that Telecom should determine the start time + * of the conference. + * + * This is based on the value of {@link SystemClock#elapsedRealtime()} to ensure that it is not + * impacted by wall clock changes (user initiated, network initiated, time zone change, etc). + * + * @return The elapsed time at which the {@link Conference} was connected. + * @hide + */ + public final long getConnectElapsedTime() { + return mConnectElapsedTimeMillis; + } + + /** * Inform this Conference that the state of its audio output has been changed externally. * * @param state The new audio state. diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index f5d37bb6d6c4..8ba934ccdb8b 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -20,7 +20,6 @@ import com.android.internal.os.SomeArgs; import com.android.internal.telecom.IVideoCallback; import com.android.internal.telecom.IVideoProvider; -import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; @@ -37,14 +36,13 @@ import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.RemoteException; +import android.os.SystemClock; import android.util.ArraySet; import android.view.Surface; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -826,6 +824,8 @@ public abstract class Connection extends Conferenceable { public void onRttInitiationFailure(Connection c, int reason) {} public void onRttSessionRemotelyTerminated(Connection c) {} public void onRemoteRttRequest(Connection c) {} + /** @hide */ + public void onPhoneAccountChanged(Connection c, PhoneAccountHandle pHandle) {} } /** @@ -1696,6 +1696,7 @@ public abstract class Connection extends Conferenceable { private VideoProvider mVideoProvider; private boolean mAudioModeIsVoip; private long mConnectTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED; + private long mConnectElapsedTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED; private StatusHints mStatusHints; private int mVideoState; private DisconnectCause mDisconnectCause; @@ -1840,6 +1841,22 @@ public abstract class Connection extends Conferenceable { } /** + * Retrieves the connection start time of the {@link Connection}, if specified. A value of + * {@link Conference#CONNECT_TIME_NOT_SPECIFIED} indicates that Telecom should determine the + * start time of the conference. + * + * Based on the value of {@link SystemClock#elapsedRealtime()}, which ensures that wall-clock + * changes do not impact the call duration. + * + * @return The time at which the {@link Connection} was connected. + * + * @hide + */ + public final long getConnectElapsedTimeMillis() { + return mConnectElapsedTimeMillis; + } + + /** * @return The status hints for this connection. */ public final StatusHints getStatusHints() { @@ -2250,7 +2267,8 @@ public abstract class Connection extends Conferenceable { * Sets the time at which a call became active on this Connection. This is set only * when a conference call becomes active on this connection. * - * @param connectionTimeMillis The connection time, in milliseconds. + * @param connectTimeMillis The connection time, in milliseconds. Should be set using a value + * obtained from {@link System#currentTimeMillis()}. * * @hide */ @@ -2259,6 +2277,19 @@ public abstract class Connection extends Conferenceable { } /** + * Sets the time at which a call became active on this Connection. This is set only + * when a conference call becomes active on this connection. + * + * @param connectElapsedTimeMillis The connection time, in milliseconds. Stored in the format + * {@link SystemClock#elapsedRealtime()}. + * + * @hide + */ + public final void setConnectElapsedTimeMillis(long connectElapsedTimeMillis) { + mConnectElapsedTimeMillis = connectElapsedTimeMillis; + } + + /** * Sets the label and icon status to display in the in-call UI. * * @param statusHints The status label and icon to set. @@ -3033,6 +3064,18 @@ public abstract class Connection extends Conferenceable { } /** + * Notifies listeners when phone account is changed. For example, when the PhoneAccount is + * changed due to an emergency call being redialed. + * @param pHandle The new PhoneAccountHandle for this connection. + * @hide + */ + public void notifyPhoneAccountChanged(PhoneAccountHandle pHandle) { + for (Listener l : mListeners) { + l.onPhoneAccountChanged(this, pHandle); + } + } + + /** * Sends an event associated with this {@code Connection} with associated event extras to the * {@link InCallService}. * <p> diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index e3b027abdb5d..a81fba95c4ed 100644 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -1332,6 +1332,14 @@ public abstract class ConnectionService extends Service { mAdapter.onRemoteRttRequest(id); } } + + @Override + public void onPhoneAccountChanged(Connection c, PhoneAccountHandle pHandle) { + String id = mIdByConnection.get(c); + if (id != null) { + mAdapter.onPhoneAccountChanged(id, pHandle); + } + } }; /** {@inheritDoc} */ @@ -1405,6 +1413,7 @@ public abstract class ConnectionService extends Service { connection.isRingbackRequested(), connection.getAudioModeIsVoip(), connection.getConnectTimeMillis(), + connection.getConnectElapsedTimeMillis(), connection.getStatusHints(), connection.getDisconnectCause(), createIdList(connection.getConferenceables()), @@ -1440,6 +1449,12 @@ public abstract class ConnectionService extends Service { */ private void notifyCreateConnectionComplete(final String callId) { Log.i(this, "notifyCreateConnectionComplete %s", callId); + if (callId == null) { + // This could happen if the connection fails quickly and is removed from the + // ConnectionService before Telecom sends the create connection complete callback. + Log.w(this, "notifyCreateConnectionComplete: callId is null."); + return; + } onCreateConnectionComplete(findConnectionForAction(callId, "notifyCreateConnectionComplete")); } @@ -1816,6 +1831,7 @@ public abstract class ConnectionService extends Service { null : conference.getVideoProvider().getInterface(), conference.getVideoState(), conference.getConnectTimeMillis(), + conference.getConnectElapsedTime(), conference.getStatusHints(), conference.getExtras()); @@ -1881,6 +1897,7 @@ public abstract class ConnectionService extends Service { connection.isRingbackRequested(), connection.getAudioModeIsVoip(), connection.getConnectTimeMillis(), + connection.getConnectElapsedTimeMillis(), connection.getStatusHints(), connection.getDisconnectCause(), emptyList, @@ -2166,7 +2183,7 @@ public abstract class ConnectionService extends Service { } private Connection findConnectionForAction(String callId, String action) { - if (mConnectionById.containsKey(callId)) { + if (callId != null && mConnectionById.containsKey(callId)) { return mConnectionById.get(callId); } Log.w(this, "%s - Cannot find Connection %s", action, callId); diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java index 63bdf74d383c..111fcc7869b4 100644 --- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java +++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java @@ -609,4 +609,20 @@ final class ConnectionServiceAdapter implements DeathRecipient { } } } + + /** + * Notifies Telecom that a call's PhoneAccountHandle has changed. + * + * @param callId The unique ID of the call. + * @param pHandle The new PhoneAccountHandle associated with the call. + */ + void onPhoneAccountChanged(String callId, PhoneAccountHandle pHandle) { + for (IConnectionServiceAdapter adapter : mAdapters) { + try { + Log.d(this, "onPhoneAccountChanged %s", callId); + adapter.onPhoneAccountChanged(callId, pHandle, Log.getExternalSession()); + } catch (RemoteException ignored) { + } + } + } } diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java index 80e3c33a443d..b1617f4db801 100644 --- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java +++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java @@ -72,6 +72,7 @@ final class ConnectionServiceAdapterServant { private static final int MSG_ON_RTT_INITIATION_FAILURE = 31; private static final int MSG_ON_RTT_REMOTELY_TERMINATED = 32; private static final int MSG_ON_RTT_UPGRADE_REQUEST = 33; + private static final int MSG_SET_PHONE_ACCOUNT_CHANGED = 34; private final IConnectionServiceAdapter mDelegate; @@ -318,6 +319,16 @@ final class ConnectionServiceAdapterServant { case MSG_ON_RTT_UPGRADE_REQUEST: mDelegate.onRemoteRttRequest((String) msg.obj, null /*Session.Info*/); break; + case MSG_SET_PHONE_ACCOUNT_CHANGED: { + SomeArgs args = (SomeArgs) msg.obj; + try { + mDelegate.onPhoneAccountChanged((String) args.arg1, + (PhoneAccountHandle) args.arg2, null /*Session.Info*/); + } finally { + args.recycle(); + } + break; + } } } }; @@ -581,6 +592,15 @@ final class ConnectionServiceAdapterServant { throws RemoteException { mHandler.obtainMessage(MSG_ON_RTT_UPGRADE_REQUEST, connectionId).sendToTarget(); } + + @Override + public void onPhoneAccountChanged(String callId, PhoneAccountHandle pHandle, + Session.Info sessionInfo) { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = callId; + args.arg2 = pHandle; + mHandler.obtainMessage(MSG_SET_PHONE_ACCOUNT_CHANGED, args).sendToTarget(); + } }; public ConnectionServiceAdapterServant(IConnectionServiceAdapter delegate) { diff --git a/telecomm/java/android/telecom/ParcelableConference.java b/telecomm/java/android/telecom/ParcelableConference.java index f5689d882ba8..a6221d4d7236 100644 --- a/telecomm/java/android/telecom/ParcelableConference.java +++ b/telecomm/java/android/telecom/ParcelableConference.java @@ -41,6 +41,7 @@ public final class ParcelableConference implements Parcelable { private final int mVideoState; private StatusHints mStatusHints; private Bundle mExtras; + private long mConnectElapsedTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED; public ParcelableConference( PhoneAccountHandle phoneAccount, @@ -51,6 +52,7 @@ public final class ParcelableConference implements Parcelable { IVideoProvider videoProvider, int videoState, long connectTimeMillis, + long connectElapsedTimeMillis, StatusHints statusHints, Bundle extras) { mPhoneAccount = phoneAccount; @@ -58,12 +60,12 @@ public final class ParcelableConference implements Parcelable { mConnectionCapabilities = connectionCapabilities; mConnectionProperties = connectionProperties; mConnectionIds = connectionIds; - mConnectTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED; mVideoProvider = videoProvider; mVideoState = videoState; mConnectTimeMillis = connectTimeMillis; mStatusHints = statusHints; mExtras = extras; + mConnectElapsedTimeMillis = connectElapsedTimeMillis; } @Override @@ -111,6 +113,11 @@ public final class ParcelableConference implements Parcelable { public long getConnectTimeMillis() { return mConnectTimeMillis; } + + public long getConnectElapsedTimeMillis() { + return mConnectElapsedTimeMillis; + } + public IVideoProvider getVideoProvider() { return mVideoProvider; } @@ -144,10 +151,11 @@ public final class ParcelableConference implements Parcelable { StatusHints statusHints = source.readParcelable(classLoader); Bundle extras = source.readBundle(classLoader); int properties = source.readInt(); + long connectElapsedTimeMillis = source.readLong(); return new ParcelableConference(phoneAccount, state, capabilities, properties, - connectionIds, videoCallProvider, videoState, connectTimeMillis, statusHints, - extras); + connectionIds, videoCallProvider, videoState, connectTimeMillis, + connectElapsedTimeMillis, statusHints, extras); } @Override @@ -176,5 +184,6 @@ public final class ParcelableConference implements Parcelable { destination.writeParcelable(mStatusHints, 0); destination.writeBundle(mExtras); destination.writeInt(mConnectionProperties); + destination.writeLong(mConnectElapsedTimeMillis); } } diff --git a/telecomm/java/android/telecom/ParcelableConnection.java b/telecomm/java/android/telecom/ParcelableConnection.java index 434abf53624c..61d5a1265312 100644 --- a/telecomm/java/android/telecom/ParcelableConnection.java +++ b/telecomm/java/android/telecom/ParcelableConnection.java @@ -47,6 +47,7 @@ public final class ParcelableConnection implements Parcelable { private final boolean mRingbackRequested; private final boolean mIsVoipAudioMode; private final long mConnectTimeMillis; + private final long mConnectElapsedTimeMillis; private final StatusHints mStatusHints; private final DisconnectCause mDisconnectCause; private final List<String> mConferenceableConnectionIds; @@ -69,6 +70,7 @@ public final class ParcelableConnection implements Parcelable { boolean ringbackRequested, boolean isVoipAudioMode, long connectTimeMillis, + long connectElapsedTimeMillis, StatusHints statusHints, DisconnectCause disconnectCause, List<String> conferenceableConnectionIds, @@ -77,7 +79,8 @@ public final class ParcelableConnection implements Parcelable { this(phoneAccount, state, capabilities, properties, supportedAudioRoutes, address, addressPresentation, callerDisplayName, callerDisplayNamePresentation, videoProvider, videoState, ringbackRequested, isVoipAudioMode, connectTimeMillis, - statusHints, disconnectCause, conferenceableConnectionIds, extras); + connectElapsedTimeMillis, statusHints, disconnectCause, conferenceableConnectionIds, + extras); mParentCallId = parentCallId; } @@ -97,6 +100,7 @@ public final class ParcelableConnection implements Parcelable { boolean ringbackRequested, boolean isVoipAudioMode, long connectTimeMillis, + long connectElapsedTimeMillis, StatusHints statusHints, DisconnectCause disconnectCause, List<String> conferenceableConnectionIds, @@ -115,6 +119,7 @@ public final class ParcelableConnection implements Parcelable { mRingbackRequested = ringbackRequested; mIsVoipAudioMode = isVoipAudioMode; mConnectTimeMillis = connectTimeMillis; + mConnectElapsedTimeMillis = connectElapsedTimeMillis; mStatusHints = statusHints; mDisconnectCause = disconnectCause; mConferenceableConnectionIds = conferenceableConnectionIds; @@ -190,6 +195,10 @@ public final class ParcelableConnection implements Parcelable { return mConnectTimeMillis; } + public long getConnectElapsedTimeMillis() { + return mConnectElapsedTimeMillis; + } + public final StatusHints getStatusHints() { return mStatusHints; } @@ -255,6 +264,7 @@ public final class ParcelableConnection implements Parcelable { int properties = source.readInt(); int supportedAudioRoutes = source.readInt(); String parentCallId = source.readString(); + long connectElapsedTimeMillis = source.readLong(); return new ParcelableConnection( phoneAccount, @@ -271,6 +281,7 @@ public final class ParcelableConnection implements Parcelable { ringbackRequested, audioModeIsVoip, connectTimeMillis, + connectElapsedTimeMillis, statusHints, disconnectCause, conferenceableConnectionIds, @@ -313,5 +324,6 @@ public final class ParcelableConnection implements Parcelable { destination.writeInt(mConnectionProperties); destination.writeInt(mSupportedAudioRoutes); destination.writeString(mParentCallId); + destination.writeLong(mConnectElapsedTimeMillis); } } diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java index 06cdd1aa7c3c..2cc431436acb 100644 --- a/telecomm/java/android/telecom/RemoteConnectionService.java +++ b/telecomm/java/android/telecom/RemoteConnectionService.java @@ -208,6 +208,11 @@ final class RemoteConnectionService { } @Override + public void onPhoneAccountChanged(String callId, PhoneAccountHandle pHandle, + Session.Info sessionInfo) { + } + + @Override public void addConferenceCall( final String callId, ParcelableConference parcel, Session.Info sessionInfo) { RemoteConference conference = new RemoteConference(callId, diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl index ac9da2ef9df4..d20da1862a28 100644 --- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl +++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl @@ -24,6 +24,7 @@ import android.telecom.DisconnectCause; import android.telecom.Logging.Session; import android.telecom.ParcelableConnection; import android.telecom.ParcelableConference; +import android.telecom.PhoneAccountHandle; import android.telecom.StatusHints; import com.android.internal.telecom.IVideoProvider; @@ -114,4 +115,7 @@ oneway interface IConnectionServiceAdapter { void onRttSessionRemotelyTerminated(String callId, in Session.Info sessionInfo); void onRemoteRttRequest(String callId, in Session.Info sessionInfo); + + void onPhoneAccountChanged(String callId, in PhoneAccountHandle pHandle, + in Session.Info sessionInfo); } diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 23db6ace2f73..8e4f48772b9b 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -346,14 +346,29 @@ public class CarrierConfigManager { public static final String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string"; /** - * Flag indicating whether we should downgrade/terminate VT calls and disable VT when - * data enabled changed (e.g. reach data limit or turn off data). + * When {@code true}, changes to the mobile data enabled switch will not cause the VT + * registration state to change. That is, turning on or off mobile data will not cause VT to be + * enabled or disabled. + * When {@code false}, disabling mobile data will cause VT to be de-registered. + * <p> + * See also {@link #KEY_VILTE_DATA_IS_METERED_BOOL}. * @hide */ public static final String KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS = "ignore_data_enabled_changed_for_video_calls"; /** + * Flag indicating whether data used for a video call over LTE is metered or not. + * <p> + * When {@code true}, if the device hits the data limit or data is disabled during a ViLTE call, + * the call will be downgraded to audio-only (or paused if + * {@link #KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL} is {@code true}). + * + * @hide + */ + public static final String KEY_VILTE_DATA_IS_METERED_BOOL = "vilte_data_is_metered_bool"; + + /** * Flag specifying whether WFC over IMS should be available for carrier: independent of * carrier provisioning. If false: hard disabled. If true: then depends on carrier * provisioning, availability etc. @@ -567,20 +582,27 @@ public class CarrierConfigManager { "carrier_data_call_retry_config_strings"; /** - * Delay between trying APN from the pool + * Delay in milliseconds between trying APN from the pool * @hide */ public static final String KEY_CARRIER_DATA_CALL_APN_DELAY_DEFAULT_LONG = "carrier_data_call_apn_delay_default_long"; /** - * Faster delay between trying APN from the pool + * Faster delay in milliseconds between trying APN from the pool * @hide */ public static final String KEY_CARRIER_DATA_CALL_APN_DELAY_FASTER_LONG = "carrier_data_call_apn_delay_faster_long"; /** + * Delay in milliseconds for retrying APN after disconnect + * @hide + */ + public static final String KEY_CARRIER_DATA_CALL_APN_RETRY_AFTER_DISCONNECT_LONG = + "carrier_data_call_apn_retry_after_disconnect_long"; + + /** * Data call setup permanent failure causes by the carrier */ public static final String KEY_CARRIER_DATA_CALL_PERMANENT_FAILURE_STRINGS = @@ -768,7 +790,6 @@ public class CarrierConfigManager { * Determines whether High Definition audio property is displayed in the dialer UI. * If {@code false}, remove the HD audio property from the connection so that HD audio related * UI is not displayed. If {@code true}, keep HD audio property as it is configured. - * @hide */ public static final String KEY_DISPLAY_HD_AUDIO_PROPERTY_BOOL = "display_hd_audio_property_bool"; @@ -819,8 +840,6 @@ public class CarrierConfigManager { * If user has explicitly disabled some packages in the list, won't re-enable. * Other carrier specific apps which are not in this list may be disabled for current carrier, * and only be re-enabled when this config for another carrier includes it. - * - * @hide */ public static final String KEY_ENABLE_APPS_STRING_ARRAY = "enable_apps_string_array"; @@ -1167,8 +1186,6 @@ public class CarrierConfigManager { /** @hide */ public static final int CDMA_ROAMING_MODE_AFFILIATED = 1; /** @hide */ - public static final int IMSI_ENCRYPTION_DAYS_TIME_DISABLED = -1; - /** @hide */ public static final int CDMA_ROAMING_MODE_ANY = 2; /** * Boolean indicating if support is provided for directly dialing FDN number from FDN list. @@ -1363,6 +1380,16 @@ public class CarrierConfigManager { "network_notification_delay_int"; /** + * Time delay (in ms) after which we show the notification for emergency calls, + * while the device is registered over WFC. Default value is -1, which indicates + * that this notification is not pertinent for a particular carrier. We've added a delay + * to prevent false positives. + * @hide + */ + public static final String KEY_EMERGENCY_NOTIFICATION_DELAY_INT = + "emergency_notification_delay_int"; + + /** * When {@code true}, the carrier allows the user of the * {@link TelephonyManager#sendUssdRequest(String, TelephonyManager.UssdResponseCallback, * Handler)} API to perform USSD requests. {@code True} by default. @@ -1517,14 +1544,15 @@ public class CarrierConfigManager { public static final String IMSI_KEY_DOWNLOAD_URL_STRING = "imsi_key_download_url_string"; /** - * Time in days, after which the key will expire, and a new key will need to be downloaded. - * default value is {@link IMSI_ENCRYPTION_DAYS_TIME_DISABLED}, and indicates that IMSI - * encryption is not enabled by default for a carrier. Value of 0 indicates that the key - * does not expire. + * Identifies if the key is available for WLAN or EPDG or both. The value is a bitmask. + * 0 indicates that neither EPDG or WLAN is enabled. + * 1 indicates that key type {@link TelephonyManager#KEY_TYPE_EPDG} is enabled. + * 2 indicates that key type {@link TelephonyManager#KEY_TYPE_WLAN} is enabled. + * 3 indicates that both are enabled. * @hide */ - public static final String IMSI_KEY_EXPIRATION_DAYS_TIME_INT = - "imsi_key_expiration_days_time_int"; + public static final String IMSI_KEY_AVAILABILITY_INT = "imsi_key_availability_int"; + /** * Key identifying if the CDMA Caller ID presentation and suppression MMI codes @@ -1554,7 +1582,8 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_NOTIFY_HANDOVER_VIDEO_FROM_WIFI_TO_LTE_BOOL, false); sDefaults.putBoolean(KEY_SUPPORT_DOWNGRADE_VT_TO_AUDIO_BOOL, true); sDefaults.putString(KEY_DEFAULT_VM_NUMBER_STRING, ""); - sDefaults.putBoolean(KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, false); + sDefaults.putBoolean(KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, true); + sDefaults.putBoolean(KEY_VILTE_DATA_IS_METERED_BOOL, true); sDefaults.putBoolean(KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL, false); @@ -1636,6 +1665,7 @@ public class CarrierConfigManager { "others:max_retries=3, 5000, 5000, 5000"}); sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_DELAY_DEFAULT_LONG, 20000); sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_DELAY_FASTER_LONG, 3000); + sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_RETRY_AFTER_DISCONNECT_LONG, 10000); sDefaults.putString(KEY_CARRIER_ERI_FILE_NAME_STRING, "eri.xml"); sDefaults.putInt(KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT, 7200); sDefaults.putStringArray(KEY_CARRIER_METERED_APN_TYPES_STRINGS, @@ -1788,6 +1818,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_PERSIST_LPP_MODE_BOOL, false); sDefaults.putStringArray(KEY_CARRIER_WIFI_STRING_ARRAY, null); sDefaults.putInt(KEY_PREF_NETWORK_NOTIFICATION_DELAY_INT, -1); + sDefaults.putInt(KEY_EMERGENCY_NOTIFICATION_DELAY_INT, -1); sDefaults.putBoolean(KEY_ALLOW_USSD_REQUESTS_VIA_TELEPHONY_MANAGER_BOOL, true); sDefaults.putBoolean(KEY_SUPPORT_3GPP_CALL_FORWARDING_WHILE_ROAMING_BOOL, true); sDefaults.putBoolean(KEY_NOTIFY_INTERNATIONAL_CALL_ON_WFC_BOOL, false); @@ -1796,7 +1827,7 @@ public class CarrierConfigManager { sDefaults.putInt(KEY_LTE_EARFCNS_RSRP_BOOST_INT, 0); sDefaults.putStringArray(KEY_BOOSTED_LTE_EARFCNS_STRING_ARRAY, null); sDefaults.putBoolean(KEY_DISABLE_VOICE_BARRING_NOTIFICATION_BOOL, false); - sDefaults.putInt(IMSI_KEY_EXPIRATION_DAYS_TIME_INT, IMSI_ENCRYPTION_DAYS_TIME_DISABLED); + sDefaults.putInt(IMSI_KEY_AVAILABILITY_INT, 0); sDefaults.putString(IMSI_KEY_DOWNLOAD_URL_STRING, null); sDefaults.putBoolean(KEY_CONVERT_CDMA_CALLER_ID_MMI_CODES_WHILE_ROAMING_ON_3GPP_BOOL, false); diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java index 9513517947f4..98fb65343485 100644 --- a/telephony/java/android/telephony/DisconnectCause.java +++ b/telephony/java/android/telephony/DisconnectCause.java @@ -227,13 +227,6 @@ public class DisconnectCause { public static final int DATA_LIMIT_REACHED = 55; /** - * The emergency call was terminated because it was dialed on the wrong SIM slot. - * The call needs to be redialed the other slot. - * {@hide} - */ - public static final int DIALED_ON_WRONG_SLOT = 56; - - /** * The call being placed was detected as a call forwarding number and was being dialed while * roaming on a carrier that does not allow this. */ @@ -258,6 +251,28 @@ public class DisconnectCause { */ public static final int IMS_ACCESS_BLOCKED = 60; + /** + * The call has ended (mid-call) because the device's battery is too low. + */ + public static final int LOW_BATTERY = 61; + + /** + * A call was not dialed because the device's battery is too low. + */ + public static final int DIAL_LOW_BATTERY = 62; + + /** + * Emergency call failed with a temporary fail cause and can be redialed on this slot. + * {@hide} + */ + public static final int EMERGENCY_TEMP_FAILURE = 63; + + /** + * Emergency call failed with a permanent fail cause and should not be redialed on this + * slot. + * {@hide} + */ + public static final int EMERGENCY_PERM_FAILURE = 64; //********************************************************************************************* // When adding a disconnect type: // 1) Update toString() with the newly added disconnect type. @@ -382,8 +397,6 @@ public class DisconnectCause { return "DATA_DISABLED"; case DATA_LIMIT_REACHED: return "DATA_LIMIT_REACHED"; - case DIALED_ON_WRONG_SLOT: - return "DIALED_ON_WRONG_SLOT"; case DIALED_CALL_FORWARDING_WHILE_ROAMING: return "DIALED_CALL_FORWARDING_WHILE_ROAMING"; case IMEI_NOT_ACCEPTED: @@ -392,6 +405,14 @@ public class DisconnectCause { return "WIFI_LOST"; case IMS_ACCESS_BLOCKED: return "IMS_ACCESS_BLOCKED"; + case LOW_BATTERY: + return "LOW_BATTERY"; + case DIAL_LOW_BATTERY: + return "DIAL_LOW_BATTERY"; + case EMERGENCY_TEMP_FAILURE: + return "EMERGENCY_TEMP_FAILURE"; + case EMERGENCY_PERM_FAILURE: + return "EMERGENCY_PERM_FAILURE"; default: return "INVALID: " + cause; } diff --git a/telephony/java/android/telephony/MbmsDownloadManager.java b/telephony/java/android/telephony/MbmsDownloadManager.java index 4c3f7e7ab5a8..1e8cf185d4e4 100644 --- a/telephony/java/android/telephony/MbmsDownloadManager.java +++ b/telephony/java/android/telephony/MbmsDownloadManager.java @@ -18,19 +18,19 @@ package android.telephony; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SdkConstant; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; -import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.IBinder; import android.os.RemoteException; +import android.telephony.mbms.DownloadProgressListener; import android.telephony.mbms.FileInfo; import android.telephony.mbms.DownloadRequest; -import android.telephony.mbms.IDownloadProgressListener; -import android.telephony.mbms.IMbmsDownloadManagerCallback; import android.telephony.mbms.MbmsDownloadManagerCallback; import android.telephony.mbms.MbmsDownloadReceiver; import android.telephony.mbms.MbmsException; @@ -44,6 +44,7 @@ import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; @@ -52,147 +53,38 @@ import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; public class MbmsDownloadManager { private static final String LOG_TAG = MbmsDownloadManager.class.getSimpleName(); + /** @hide */ + // TODO: systemapi + @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) public static final String MBMS_DOWNLOAD_SERVICE_ACTION = "android.telephony.action.EmbmsDownload"; - /** - * The MBMS middleware should send this when a download of single file has completed or - * failed. Mandatory extras are - * {@link #EXTRA_RESULT} - * {@link #EXTRA_FILE_INFO} - * {@link #EXTRA_REQUEST} - * {@link #EXTRA_TEMP_LIST} - * {@link #EXTRA_FINAL_URI} - * - * TODO: future systemapi - */ - public static final String ACTION_DOWNLOAD_RESULT_INTERNAL = - "android.telephony.mbms.action.DOWNLOAD_RESULT_INTERNAL"; - - /** - * The MBMS middleware should send this when it wishes to request {@code content://} URIs to - * serve as temp files for downloads or when it wishes to resume paused downloads. Mandatory - * extras are - * {@link #EXTRA_REQUEST} - * - * Optional extras are - * {@link #EXTRA_FD_COUNT} (0 if not present) - * {@link #EXTRA_PAUSED_LIST} (empty if not present) - * - * TODO: future systemapi - */ - public static final String ACTION_FILE_DESCRIPTOR_REQUEST = - "android.telephony.mbms.action.FILE_DESCRIPTOR_REQUEST"; - - /** - * The MBMS middleware should send this when it wishes to clean up temp files in the app's - * filesystem. Mandatory extras are: - * {@link #EXTRA_TEMP_FILES_IN_USE} - * - * TODO: future systemapi - */ - public static final String ACTION_CLEANUP = - "android.telephony.mbms.action.CLEANUP"; /** * Integer extra indicating the result code of the download. One of * {@link #RESULT_SUCCESSFUL}, {@link #RESULT_EXPIRED}, or {@link #RESULT_CANCELLED}. - * TODO: Not systemapi. */ public static final String EXTRA_RESULT = "android.telephony.mbms.extra.RESULT"; /** * Extra containing the {@link android.telephony.mbms.FileInfo} for which the download result * is for. Must not be null. - * TODO: Not systemapi. */ public static final String EXTRA_FILE_INFO = "android.telephony.mbms.extra.FILE_INFO"; /** - * Extra containing the {@link DownloadRequest} for which the download result or file - * descriptor request is for. Must not be null. - * TODO: future systemapi (here and and all extras) except the three for the app intent - */ - public static final String EXTRA_REQUEST = "android.telephony.mbms.extra.REQUEST"; - - /** - * Extra containing a {@link List} of {@link Uri}s that were used as temp files for this - * completed file. These {@link Uri}s should have scheme {@code file://}, and the temp - * files will be deleted upon receipt of the intent. - * May be null. - */ - public static final String EXTRA_TEMP_LIST = "android.telephony.mbms.extra.TEMP_LIST"; - - /** - * Extra containing a single {@link Uri} indicating the path to the temp file in which the - * decoded downloaded file resides. Must not be null. - */ - public static final String EXTRA_FINAL_URI = "android.telephony.mbms.extra.FINAL_URI"; - - /** - * Extra containing an integer indicating the number of temp files requested. - */ - public static final String EXTRA_FD_COUNT = "android.telephony.mbms.extra.FD_COUNT"; - - /** - * Extra containing a list of {@link Uri}s that the middleware is requesting access to via - * {@link #ACTION_FILE_DESCRIPTOR_REQUEST} in order to resume downloading. These {@link Uri}s - * should have scheme {@code file://}. - */ - public static final String EXTRA_PAUSED_LIST = "android.telephony.mbms.extra.PAUSED_LIST"; - - /** - * Extra containing a list of {@link android.telephony.mbms.UriPathPair}s, used in the - * response to {@link #ACTION_FILE_DESCRIPTOR_REQUEST}. These are temp files that are meant - * to be used for new file downloads. - */ - public static final String EXTRA_FREE_URI_LIST = "android.telephony.mbms.extra.FREE_URI_LIST"; - - /** - * Extra containing a list of {@link android.telephony.mbms.UriPathPair}s, used in the - * response to {@link #ACTION_FILE_DESCRIPTOR_REQUEST}. These - * {@link android.telephony.mbms.UriPathPair}s contain {@code content://} URIs that provide - * access to previously paused downloads. - */ - public static final String EXTRA_PAUSED_URI_LIST = - "android.telephony.mbms.extra.PAUSED_URI_LIST"; - - /** - * Extra containing a string that points to the middleware's knowledge of where the temp file - * root for the app is. The path should be a canonical path as returned by - * {@link File#getCanonicalPath()} - */ - public static final String EXTRA_TEMP_FILE_ROOT = - "android.telephony.mbms.extra.TEMP_FILE_ROOT"; - - /** - * Extra containing a list of {@link Uri}s indicating temp files which the middleware is - * still using. - */ - public static final String EXTRA_TEMP_FILES_IN_USE = - "android.telephony.mbms.extra.TEMP_FILES_IN_USE"; - - /** - * Extra containing an instance of {@link android.telephony.mbms.ServiceInfo}, used by - * file-descriptor requests and cleanup requests to specify which service they want to - * request temp files or clean up temp files for, respectively. - */ - public static final String EXTRA_SERVICE_INFO = - "android.telephony.mbms.extra.SERVICE_INFO"; - - /** * Extra containing a single {@link Uri} indicating the location of the successfully * downloaded file. Set on the intent provided via * {@link android.telephony.mbms.DownloadRequest.Builder#setAppIntent(Intent)}. * Will always be set to a non-null value if {@link #EXTRA_RESULT} is set to * {@link #RESULT_SUCCESSFUL}. - * TODO: Not systemapi. */ public static final String EXTRA_COMPLETED_FILE_URI = "android.telephony.mbms.extra.COMPLETED_FILE_URI"; public static final int RESULT_SUCCESSFUL = 1; - public static final int RESULT_CANCELLED = 2; - public static final int RESULT_EXPIRED = 3; + public static final int RESULT_CANCELLED = 2; + public static final int RESULT_EXPIRED = 3; + public static final int RESULT_IO_ERROR = 4; // TODO - more results! /** @hide */ @@ -207,8 +99,16 @@ public class MbmsDownloadManager { public static final int STATUS_PENDING_REPAIR = 3; public static final int STATUS_PENDING_DOWNLOAD_WINDOW = 4; + private static AtomicBoolean sIsInitialized = new AtomicBoolean(false); + private final Context mContext; private int mSubscriptionId = INVALID_SUBSCRIPTION_ID; + private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { + @Override + public void binderDied() { + sendErrorToApp(MbmsException.ERROR_MIDDLEWARE_LOST, "Received death notification"); + } + }; private AtomicReference<IMbmsDownloadService> mService = new AtomicReference<>(null); private final MbmsDownloadManagerCallback mCallback; @@ -236,10 +136,21 @@ public class MbmsDownloadManager { * * Note that this call will bind a remote service and that may take a bit. The instance of * {@link MbmsDownloadManager} that is returned will not be ready for use until - * {@link IMbmsDownloadManagerCallback#middlewareReady()} is called on the provided callback. + * {@link MbmsDownloadManagerCallback#middlewareReady()} is called on the provided callback. * If you attempt to use the manager before it is ready, a {@link MbmsException} will be thrown. * - * This also may throw an {@link IllegalArgumentException} or a {@link MbmsException}. + * This also may throw an {@link IllegalArgumentException} or an {@link IllegalStateException}. + * + * You may only have one instance of {@link MbmsDownloadManager} per UID. If you call this + * method while there is an active instance of {@link MbmsDownloadManager} in your process + * (in other words, one that has not had {@link #dispose()} called on it), this method will + * throw an {@link MbmsException}. If you call this method in a different process + * running under the same UID, an error will be indicated via + * {@link MbmsDownloadManagerCallback#error(int, String)}. + * + * Note that initialization may fail asynchronously. If you wish to try again after you + * receive such an asynchronous error, you must call dispose() on the instance of + * {@link MbmsDownloadManager} that you received before calling this method again. * * @param context The instance of {@link Context} to use * @param listener A callback to get asynchronous error messages and file service updates. @@ -249,8 +160,16 @@ public class MbmsDownloadManager { public static MbmsDownloadManager create(Context context, MbmsDownloadManagerCallback listener, int subscriptionId) throws MbmsException { + if (!sIsInitialized.compareAndSet(false, true)) { + throw new MbmsException(MbmsException.InitializationErrors.ERROR_DUPLICATE_INITIALIZE); + } MbmsDownloadManager mdm = new MbmsDownloadManager(context, listener, subscriptionId); - mdm.bindAndInitialize(); + try { + mdm.bindAndInitialize(); + } catch (MbmsException e) { + sIsInitialized.set(false); + throw e; + } return mdm; } @@ -266,16 +185,27 @@ public class MbmsDownloadManager { result = downloadService.initialize(mSubscriptionId, mCallback); } catch (RemoteException e) { Log.e(LOG_TAG, "Service died before initialization"); + sIsInitialized.set(false); return; } catch (RuntimeException e) { Log.e(LOG_TAG, "Runtime exception during initialization"); - mCallback.error( + sendErrorToApp( MbmsException.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE, e.toString()); + sIsInitialized.set(false); return; } if (result != MbmsException.SUCCESS) { - mCallback.error(result, "Error returned during initialization"); + sendErrorToApp(result, "Error returned during initialization"); + sIsInitialized.set(false); + return; + } + try { + downloadService.asBinder().linkToDeath(mDeathRecipient, 0); + } catch (RemoteException e) { + sendErrorToApp(MbmsException.ERROR_MIDDLEWARE_LOST, + "Middleware lost during initialization"); + sIsInitialized.set(false); return; } mService.set(downloadService); @@ -283,6 +213,7 @@ public class MbmsDownloadManager { @Override public void onServiceDisconnected(ComponentName name) { + sIsInitialized.set(false); mService.set(null); } }); @@ -292,7 +223,7 @@ public class MbmsDownloadManager { * An inspection API to retrieve the list of available * {@link android.telephony.mbms.FileServiceInfo}s currently being advertised. * The results are returned asynchronously via a call to - * {@link IMbmsDownloadManagerCallback#fileServicesUpdated(List)} + * {@link MbmsDownloadManagerCallback#fileServicesUpdated(List)} * * The serviceClasses argument lets the app filter on types of programming and is opaque data * negotiated beforehand between the app and the carrier. @@ -306,7 +237,7 @@ public class MbmsDownloadManager { * {@link MbmsException.StreamingErrors#ERROR_UNABLE_TO_START_SERVICE} * * @param classList A list of service classes which the app wishes to receive - * {@link IMbmsDownloadManagerCallback#fileServicesUpdated(List)} callbacks + * {@link MbmsDownloadManagerCallback#fileServicesUpdated(List)} callbacks * about. Subsequent calls to this method will replace this list of service * classes (i.e. the middleware will no longer send updates for services * matching classes only in the old list). @@ -336,14 +267,15 @@ public class MbmsDownloadManager { * local instance of {@link android.content.SharedPreferences} and by the middleware. * * If this method is not called at least once before calling - * {@link #download(DownloadRequest, IDownloadCallback)}, the framework + * {@link #download(DownloadRequest, DownloadProgressListener)}, the framework * will default to a directory formed by the concatenation of the app's files directory and * {@link android.telephony.mbms.MbmsTempFileProvider#DEFAULT_TOP_LEVEL_TEMP_DIRECTORY}. * * Before calling this method, the app must cancel all of its pending * {@link DownloadRequest}s via {@link #cancelDownload(DownloadRequest)}. If this is not done, * an {@link MbmsException} will be thrown with code - * {@link MbmsException.DownloadErrors#ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT} + * {@link MbmsException.DownloadErrors#ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT} unless the + * provided directory is the same as what has been previously configured. * * The {@link File} supplied as a root temp file directory must already exist. If not, an * {@link IllegalArgumentException} will be thrown. @@ -384,6 +316,26 @@ public class MbmsDownloadManager { } /** + * Retrieves the currently configured temp file root directory. Returns the file that was + * configured via {@link #setTempFileRootDirectory(File)} or the default directory + * {@link #download(DownloadRequest, DownloadProgressListener)} was called without ever setting + * the temp file root. If neither method has been called since the last time the app's shared + * preferences were reset, returns null. + * + * @return A {@link File} pointing to the configured temp file directory, or null if not yet + * configured. + */ + public @Nullable File getTempFileRootDirectory() { + SharedPreferences prefs = mContext.getSharedPreferences( + MbmsTempFileProvider.TEMP_FILE_ROOT_PREF_FILE_NAME, 0); + String path = prefs.getString(MbmsTempFileProvider.TEMP_FILE_ROOT_PREF_NAME, null); + if (path != null) { + return new File(path); + } + return null; + } + + /** * Requests a download of a file that is available via multicast. * * downloadListener is an optional callback object which can be used to get progress reports @@ -404,7 +356,7 @@ public class MbmsDownloadManager { * @param progressListener Optional listener that will be provided progress updates * if the app is running. */ - public void download(DownloadRequest request, IDownloadProgressListener progressListener) + public void download(DownloadRequest request, DownloadProgressListener progressListener) throws MbmsException { IMbmsDownloadService downloadService = mService.get(); if (downloadService == null) { @@ -434,7 +386,7 @@ public class MbmsDownloadManager { /** * Returns a list of pending {@link DownloadRequest}s that originated from this application. * A pending request is one that was issued via - * {@link #download(DownloadRequest, IDownloadCallback)} but not cancelled through + * {@link #download(DownloadRequest, DownloadProgressListener)} but not cancelled through * {@link #cancelDownload(DownloadRequest)}. * @return A list, possibly empty, of {@link DownloadRequest}s */ @@ -550,43 +502,15 @@ public class MbmsDownloadManager { return; } downloadService.dispose(mSubscriptionId); - mService.set(null); } catch (RemoteException e) { // Ignore Log.i(LOG_TAG, "Remote exception while disposing of service"); + } finally { + mService.set(null); + sIsInitialized.set(false); } } - /** - * Retrieves the {@link ComponentName} for the {@link android.content.BroadcastReceiver} that - * the various intents from the middleware should be targeted towards. - * @param uid The uid of the frontend app. - * @return The component name of the receiver that the middleware should send its intents to, - * or null if the app didn't declare it in the manifest. - * - * @hide - * future systemapi - */ - public static ComponentName getAppReceiverFromUid(Context context, int uid) { - String[] packageNames = context.getPackageManager().getPackagesForUid(uid); - if (packageNames == null) { - return null; - } - - for (String packageName : packageNames) { - ComponentName candidate = new ComponentName(packageName, - MbmsDownloadReceiver.class.getCanonicalName()); - Intent queryIntent = new Intent(); - queryIntent.setComponent(candidate); - List<ResolveInfo> receivers = - context.getPackageManager().queryBroadcastReceivers(queryIntent, 0); - if (receivers != null && receivers.size() > 0) { - return candidate; - } - } - return null; - } - private void writeDownloadRequestToken(DownloadRequest request) { File token = getDownloadRequestTokenPath(request); if (!token.getParentFile().exists()) { @@ -651,4 +575,12 @@ public class MbmsDownloadManager { } } } + + private void sendErrorToApp(int errorCode, String message) { + try { + mCallback.error(errorCode, message); + } catch (RemoteException e) { + // Ignore, should not happen locally. + } + } } diff --git a/telephony/java/android/telephony/MbmsStreamingManager.java b/telephony/java/android/telephony/MbmsStreamingManager.java index d69562cb903e..b6b253ecaddb 100644 --- a/telephony/java/android/telephony/MbmsStreamingManager.java +++ b/telephony/java/android/telephony/MbmsStreamingManager.java @@ -21,8 +21,12 @@ import android.annotation.SystemApi; import android.content.ComponentName; import android.content.Context; import android.content.ServiceConnection; +import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.os.RemoteException; +import android.telephony.mbms.InternalStreamingManagerCallback; +import android.telephony.mbms.InternalStreamingServiceCallback; import android.telephony.mbms.MbmsException; import android.telephony.mbms.MbmsStreamingManagerCallback; import android.telephony.mbms.MbmsUtils; @@ -33,6 +37,7 @@ import android.telephony.mbms.vendor.IMbmsStreamingService; import android.util.Log; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; @@ -53,18 +58,31 @@ public class MbmsStreamingManager { public static final String MBMS_STREAMING_SERVICE_ACTION = "android.telephony.action.EmbmsStreaming"; + private static AtomicBoolean sIsInitialized = new AtomicBoolean(false); + private AtomicReference<IMbmsStreamingService> mService = new AtomicReference<>(null); - private MbmsStreamingManagerCallback mCallbackToApp; + private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { + @Override + public void binderDied() { + sIsInitialized.set(false); + sendErrorToApp(MbmsException.ERROR_MIDDLEWARE_LOST, "Received death notification"); + } + }; + + private InternalStreamingManagerCallback mInternalCallback; private final Context mContext; private int mSubscriptionId = INVALID_SUBSCRIPTION_ID; /** @hide */ private MbmsStreamingManager(Context context, MbmsStreamingManagerCallback callback, - int subscriptionId) { + int subscriptionId, Handler handler) { mContext = context; - mCallbackToApp = callback; mSubscriptionId = subscriptionId; + if (handler == null) { + handler = new Handler(Looper.getMainLooper()); + } + mInternalCallback = new InternalStreamingManagerCallback(callback, handler); } /** @@ -74,27 +92,62 @@ public class MbmsStreamingManager { * main thread. This may throw an {@link MbmsException}, indicating errors that may happen * during the initialization or binding process. * + * + * You may only have one instance of {@link MbmsStreamingManager} per UID. If you call this + * method while there is an active instance of {@link MbmsStreamingManager} in your process + * (in other words, one that has not had {@link #dispose()} called on it), this method will + * throw an {@link MbmsException}. If you call this method in a different process + * running under the same UID, an error will be indicated via + * {@link MbmsStreamingManagerCallback#onError(int, String)}. + * + * Note that initialization may fail asynchronously. If you wish to try again after you + * receive such an asynchronous error, you must call dispose() on the instance of + * {@link MbmsStreamingManager} that you received before calling this method again. + * * @param context The {@link Context} to use. * @param callback A callback object on which you wish to receive results of asynchronous * operations. * @param subscriptionId The subscription ID to use. + * @param handler The handler you wish to receive callbacks on. If null, callbacks will be + * processed on the main looper (in other words, the looper returned from + * {@link Looper#getMainLooper()}). */ public static MbmsStreamingManager create(Context context, - MbmsStreamingManagerCallback callback, int subscriptionId) + MbmsStreamingManagerCallback callback, int subscriptionId, Handler handler) throws MbmsException { - MbmsStreamingManager manager = new MbmsStreamingManager(context, callback, subscriptionId); - manager.bindAndInitialize(); + if (!sIsInitialized.compareAndSet(false, true)) { + throw new MbmsException(MbmsException.InitializationErrors.ERROR_DUPLICATE_INITIALIZE); + } + MbmsStreamingManager manager = new MbmsStreamingManager(context, callback, + subscriptionId, handler); + try { + manager.bindAndInitialize(); + } catch (MbmsException e) { + sIsInitialized.set(false); + throw e; + } return manager; } /** * Create a new MbmsStreamingManager using the system default data subscription ID. - * See {@link #create(Context, MbmsStreamingManagerCallback, int)}. + * See {@link #create(Context, MbmsStreamingManagerCallback, int, Handler)}. + */ + public static MbmsStreamingManager create(Context context, + MbmsStreamingManagerCallback callback, Handler handler) + throws MbmsException { + return create(context, callback, SubscriptionManager.getDefaultSubscriptionId(), handler); + } + + /** + * Create a new MbmsStreamingManager using the system default data subscription ID and + * default {@link Handler}. + * See {@link #create(Context, MbmsStreamingManagerCallback, int, Handler)}. */ public static MbmsStreamingManager create(Context context, MbmsStreamingManagerCallback callback) throws MbmsException { - return create(context, callback, SubscriptionManager.getDefaultSubscriptionId()); + return create(context, callback, SubscriptionManager.getDefaultSubscriptionId(), null); } /** @@ -104,17 +157,19 @@ public class MbmsStreamingManager { * May throw an {@link IllegalStateException} */ public void dispose() { - IMbmsStreamingService streamingService = mService.get(); - if (streamingService == null) { - // Ignore and return, assume already disposed. - return; - } try { + IMbmsStreamingService streamingService = mService.get(); + if (streamingService == null) { + // Ignore and return, assume already disposed. + return; + } streamingService.dispose(mSubscriptionId); } catch (RemoteException e) { // Ignore for now + } finally { + mService.set(null); + sIsInitialized.set(false); } - mService.set(null); } /** @@ -148,16 +203,17 @@ public class MbmsStreamingManager { } catch (RemoteException e) { Log.w(LOG_TAG, "Remote process died"); mService.set(null); + sIsInitialized.set(false); throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST); } } /** - * Starts streaming a requested service, reporting status to the indicated listener. + * Starts streaming a requested service, reporting status to the indicated callback. * Returns an object used to control that stream. The stream may not be ready for consumption * immediately upon return from this method -- wait until the streaming state has been * reported via - * {@link android.telephony.mbms.StreamingServiceCallback#streamStateUpdated(int, int)} + * {@link android.telephony.mbms.StreamingServiceCallback#onStreamStateUpdated(int, int)} * * May throw an * {@link MbmsException} containing any of the error codes in @@ -167,34 +223,44 @@ public class MbmsStreamingManager { * * May also throw an {@link IllegalArgumentException} or an {@link IllegalStateException} * - * Asynchronous errors through the listener include any of the errors in + * Asynchronous errors through the callback include any of the errors in * {@link android.telephony.mbms.MbmsException.GeneralErrors} or * {@link android.telephony.mbms.MbmsException.StreamingErrors}. * * @param serviceInfo The information about the service to stream. - * @param listener A listener that'll be called when something about the stream changes. + * @param callback A callback that'll be called when something about the stream changes. + * @param handler A handler that calls to {@code callback} should be called on. If null, + * defaults to the handler provided via + * {@link #create(Context, MbmsStreamingManagerCallback, int, Handler)}. * @return An instance of {@link StreamingService} through which the stream can be controlled. */ public StreamingService startStreaming(StreamingServiceInfo serviceInfo, - StreamingServiceCallback listener) throws MbmsException { + StreamingServiceCallback callback, Handler handler) throws MbmsException { IMbmsStreamingService streamingService = mService.get(); if (streamingService == null) { throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND); } + InternalStreamingServiceCallback serviceCallback = new InternalStreamingServiceCallback( + callback, handler == null ? mInternalCallback.getHandler() : handler); + + StreamingService serviceForApp = new StreamingService( + mSubscriptionId, streamingService, serviceInfo, serviceCallback); + try { int returnCode = streamingService.startStreaming( - mSubscriptionId, serviceInfo.getServiceId(), listener); + mSubscriptionId, serviceInfo.getServiceId(), serviceCallback); if (returnCode != MbmsException.SUCCESS) { throw new MbmsException(returnCode); } } catch (RemoteException e) { Log.w(LOG_TAG, "Remote process died"); mService.set(null); + sIsInitialized.set(false); throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST); } - return new StreamingService(mSubscriptionId, streamingService, serviceInfo, listener); + return serviceForApp; } private void bindAndInitialize() throws MbmsException { @@ -206,29 +272,34 @@ public class MbmsStreamingManager { IMbmsStreamingService.Stub.asInterface(service); int result; try { - result = streamingService.initialize(mCallbackToApp, mSubscriptionId); + result = streamingService.initialize(mInternalCallback, + mSubscriptionId); } catch (RemoteException e) { Log.e(LOG_TAG, "Service died before initialization"); + sendErrorToApp( + MbmsException.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE, + e.toString()); + sIsInitialized.set(false); return; } catch (RuntimeException e) { Log.e(LOG_TAG, "Runtime exception during initialization"); - try { - mCallbackToApp.error( - MbmsException.InitializationErrors - .ERROR_UNABLE_TO_INITIALIZE, - e.toString()); - } catch (RemoteException e1) { - // ignore - } + sendErrorToApp( + MbmsException.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE, + e.toString()); + sIsInitialized.set(false); return; } if (result != MbmsException.SUCCESS) { - try { - mCallbackToApp.error( - result, "Error returned during initialization"); - } catch (RemoteException e) { - // ignore - } + sendErrorToApp(result, "Error returned during initialization"); + sIsInitialized.set(false); + return; + } + try { + streamingService.asBinder().linkToDeath(mDeathRecipient, 0); + } catch (RemoteException e) { + sendErrorToApp(MbmsException.ERROR_MIDDLEWARE_LOST, + "Middleware lost during initialization"); + sIsInitialized.set(false); return; } mService.set(streamingService); @@ -236,8 +307,17 @@ public class MbmsStreamingManager { @Override public void onServiceDisconnected(ComponentName name) { + sIsInitialized.set(false); mService.set(null); } }); } + + private void sendErrorToApp(int errorCode, String message) { + try { + mInternalCallback.error(errorCode, message); + } catch (RemoteException e) { + // Ignore, should not happen locally. + } + } } diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index 5fb83ab42866..e448fb2a532e 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -795,34 +795,57 @@ public class ServiceState implements Parcelable { return rtString; } + /** + * Convert RIL Service State to String + * + * @param serviceState + * @return String representation of the ServiceState + * + * @hide + */ + public static String rilServiceStateToString(int serviceState) { + switch(serviceState) { + case STATE_IN_SERVICE: + return "IN_SERVICE"; + case STATE_OUT_OF_SERVICE: + return "OUT_OF_SERVICE"; + case STATE_EMERGENCY_ONLY: + return "EMERGENCY_ONLY"; + case STATE_POWER_OFF: + return "POWER_OFF"; + default: + return "UNKNOWN"; + } + } + @Override public String toString() { - String radioTechnology = rilRadioTechnologyToString(mRilVoiceRadioTechnology); - String dataRadioTechnology = rilRadioTechnologyToString(mRilDataRadioTechnology); - - return (mVoiceRegState + " " + mDataRegState - + " " - + "voice " + getRoamingLogString(mVoiceRoamingType) - + " " - + "data " + getRoamingLogString(mDataRoamingType) - + " " + mVoiceOperatorAlphaLong - + " " + mVoiceOperatorAlphaShort - + " " + mVoiceOperatorNumeric - + " " + mDataOperatorAlphaLong - + " " + mDataOperatorAlphaShort - + " " + mDataOperatorNumeric - + " " + (mIsManualNetworkSelection ? "(manual)" : "") - + " " + radioTechnology - + " " + dataRadioTechnology - + " " + (mCssIndicator ? "CSS supported" : "CSS not supported") - + " " + mNetworkId - + " " + mSystemId - + " RoamInd=" + mCdmaRoamingIndicator - + " DefRoamInd=" + mCdmaDefaultRoamingIndicator - + " EmergOnly=" + mIsEmergencyOnly - + " IsDataRoamingFromRegistration=" + mIsDataRoamingFromRegistration - + " IsUsingCarrierAggregation=" + mIsUsingCarrierAggregation - + " mLteEarfcnRsrpBoost=" + mLteEarfcnRsrpBoost); + return new StringBuilder().append("{mVoiceRegState=").append(mVoiceRegState) + .append("(" + rilServiceStateToString(mVoiceRegState) + ")") + .append(", mDataRegState=").append(mDataRegState) + .append("(" + rilServiceStateToString(mDataRegState) + ")") + .append(", mVoiceRoamingType=").append(getRoamingLogString(mVoiceRoamingType)) + .append(", mDataRoamingType=").append(getRoamingLogString(mDataRoamingType)) + .append(", mVoiceOperatorAlphaLong=").append(mVoiceOperatorAlphaLong) + .append(", mVoiceOperatorAlphaShort=").append(mVoiceOperatorAlphaShort) + .append(", mDataOperatorAlphaLong=").append(mDataOperatorAlphaLong) + .append(", mDataOperatorAlphaShort=").append(mDataOperatorAlphaShort) + .append(", isManualNetworkSelection=").append(mIsManualNetworkSelection) + .append(mIsManualNetworkSelection ? "(manual)" : "(automatic)") + .append(", mRilVoiceRadioTechnology=").append(mRilVoiceRadioTechnology) + .append("(" + rilRadioTechnologyToString(mRilVoiceRadioTechnology) + ")") + .append(", mRilDataRadioTechnology=").append(mRilDataRadioTechnology) + .append("(" + rilRadioTechnologyToString(mRilDataRadioTechnology) + ")") + .append(", mCssIndicator=").append(mCssIndicator ? "supported" : "unsupported") + .append(", mNetworkId=").append(mNetworkId) + .append(", mSystemId=").append(mSystemId) + .append(", mCdmaRoamingIndicator=").append(mCdmaRoamingIndicator) + .append(", mCdmaDefaultRoamingIndicator=").append(mCdmaDefaultRoamingIndicator) + .append(", mIsEmergencyOnly=").append(mIsEmergencyOnly) + .append(", mIsDataRoamingFromRegistration=").append(mIsDataRoamingFromRegistration) + .append(", mIsUsingCarrierAggregation=").append(mIsUsingCarrierAggregation) + .append(", mLteEarfcnRsrpBoost=").append(mLteEarfcnRsrpBoost) + .append("}").toString(); } private void setNullState(int state) { diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index 1eac263133e5..6029995f2468 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -1131,10 +1131,14 @@ public final class SmsManager { static public final int RESULT_ERROR_NULL_PDU = 3; /** Failed because service is currently unavailable */ static public final int RESULT_ERROR_NO_SERVICE = 4; - /** Failed because we reached the sending queue limit. {@hide} */ + /** Failed because we reached the sending queue limit. */ static public final int RESULT_ERROR_LIMIT_EXCEEDED = 5; /** Failed because FDN is enabled. {@hide} */ static public final int RESULT_ERROR_FDN_CHECK_FAILURE = 6; + /** Failed because user denied the sending of this short code. */ + static public final int RESULT_ERROR_SHORT_CODE_NOT_ALLOWED = 7; + /** Failed because the user has denied this app ever send premium short codes. */ + static public final int RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED = 8; static private final String PHONE_PACKAGE_NAME = "com.android.phone"; diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 18c1923924bb..b3c80ed5748f 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -137,7 +137,7 @@ public class TelephonyManager { /** @hide */ - static public final int KEY_TYPE_EPDDG = 1; + static public final int KEY_TYPE_EPDG = 1; /** @hide */ static public final int KEY_TYPE_WLAN = 2; @@ -2372,31 +2372,73 @@ public class TelephonyManager { * Requires Permission: * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} * @param keyType whether the key is being used for wlan or epdg. Valid key types are - * {@link TelephonyManager#KEY_TYPE_EPDDG} or + * {@link TelephonyManager#KEY_TYPE_EPDG} or * {@link TelephonyManager#KEY_TYPE_WLAN}. * @return ImsiEncryptionInfo Carrier specific information that will be used to encrypt the * IMSI and IMPI. This includes the public key and the key identifier. This information - * will be stored in the device keystore. + * will be stored in the device keystore. The system will return a null when no key was + * found, and the carrier does not require a key. The system will throw the following + * exceptions: + * 1. IllegalArgumentException when an invalid key is sent. + * 2. RuntimeException if the key is required but not found; and also if there was an + * internal exception. * @hide */ public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType) { try { IPhoneSubInfo info = getSubscriberInfo(); - if (info == null) return null; + if (info == null) { + throw new RuntimeException("IMSI error: Subscriber Info is null"); + } int subId = getSubId(SubscriptionManager.getDefaultDataSubscriptionId()); - if (keyType != KEY_TYPE_EPDDG && keyType != KEY_TYPE_WLAN) { - throw new IllegalArgumentException("Invalid key type"); + if (keyType != KEY_TYPE_EPDG && keyType != KEY_TYPE_WLAN) { + throw new IllegalArgumentException("IMSI error: Invalid key type"); + } + ImsiEncryptionInfo imsiEncryptionInfo = info.getCarrierInfoForImsiEncryption( + subId, keyType, mContext.getOpPackageName()); + if (imsiEncryptionInfo == null + && isImsiEncryptionRequired(subId, keyType)) { + Rlog.e(TAG, "IMSI error: key is required but not found"); + throw new RuntimeException("IMSI error: key is required but not found"); } - return info.getCarrierInfoForImsiEncryption(subId, keyType, - mContext.getOpPackageName()); + return imsiEncryptionInfo; } catch (RemoteException ex) { - Rlog.e(TAG, "getCarrierInfoForImsiEncryption RemoteException", ex); - return null; + Rlog.e(TAG, "getCarrierInfoForImsiEncryption RemoteException" + ex); + throw new RuntimeException("IMSI error: Remote Exception"); } catch (NullPointerException ex) { // This could happen before phone restarts due to crashing - Rlog.e(TAG, "getCarrierInfoForImsiEncryption NullPointerException", ex); - return null; + Rlog.e(TAG, "getCarrierInfoForImsiEncryption NullPointerException" + ex); + throw new RuntimeException("IMSI error: Null Pointer exception"); + } + } + + /** + * @param keyAvailability bitmask that defines the availabilty of keys for a type. + * @param keyType the key type which is being checked. (WLAN, EPDG) + * @return true if the digit at position keyType is 1, else false. + * @hide + */ + private static boolean isKeyEnabled(int keyAvailability, int keyType) { + int returnValue = (keyAvailability >> (keyType - 1)) & 1; + return (returnValue == 1) ? true : false; + } + + /** + * If Carrier requires Imsi to be encrypted. + * @hide + */ + private boolean isImsiEncryptionRequired(int subId, int keyType) { + CarrierConfigManager configManager = + (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); + if (configManager == null) { + return false; + } + PersistableBundle pb = configManager.getConfigForSubId(subId); + if (pb == null) { + return false; } + int keyAvailability = pb.getInt(CarrierConfigManager.IMSI_KEY_AVAILABILITY_INT); + return isKeyEnabled(keyAvailability, keyType); } /** @@ -6699,11 +6741,13 @@ public class TelephonyManager { * Get aggregated video call data usage since boot. * Permissions android.Manifest.permission.READ_NETWORK_USAGE_HISTORY is required. * - * @param perUidStats True if requesting data usage per uid, otherwise overall usage. + * @param how one of the NetworkStats.STATS_PER_* constants depending on whether the request is + * for data usage per uid or overall usage. * @return Snapshot of video call data usage * @hide */ - public NetworkStats getVtDataUsage(boolean perUidStats) { + public NetworkStats getVtDataUsage(int how) { + boolean perUidStats = (how == NetworkStats.STATS_PER_UID); try { ITelephony service = getITelephony(); if (service != null) { diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java index 8304d84d8a2b..a13af5f4b90b 100644 --- a/telephony/java/android/telephony/euicc/EuiccManager.java +++ b/telephony/java/android/telephony/euicc/EuiccManager.java @@ -154,6 +154,14 @@ public class EuiccManager { "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT"; /** + * Key for an extra set on the {@link #ACTION_PROVISION_EMBEDDED_SUBSCRIPTION} intent for + * whether the user choses to use eUICC to set up network in SUW. + * @hide + */ + public static final String EXTRA_FORCE_PROVISION = + "android.telephony.euicc.extra.FORCE_PROVISION"; + + /** * Optional meta-data attribute for a carrier app providing an icon to use to represent the * carrier. If not provided, the app's launcher icon will be used as a fallback. */ diff --git a/telephony/java/android/telephony/mbms/DownloadProgressListener.java b/telephony/java/android/telephony/mbms/DownloadProgressListener.java index d6bd5dca8781..d91e9ad24a9a 100644 --- a/telephony/java/android/telephony/mbms/DownloadProgressListener.java +++ b/telephony/java/android/telephony/mbms/DownloadProgressListener.java @@ -16,6 +16,8 @@ package android.telephony.mbms; +import android.os.RemoteException; + /** * A optional listener class used by download clients to track progress. * @hide @@ -38,8 +40,9 @@ public class DownloadProgressListener extends IDownloadProgressListener.Stub { * @param currentDecodedSize is the number of bytes that have been decoded. * @param fullDecodedSize is the total number of bytes that make up the final decoded content. */ + @Override public void progress(DownloadRequest request, FileInfo fileInfo, int currentDownloadSize, int fullDownloadSize, - int currentDecodedSize, int fullDecodedSize) { + int currentDecodedSize, int fullDecodedSize) throws RemoteException { } } diff --git a/telephony/java/android/telephony/mbms/DownloadRequest.java b/telephony/java/android/telephony/mbms/DownloadRequest.java index 01e0bbdfc0a0..eae9011e42c8 100644 --- a/telephony/java/android/telephony/mbms/DownloadRequest.java +++ b/telephony/java/android/telephony/mbms/DownloadRequest.java @@ -25,6 +25,7 @@ import android.util.Log; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; @@ -77,12 +78,18 @@ public class DownloadRequest implements Parcelable { private String appIntent; private int version = CURRENT_VERSION; + /** + * Sets the service from which the download request to be built will download from. + * @param serviceInfo + * @return + */ public Builder setServiceInfo(FileServiceInfo serviceInfo) { fileServiceId = serviceInfo.getServiceId(); return this; } /** + * Set the service ID for the download request. For use by the middleware only. * @hide * TODO: systemapi */ @@ -91,11 +98,23 @@ public class DownloadRequest implements Parcelable { return this; } + /** + * Sets the source URI for the download request to be built. + * @param source + * @return + */ public Builder setSource(Uri source) { this.source = source; return this; } + /** + * Sets the destination URI for the download request to be built. The middleware should + * not set this directly. + * @param dest A URI obtained from {@link Uri#fromFile(File)}, denoting the requested + * final destination of the download. + * @return + */ public Builder setDest(Uri dest) { if (dest.toString().length() > MAX_DESTINATION_URI_SIZE) { throw new IllegalArgumentException("Destination uri must not exceed length " + @@ -105,11 +124,25 @@ public class DownloadRequest implements Parcelable { return this; } - public Builder setSubscriptionId(int sub) { - this.subscriptionId = sub; + /** + * Set the subscription ID on which the file(s) should be downloaded. + * @param subscriptionId + * @return + */ + public Builder setSubscriptionId(int subscriptionId) { + this.subscriptionId = subscriptionId; return this; } + /** + * Set the {@link Intent} that should be sent when the download completes or fails. This + * should be an intent with a explicit {@link android.content.ComponentName} targeted to a + * {@link android.content.BroadcastReceiver} in the app's package. + * + * The middleware should not use this method. + * @param intent + * @return + */ public Builder setAppIntent(Intent intent) { this.appIntent = intent.toUri(0); if (this.appIntent.length() > MAX_APP_INTENT_SIZE) { @@ -120,7 +153,12 @@ public class DownloadRequest implements Parcelable { } /** - * For use by middleware only + * For use by the middleware to set the byte array of opaque data. The opaque data + * includes information about the download request that is used by the client app and the + * manager code, but is irrelevant to the middleware. + * @param data A byte array, the contents of which should have been originally obtained + * from {@link DownloadRequest#getOpaqueData()}. + * @return * TODO: systemapi * @hide */ @@ -201,22 +239,40 @@ public class DownloadRequest implements Parcelable { out.writeInt(version); } + /** + * @return The ID of the file service to download from. + */ public String getFileServiceId() { return fileServiceId; } + /** + * @return The source URI to download from + */ public Uri getSourceUri() { return sourceUri; } + /** + * For use by the client app only. + * @return The URI of the final destination of the download. + */ public Uri getDestinationUri() { return destinationUri; } + /** + * @return The subscription ID on which to perform MBMS operations. + */ public int getSubscriptionId() { return subscriptionId; } + /** + * For internal use -- returns the intent to send to the app after download completion or + * failure. + * @hide + */ public Intent getIntentForApp() { try { return Intent.parseUri(serializedResultIntentForApp, 0); @@ -226,6 +282,10 @@ public class DownloadRequest implements Parcelable { } /** + * For use by the middleware only. The byte array returned from this method should be + * persisted and sent back to the app upon download completion or failure by passing it into + * {@link Builder#setOpaqueData(byte[])}. + * @return A byte array of opaque data to persist. * @hide * TODO: systemapi */ diff --git a/telephony/java/android/telephony/mbms/FileInfo.java b/telephony/java/android/telephony/mbms/FileInfo.java index b8e1c49f6b4a..f97131dda427 100644 --- a/telephony/java/android/telephony/mbms/FileInfo.java +++ b/telephony/java/android/telephony/mbms/FileInfo.java @@ -38,16 +38,6 @@ public class FileInfo implements Parcelable { */ private final String mimeType; - /** - * The size of the file in bytes. - */ - private final long size; - - /** - * The MD5 hash of the file. - */ - private final byte md5Hash[]; - public static final Parcelable.Creator<FileInfo> CREATOR = new Parcelable.Creator<FileInfo>() { @Override @@ -65,29 +55,20 @@ public class FileInfo implements Parcelable { * @hide * TODO: systemapi */ - public FileInfo(Uri uri, String mimeType, long size, byte[] md5Hash) { + public FileInfo(Uri uri, String mimeType) { this.uri = uri; this.mimeType = mimeType; - this.size = size; - this.md5Hash = md5Hash; } private FileInfo(Parcel in) { uri = in.readParcelable(null); mimeType = in.readString(); - size = in.readLong(); - int arraySize = in.readInt(); - md5Hash = new byte[arraySize]; - in.readByteArray(md5Hash); } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeParcelable(uri, flags); dest.writeString(mimeType); - dest.writeLong(size); - dest.writeInt(md5Hash.length); - dest.writeByteArray(md5Hash); } @Override @@ -102,12 +83,4 @@ public class FileInfo implements Parcelable { public String getMimeType() { return mimeType; } - - public long getSize() { - return size; - } - - public byte[] getMd5Hash() { - return md5Hash; - } } diff --git a/telephony/java/android/telephony/mbms/InternalStreamingManagerCallback.java b/telephony/java/android/telephony/mbms/InternalStreamingManagerCallback.java new file mode 100644 index 000000000000..b52df8c0dd84 --- /dev/null +++ b/telephony/java/android/telephony/mbms/InternalStreamingManagerCallback.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.telephony.mbms; + +import android.os.Handler; +import android.os.RemoteException; +import android.telephony.mbms.IMbmsStreamingManagerCallback; +import android.telephony.mbms.MbmsStreamingManagerCallback; +import android.telephony.mbms.StreamingServiceInfo; + +import java.util.List; + +/** @hide */ +public class InternalStreamingManagerCallback extends IMbmsStreamingManagerCallback.Stub { + private final Handler mHandler; + private final MbmsStreamingManagerCallback mAppCallback; + + public InternalStreamingManagerCallback(MbmsStreamingManagerCallback appCallback, + Handler handler) { + mAppCallback = appCallback; + mHandler = handler; + } + + @Override + public void error(int errorCode, String message) throws RemoteException { + mHandler.post(new Runnable() { + @Override + public void run() { + mAppCallback.onError(errorCode, message); + } + }); + } + + @Override + public void streamingServicesUpdated(List<StreamingServiceInfo> services) + throws RemoteException { + mHandler.post(new Runnable() { + @Override + public void run() { + mAppCallback.onStreamingServicesUpdated(services); + } + }); + } + + @Override + public void middlewareReady() throws RemoteException { + mHandler.post(new Runnable() { + @Override + public void run() { + mAppCallback.onMiddlewareReady(); + } + }); + } + + public Handler getHandler() { + return mHandler; + } +} diff --git a/telephony/java/android/telephony/mbms/InternalStreamingServiceCallback.java b/telephony/java/android/telephony/mbms/InternalStreamingServiceCallback.java new file mode 100644 index 000000000000..bb337b271cf0 --- /dev/null +++ b/telephony/java/android/telephony/mbms/InternalStreamingServiceCallback.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.telephony.mbms; + +import android.os.Handler; +import android.os.RemoteException; + +/** @hide */ +public class InternalStreamingServiceCallback extends IStreamingServiceCallback.Stub { + private final StreamingServiceCallback mAppCallback; + private final Handler mHandler; + + public InternalStreamingServiceCallback(StreamingServiceCallback appCallback, Handler handler) { + mAppCallback = appCallback; + mHandler = handler; + } + + @Override + public void error(int errorCode, String message) throws RemoteException { + mHandler.post(new Runnable() { + @Override + public void run() { + mAppCallback.onError(errorCode, message); + } + }); + } + + @Override + public void streamStateUpdated(int state, int reason) throws RemoteException { + mHandler.post(new Runnable() { + @Override + public void run() { + mAppCallback.onStreamStateUpdated(state, reason); + } + }); + } + + @Override + public void mediaDescriptionUpdated() throws RemoteException { + mHandler.post(new Runnable() { + @Override + public void run() { + mAppCallback.onMediaDescriptionUpdated(); + } + }); + } + + @Override + public void broadcastSignalStrengthUpdated(int signalStrength) throws RemoteException { + mHandler.post(new Runnable() { + @Override + public void run() { + mAppCallback.onBroadcastSignalStrengthUpdated(signalStrength); + } + }); + } + + @Override + public void streamMethodUpdated(int methodType) throws RemoteException { + mHandler.post(new Runnable() { + @Override + public void run() { + mAppCallback.onStreamMethodUpdated(methodType); + } + }); + } +} diff --git a/telephony/java/android/telephony/mbms/MbmsDownloadManagerCallback.java b/telephony/java/android/telephony/mbms/MbmsDownloadManagerCallback.java index ba25f663ffb4..17291d09215d 100644 --- a/telephony/java/android/telephony/mbms/MbmsDownloadManagerCallback.java +++ b/telephony/java/android/telephony/mbms/MbmsDownloadManagerCallback.java @@ -16,6 +16,9 @@ package android.telephony.mbms; +import android.os.RemoteException; +import android.telephony.MbmsDownloadManager; + import java.util.List; /** @@ -24,12 +27,8 @@ import java.util.List; */ public class MbmsDownloadManagerCallback extends IMbmsDownloadManagerCallback.Stub { - public final static int ERROR_CARRIER_NOT_SUPPORTED = 1; - public final static int ERROR_UNABLE_TO_INITIALIZE = 2; - public final static int ERROR_UNABLE_TO_ALLOCATE_MEMORY = 3; - - - public void error(int errorCode, String message) { + @Override + public void error(int errorCode, String message) throws RemoteException { // default implementation empty } @@ -45,7 +44,8 @@ public class MbmsDownloadManagerCallback extends IMbmsDownloadManagerCallback.St * @param services a List of FileServiceInfos * */ - public void fileServicesUpdated(List<FileServiceInfo> services) { + @Override + public void fileServicesUpdated(List<FileServiceInfo> services) throws RemoteException { // default implementation empty } @@ -58,7 +58,7 @@ public class MbmsDownloadManagerCallback extends IMbmsDownloadManagerCallback.St * or {@link MbmsException.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY} */ @Override - public void middlewareReady() { + public void middlewareReady() throws RemoteException { // default implementation empty } } diff --git a/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java b/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java index 339ff3985bff..ba7d120a3b7c 100644 --- a/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java +++ b/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java @@ -25,6 +25,7 @@ import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.telephony.MbmsDownloadManager; +import android.telephony.mbms.vendor.VendorIntents; import android.util.Log; import java.io.File; @@ -56,9 +57,9 @@ public class MbmsDownloadReceiver extends BroadcastReceiver { /** * Indicates that the intent sent had an invalid action. This will be the result if * {@link Intent#getAction()} returns anything other than - * {@link MbmsDownloadManager#ACTION_DOWNLOAD_RESULT_INTERNAL}, - * {@link MbmsDownloadManager#ACTION_FILE_DESCRIPTOR_REQUEST}, or - * {@link MbmsDownloadManager#ACTION_CLEANUP}. + * {@link VendorIntents#ACTION_DOWNLOAD_RESULT_INTERNAL}, + * {@link VendorIntents#ACTION_FILE_DESCRIPTOR_REQUEST}, or + * {@link VendorIntents#ACTION_CLEANUP}. * This is a fatal result code and no result extras should be expected. */ public static final int RESULT_INVALID_ACTION = 1; @@ -70,7 +71,7 @@ public class MbmsDownloadReceiver extends BroadcastReceiver { public static final int RESULT_MALFORMED_INTENT = 2; /** - * Indicates that the supplied value for {@link MbmsDownloadManager#EXTRA_TEMP_FILE_ROOT} + * Indicates that the supplied value for {@link VendorIntents#EXTRA_TEMP_FILE_ROOT} * does not match what the app has stored. * This is a fatal result code and no result extras should be expected. */ @@ -104,18 +105,18 @@ public class MbmsDownloadReceiver extends BroadcastReceiver { setResultCode(RESULT_MALFORMED_INTENT); return; } - if (!Objects.equals(intent.getStringExtra(MbmsDownloadManager.EXTRA_TEMP_FILE_ROOT), + if (!Objects.equals(intent.getStringExtra(VendorIntents.EXTRA_TEMP_FILE_ROOT), MbmsTempFileProvider.getEmbmsTempFileDir(context).getPath())) { setResultCode(RESULT_BAD_TEMP_FILE_ROOT); return; } - if (MbmsDownloadManager.ACTION_DOWNLOAD_RESULT_INTERNAL.equals(intent.getAction())) { + if (VendorIntents.ACTION_DOWNLOAD_RESULT_INTERNAL.equals(intent.getAction())) { moveDownloadedFile(context, intent); cleanupPostMove(context, intent); - } else if (MbmsDownloadManager.ACTION_FILE_DESCRIPTOR_REQUEST.equals(intent.getAction())) { + } else if (VendorIntents.ACTION_FILE_DESCRIPTOR_REQUEST.equals(intent.getAction())) { generateTempFiles(context, intent); - } else if (MbmsDownloadManager.ACTION_CLEANUP.equals(intent.getAction())) { + } else if (VendorIntents.ACTION_CLEANUP.equals(intent.getAction())) { cleanupTempFiles(context, intent); } else { setResultCode(RESULT_INVALID_ACTION); @@ -123,16 +124,16 @@ public class MbmsDownloadReceiver extends BroadcastReceiver { } private boolean verifyIntentContents(Context context, Intent intent) { - if (MbmsDownloadManager.ACTION_DOWNLOAD_RESULT_INTERNAL.equals(intent.getAction())) { + if (VendorIntents.ACTION_DOWNLOAD_RESULT_INTERNAL.equals(intent.getAction())) { if (!intent.hasExtra(MbmsDownloadManager.EXTRA_RESULT)) { Log.w(LOG_TAG, "Download result did not include a result code. Ignoring."); return false; } - if (!intent.hasExtra(MbmsDownloadManager.EXTRA_REQUEST)) { + if (!intent.hasExtra(VendorIntents.EXTRA_REQUEST)) { Log.w(LOG_TAG, "Download result did not include the associated request. Ignoring."); return false; } - if (!intent.hasExtra(MbmsDownloadManager.EXTRA_TEMP_FILE_ROOT)) { + if (!intent.hasExtra(VendorIntents.EXTRA_TEMP_FILE_ROOT)) { Log.w(LOG_TAG, "Download result did not include the temp file root. Ignoring."); return false; } @@ -141,12 +142,12 @@ public class MbmsDownloadReceiver extends BroadcastReceiver { "Ignoring."); return false; } - if (!intent.hasExtra(MbmsDownloadManager.EXTRA_FINAL_URI)) { + if (!intent.hasExtra(VendorIntents.EXTRA_FINAL_URI)) { Log.w(LOG_TAG, "Download result did not include the path to the final " + "temp file. Ignoring."); return false; } - DownloadRequest request = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_REQUEST); + DownloadRequest request = intent.getParcelableExtra(VendorIntents.EXTRA_REQUEST); String expectedTokenFileName = request.getHash() + DOWNLOAD_TOKEN_SUFFIX; File expectedTokenFile = new File( MbmsUtils.getEmbmsTempFileDirForService(context, request.getFileServiceId()), @@ -156,27 +157,27 @@ public class MbmsDownloadReceiver extends BroadcastReceiver { "Expected " + expectedTokenFile); return false; } - } else if (MbmsDownloadManager.ACTION_FILE_DESCRIPTOR_REQUEST.equals(intent.getAction())) { - if (!intent.hasExtra(MbmsDownloadManager.EXTRA_SERVICE_INFO)) { + } else if (VendorIntents.ACTION_FILE_DESCRIPTOR_REQUEST.equals(intent.getAction())) { + if (!intent.hasExtra(VendorIntents.EXTRA_SERVICE_INFO)) { Log.w(LOG_TAG, "Temp file request did not include the associated service info." + " Ignoring."); return false; } - if (!intent.hasExtra(MbmsDownloadManager.EXTRA_TEMP_FILE_ROOT)) { + if (!intent.hasExtra(VendorIntents.EXTRA_TEMP_FILE_ROOT)) { Log.w(LOG_TAG, "Download result did not include the temp file root. Ignoring."); return false; } - } else if (MbmsDownloadManager.ACTION_CLEANUP.equals(intent.getAction())) { - if (!intent.hasExtra(MbmsDownloadManager.EXTRA_SERVICE_INFO)) { + } else if (VendorIntents.ACTION_CLEANUP.equals(intent.getAction())) { + if (!intent.hasExtra(VendorIntents.EXTRA_SERVICE_INFO)) { Log.w(LOG_TAG, "Cleanup request did not include the associated service info." + " Ignoring."); return false; } - if (!intent.hasExtra(MbmsDownloadManager.EXTRA_TEMP_FILE_ROOT)) { + if (!intent.hasExtra(VendorIntents.EXTRA_TEMP_FILE_ROOT)) { Log.w(LOG_TAG, "Cleanup request did not include the temp file root. Ignoring."); return false; } - if (!intent.hasExtra(MbmsDownloadManager.EXTRA_TEMP_FILES_IN_USE)) { + if (!intent.hasExtra(VendorIntents.EXTRA_TEMP_FILES_IN_USE)) { Log.w(LOG_TAG, "Cleanup request did not include the list of temp files in use. " + "Ignoring."); return false; @@ -186,7 +187,7 @@ public class MbmsDownloadReceiver extends BroadcastReceiver { } private void moveDownloadedFile(Context context, Intent intent) { - DownloadRequest request = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_REQUEST); + DownloadRequest request = intent.getParcelableExtra(VendorIntents.EXTRA_REQUEST); Intent intentForApp = request.getIntentForApp(); int result = intent.getIntExtra(MbmsDownloadManager.EXTRA_RESULT, @@ -200,7 +201,7 @@ public class MbmsDownloadReceiver extends BroadcastReceiver { } Uri destinationUri = request.getDestinationUri(); - Uri finalTempFile = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_FINAL_URI); + Uri finalTempFile = intent.getParcelableExtra(VendorIntents.EXTRA_FINAL_URI); if (!verifyTempFilePath(context, request.getFileServiceId(), finalTempFile)) { Log.w(LOG_TAG, "Download result specified an invalid temp file " + finalTempFile); setResultCode(RESULT_DOWNLOAD_FINALIZATION_ERROR); @@ -225,13 +226,13 @@ public class MbmsDownloadReceiver extends BroadcastReceiver { } private void cleanupPostMove(Context context, Intent intent) { - DownloadRequest request = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_REQUEST); + DownloadRequest request = intent.getParcelableExtra(VendorIntents.EXTRA_REQUEST); if (request == null) { Log.w(LOG_TAG, "Intent does not include a DownloadRequest. Ignoring."); return; } - List<Uri> tempFiles = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_TEMP_LIST); + List<Uri> tempFiles = intent.getParcelableExtra(VendorIntents.EXTRA_TEMP_LIST); if (tempFiles == null) { return; } @@ -246,15 +247,15 @@ public class MbmsDownloadReceiver extends BroadcastReceiver { private void generateTempFiles(Context context, Intent intent) { FileServiceInfo serviceInfo = - intent.getParcelableExtra(MbmsDownloadManager.EXTRA_SERVICE_INFO); + intent.getParcelableExtra(VendorIntents.EXTRA_SERVICE_INFO); if (serviceInfo == null) { Log.w(LOG_TAG, "Temp file request did not include the associated service info. " + "Ignoring."); setResultCode(RESULT_MALFORMED_INTENT); return; } - int fdCount = intent.getIntExtra(MbmsDownloadManager.EXTRA_FD_COUNT, 0); - List<Uri> pausedList = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_PAUSED_LIST); + int fdCount = intent.getIntExtra(VendorIntents.EXTRA_FD_COUNT, 0); + List<Uri> pausedList = intent.getParcelableExtra(VendorIntents.EXTRA_PAUSED_LIST); if (fdCount == 0 && (pausedList == null || pausedList.size() == 0)) { Log.i(LOG_TAG, "No temp files actually requested. Ending."); @@ -269,8 +270,8 @@ public class MbmsDownloadReceiver extends BroadcastReceiver { generateUrisForPausedFiles(context, serviceInfo, pausedList); Bundle result = new Bundle(); - result.putParcelableArrayList(MbmsDownloadManager.EXTRA_FREE_URI_LIST, freshTempFiles); - result.putParcelableArrayList(MbmsDownloadManager.EXTRA_PAUSED_URI_LIST, pausedFiles); + result.putParcelableArrayList(VendorIntents.EXTRA_FREE_URI_LIST, freshTempFiles); + result.putParcelableArrayList(VendorIntents.EXTRA_PAUSED_URI_LIST, pausedFiles); setResultCode(RESULT_OK); setResultExtras(result); } @@ -353,11 +354,11 @@ public class MbmsDownloadReceiver extends BroadcastReceiver { private void cleanupTempFiles(Context context, Intent intent) { FileServiceInfo serviceInfo = - intent.getParcelableExtra(MbmsDownloadManager.EXTRA_SERVICE_INFO); + intent.getParcelableExtra(VendorIntents.EXTRA_SERVICE_INFO); File tempFileDir = MbmsUtils.getEmbmsTempFileDirForService(context, serviceInfo.getServiceId()); final List<Uri> filesInUse = - intent.getParcelableArrayListExtra(MbmsDownloadManager.EXTRA_TEMP_FILES_IN_USE); + intent.getParcelableArrayListExtra(VendorIntents.EXTRA_TEMP_FILES_IN_USE); File[] filesToDelete = tempFileDir.listFiles(new FileFilter() { @Override public boolean accept(File file) { diff --git a/telephony/java/android/telephony/mbms/MbmsException.java b/telephony/java/android/telephony/mbms/MbmsException.java index f51563a1cccb..6de5a18ebaf5 100644 --- a/telephony/java/android/telephony/mbms/MbmsException.java +++ b/telephony/java/android/telephony/mbms/MbmsException.java @@ -43,6 +43,7 @@ public class MbmsException extends Exception { * middleware. They are applicable to both streaming and file-download use-cases. */ public static class InitializationErrors { + private InitializationErrors() {} /** * Indicates that the app tried to create more than one instance each of * {@link android.telephony.MbmsStreamingManager} or @@ -60,9 +61,10 @@ public class MbmsException extends Exception { * streaming and file-download. */ public static class GeneralErrors { + private GeneralErrors() {} /** * Indicates that the app attempted to perform an operation before receiving notification - * that the middleware is ready via {@link MbmsStreamingManagerCallback#middlewareReady()} + * that the middleware is ready via {@link MbmsStreamingManagerCallback#onMiddlewareReady()} * or TODO: link MbmsDownloadManagerCallback#middlewareReady */ public static final int ERROR_MIDDLEWARE_NOT_YET_READY = 201; @@ -96,6 +98,7 @@ public class MbmsException extends Exception { * Indicates the errors that are applicable only to the streaming use-case */ public static class StreamingErrors { + private StreamingErrors() {} /** Indicates that the middleware cannot start a stream due to too many ongoing streams */ public static final int ERROR_CONCURRENT_SERVICE_LIMIT_REACHED = 301; @@ -104,7 +107,8 @@ public class MbmsException extends Exception { /** * Indicates that the app called - * {@link android.telephony.MbmsStreamingManager#startStreaming(StreamingServiceInfo, StreamingServiceCallback)} + * {@link android.telephony.MbmsStreamingManager#startStreaming( + * StreamingServiceInfo, StreamingServiceCallback, android.os.Handler)} * more than once for the same {@link StreamingServiceInfo}. */ public static final int ERROR_DUPLICATE_START_STREAM = 303; diff --git a/telephony/java/android/telephony/mbms/MbmsStreamingManagerCallback.java b/telephony/java/android/telephony/mbms/MbmsStreamingManagerCallback.java index f67d6e4b96c3..b31ffa72781f 100644 --- a/telephony/java/android/telephony/mbms/MbmsStreamingManagerCallback.java +++ b/telephony/java/android/telephony/mbms/MbmsStreamingManagerCallback.java @@ -18,6 +18,7 @@ package android.telephony.mbms; import android.content.Context; import android.os.RemoteException; +import android.telephony.MbmsStreamingManager; import java.util.List; @@ -26,14 +27,14 @@ import java.util.List; * services. An instance of this object should be passed into * {@link android.telephony.MbmsStreamingManager#create(Context, MbmsStreamingManagerCallback)}. */ -public class MbmsStreamingManagerCallback extends IMbmsStreamingManagerCallback.Stub { +public class MbmsStreamingManagerCallback { /** * Called by the middleware when it has detected an error condition. The possible error codes * are listed in {@link MbmsException}. * @param errorCode The error code. * @param message A human-readable message generated by the middleware for debugging purposes. */ - public void error(int errorCode, String message) throws RemoteException { + public void onError(int errorCode, String message) { // default implementation empty } @@ -49,8 +50,7 @@ public class MbmsStreamingManagerCallback extends IMbmsStreamingManagerCallback. * @param services a List of StreamingServiceInfos * */ - public void streamingServicesUpdated(List<StreamingServiceInfo> services) - throws RemoteException { + public void onStreamingServicesUpdated(List<StreamingServiceInfo> services) { // default implementation empty } @@ -62,8 +62,7 @@ public class MbmsStreamingManagerCallback extends IMbmsStreamingManagerCallback. * being thrown with error code {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND} * or {@link MbmsException.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY} */ - @Override - public void middlewareReady() throws RemoteException { + public void onMiddlewareReady() { // default implementation empty } } diff --git a/telephony/java/android/telephony/mbms/ServiceInfo.java b/telephony/java/android/telephony/mbms/ServiceInfo.java index e1ccd439fa41..c01604b0a1bf 100644 --- a/telephony/java/android/telephony/mbms/ServiceInfo.java +++ b/telephony/java/android/telephony/mbms/ServiceInfo.java @@ -33,7 +33,7 @@ import java.util.Set; * Describes a cell-broadcast service. This class should not be instantiated directly -- use * {@link StreamingServiceInfo} or FileServiceInfo TODO: add link once that's unhidden */ -public class ServiceInfo implements Parcelable { +public class ServiceInfo { // arbitrary limit on the number of locale -> name pairs we support final static int MAP_LIMIT = 1000; @@ -67,19 +67,6 @@ public class ServiceInfo implements Parcelable { sessionEndTime = (Date)end.clone(); } - public static final Parcelable.Creator<ServiceInfo> CREATOR = - new Parcelable.Creator<ServiceInfo>() { - @Override - public ServiceInfo createFromParcel(Parcel source) { - return new ServiceInfo(source); - } - - @Override - public ServiceInfo[] newArray(int size) { - return new ServiceInfo[size]; - } - }; - /** @hide */ protected ServiceInfo(Parcel in) { int mapCount = in.readInt(); @@ -107,7 +94,7 @@ public class ServiceInfo implements Parcelable { sessionEndTime = (java.util.Date) in.readSerializable(); } - @Override + /** @hide */ public void writeToParcel(Parcel dest, int flags) { Set<Locale> keySet = names.keySet(); dest.writeInt(keySet.size()); @@ -126,11 +113,6 @@ public class ServiceInfo implements Parcelable { dest.writeSerializable(sessionEndTime); } - @Override - public int describeContents() { - return 0; - } - /** * User displayable names listed by language. Do not modify the map returned from this method. */ diff --git a/telephony/java/android/telephony/mbms/StreamingService.java b/telephony/java/android/telephony/mbms/StreamingService.java index 42c78c31c2cb..1d66bac0d06c 100644 --- a/telephony/java/android/telephony/mbms/StreamingService.java +++ b/telephony/java/android/telephony/mbms/StreamingService.java @@ -28,14 +28,14 @@ import java.lang.annotation.RetentionPolicy; /** * Class used to represent a single MBMS stream. After a stream has been started with * {@link android.telephony.MbmsStreamingManager#startStreaming(StreamingServiceInfo, - * StreamingServiceCallback)}, + * StreamingServiceCallback, android.os.Handler)}, * this class is used to hold information about the stream and control it. */ public class StreamingService { private static final String LOG_TAG = "MbmsStreamingService"; /** - * The state of a stream, reported via {@link StreamingServiceCallback#streamStateUpdated} + * The state of a stream, reported via {@link StreamingServiceCallback#onStreamStateUpdated} * @hide */ @Retention(RetentionPolicy.SOURCE) @@ -47,7 +47,7 @@ public class StreamingService { /** * The reason for a stream state change, reported via - * {@link StreamingServiceCallback#streamStateUpdated} + * {@link StreamingServiceCallback#onStreamStateUpdated} * @hide */ @Retention(RetentionPolicy.SOURCE) @@ -64,7 +64,7 @@ public class StreamingService { /** * State changed due to a call to {@link #stopStreaming()} or * {@link android.telephony.MbmsStreamingManager#startStreaming(StreamingServiceInfo, - * StreamingServiceCallback)} + * StreamingServiceCallback, android.os.Handler)} */ public static final int REASON_BY_USER_REQUEST = 1; @@ -91,27 +91,28 @@ public class StreamingService { /** * State changed due to the device leaving the where this stream is being broadcast. */ - public static final int REASON_LEFT_MBMS_BROADCAST_AREA = 5; + public static final int REASON_LEFT_MBMS_BROADCAST_AREA = 6; /** * The method of transmission currently used for a stream, - * reported via {@link StreamingServiceCallback#streamMethodUpdated} + * reported via {@link StreamingServiceCallback#onStreamMethodUpdated} */ public final static int BROADCAST_METHOD = 1; public final static int UNICAST_METHOD = 2; private final int mSubscriptionId; private final StreamingServiceInfo mServiceInfo; - private final IStreamingServiceCallback mCallback; + private final InternalStreamingServiceCallback mCallback; private IMbmsStreamingService mService; + /** * @hide */ public StreamingService(int subscriptionId, IMbmsStreamingService service, StreamingServiceInfo streamingServiceInfo, - IStreamingServiceCallback callback) { + InternalStreamingServiceCallback callback) { mSubscriptionId = subscriptionId; mService = service; mServiceInfo = streamingServiceInfo; diff --git a/telephony/java/android/telephony/mbms/StreamingServiceCallback.java b/telephony/java/android/telephony/mbms/StreamingServiceCallback.java index 6a1ff9c2d1d7..b72c71572b60 100644 --- a/telephony/java/android/telephony/mbms/StreamingServiceCallback.java +++ b/telephony/java/android/telephony/mbms/StreamingServiceCallback.java @@ -16,13 +16,11 @@ package android.telephony.mbms; -import android.os.RemoteException; - /** * A callback class for use when the application is actively streaming content. The middleware * will provide updates on the status of the stream via this callback. */ -public class StreamingServiceCallback extends IStreamingServiceCallback.Stub { +public class StreamingServiceCallback { /** * Indicates broadcast signal strength is not available for this service. @@ -39,8 +37,7 @@ public class StreamingServiceCallback extends IStreamingServiceCallback.Stub { * @param errorCode The error code. * @param message A human-readable message generated by the middleware for debugging purposes. */ - @Override - public void error(int errorCode, String message) throws RemoteException { + public void onError(int errorCode, String message) { // default implementation empty } @@ -50,9 +47,8 @@ public class StreamingServiceCallback extends IStreamingServiceCallback.Stub { * See {@link StreamingService#STATE_STOPPED}, {@link StreamingService#STATE_STARTED} * and {@link StreamingService#STATE_STALLED}. */ - @Override - public void streamStateUpdated(@StreamingService.StreamingState int state, - @StreamingService.StreamingStateChangeReason int reason) throws RemoteException { + public void onStreamStateUpdated(@StreamingService.StreamingState int state, + @StreamingService.StreamingStateChangeReason int reason) { // default implementation empty } @@ -66,8 +62,7 @@ public class StreamingServiceCallback extends IStreamingServiceCallback.Stub { * This may be called when a looping stream hits the end or * when parameters have changed to account for time drift. */ - @Override - public void mediaDescriptionUpdated() throws RemoteException { + public void onMediaDescriptionUpdated() { // default implementation empty } @@ -81,8 +76,7 @@ public class StreamingServiceCallback extends IStreamingServiceCallback.Stub { * {@link #SIGNAL_STRENGTH_UNAVAILABLE} if broadcast is not available * for this service due to timing, geography or popularity. */ - @Override - public void broadcastSignalStrengthUpdated(int signalStrength) throws RemoteException { + public void onBroadcastSignalStrengthUpdated(int signalStrength) { // default implementation empty } @@ -102,8 +96,7 @@ public class StreamingServiceCallback extends IStreamingServiceCallback.Stub { * See {@link StreamingService#BROADCAST_METHOD} and * {@link StreamingService#UNICAST_METHOD} */ - @Override - public void streamMethodUpdated(int methodType) throws RemoteException { + public void onStreamMethodUpdated(int methodType) { // default implementation empty } } diff --git a/telephony/java/android/telephony/mbms/StreamingServiceInfo.java b/telephony/java/android/telephony/mbms/StreamingServiceInfo.java index 58df24d882de..c704f346e311 100644 --- a/telephony/java/android/telephony/mbms/StreamingServiceInfo.java +++ b/telephony/java/android/telephony/mbms/StreamingServiceInfo.java @@ -28,7 +28,7 @@ import java.util.Map; /** * Describes a single MBMS streaming service. */ -public class StreamingServiceInfo extends ServiceInfo implements Parcelable { +public final class StreamingServiceInfo extends ServiceInfo implements Parcelable { /** * @param names User displayable names listed by language. diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java index edd585808580..71713d013f97 100644 --- a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java +++ b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java @@ -18,10 +18,13 @@ package android.telephony.mbms.vendor; import android.annotation.NonNull; import android.os.RemoteException; +import android.telephony.mbms.DownloadProgressListener; import android.telephony.mbms.DownloadRequest; import android.telephony.mbms.FileInfo; +import android.telephony.mbms.FileServiceInfo; import android.telephony.mbms.IDownloadProgressListener; import android.telephony.mbms.IMbmsDownloadManagerCallback; +import android.telephony.mbms.MbmsDownloadManagerCallback; import android.telephony.mbms.MbmsException; import java.util.List; @@ -44,16 +47,40 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub { * or {@link MbmsException#SUCCESS}. Non-successful error codes will be passed to the app via * {@link IMbmsDownloadManagerCallback#error(int, String)}. * - * @param listener The callback to use to communicate with the app. + * @param callback The callback to use to communicate with the app. * @param subscriptionId The subscription ID to use. */ - @Override - public int initialize(int subscriptionId, - IMbmsDownloadManagerCallback listener) throws RemoteException { + public int initialize(int subscriptionId, MbmsDownloadManagerCallback callback) + throws RemoteException { return 0; } /** + * Actual AIDL implementation -- hides the callback AIDL from the API. + * @hide + */ + @Override + public final int initialize(int subscriptionId, + final IMbmsDownloadManagerCallback callback) throws RemoteException { + return initialize(subscriptionId, new MbmsDownloadManagerCallback() { + @Override + public void error(int errorCode, String message) throws RemoteException { + callback.error(errorCode, message); + } + + @Override + public void fileServicesUpdated(List<FileServiceInfo> services) throws RemoteException { + callback.fileServicesUpdated(services); + } + + @Override + public void middlewareReady() throws RemoteException { + callback.middlewareReady(); + } + }); + } + + /** * Registers serviceClasses of interest with the appName/subId key. * Starts async fetching data on streaming services of matching classes to be reported * later via {@link IMbmsDownloadManagerCallback#fileServicesUpdated(List)} @@ -107,19 +134,36 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub { * @param downloadRequest An object describing the set of files to be downloaded. * @param listener A listener through which the middleware can provide progress updates to * the app while both are still running. - * @return TODO: enumerate possible return values + * @return Any error from {@link android.telephony.mbms.MbmsException.GeneralErrors} + * or {@link MbmsException#SUCCESS} + */ + public int download(DownloadRequest downloadRequest, DownloadProgressListener listener) { + return 0; + } + + /** + * Actual AIDL implementation -- hides the callback AIDL from the API. + * @hide */ @Override - public int download(DownloadRequest downloadRequest, IDownloadProgressListener listener) + public final int download(DownloadRequest downloadRequest, IDownloadProgressListener listener) throws RemoteException { - return 0; + return download(downloadRequest, new DownloadProgressListener() { + @Override + public void progress(DownloadRequest request, FileInfo fileInfo, int + currentDownloadSize, int fullDownloadSize, int currentDecodedSize, int + fullDecodedSize) throws RemoteException { + listener.progress(request, fileInfo, currentDownloadSize, fullDownloadSize, + currentDecodedSize, fullDecodedSize); + } + }); } /** * Returns a list of pending {@link DownloadRequest}s that originated from the calling * application, identified by its uid. A pending request is one that was issued via - * {@link #download(DownloadRequest, IDownloadCallback)} but not cancelled through + * {@link #download(DownloadRequest, IDownloadProgressListener)} but not cancelled through * {@link #cancelDownload(DownloadRequest)}. * The middleware must return a non-null result synchronously or throw an exception * inheriting from {@link RuntimeException}. diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java index b2200c300262..843e0482ee1b 100644 --- a/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java +++ b/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java @@ -19,6 +19,7 @@ package android.telephony.mbms.vendor; import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.Uri; +import android.os.Binder; import android.os.RemoteException; import android.telephony.mbms.IMbmsStreamingManagerCallback; import android.telephony.mbms.IStreamingServiceCallback; @@ -38,7 +39,7 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub { /** * Initialize streaming service for this app and subId, registering the listener. * - * May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}, which + * May throw an {@link IllegalArgumentException} or a {@link SecurityException}, which * will be intercepted and passed to the app as * {@link android.telephony.mbms.MbmsException.InitializationErrors#ERROR_UNABLE_TO_INITIALIZE} * @@ -46,10 +47,10 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub { * or {@link MbmsException#SUCCESS}. Non-successful error codes will be passed to the app via * {@link IMbmsStreamingManagerCallback#error(int, String)}. * - * @param listener The callback to use to communicate with the app. + * @param callback The callback to use to communicate with the app. * @param subscriptionId The subscription ID to use. */ - public int initialize(MbmsStreamingManagerCallback listener, int subscriptionId) + public int initialize(MbmsStreamingManagerCallback callback, int subscriptionId) throws RemoteException { return 0; } @@ -59,23 +60,42 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub { * @hide */ @Override - public final int initialize(IMbmsStreamingManagerCallback listener, int subscriptionId) - throws RemoteException { + public final int initialize(final IMbmsStreamingManagerCallback callback, + final int subscriptionId) throws RemoteException { + final int uid = Binder.getCallingUid(); + callback.asBinder().linkToDeath(new DeathRecipient() { + @Override + public void binderDied() { + onAppCallbackDied(uid, subscriptionId); + } + }, 0); + return initialize(new MbmsStreamingManagerCallback() { @Override - public void error(int errorCode, String message) throws RemoteException { - listener.error(errorCode, message); + public void onError(int errorCode, String message) { + try { + callback.error(errorCode, message); + } catch (RemoteException e) { + onAppCallbackDied(uid, subscriptionId); + } } @Override - public void streamingServicesUpdated(List<StreamingServiceInfo> services) throws - RemoteException { - listener.streamingServicesUpdated(services); + public void onStreamingServicesUpdated(List<StreamingServiceInfo> services) { + try { + callback.streamingServicesUpdated(services); + } catch (RemoteException e) { + onAppCallbackDied(uid, subscriptionId); + } } @Override - public void middlewareReady() throws RemoteException { - listener.middlewareReady(); + public void onMiddlewareReady() { + try { + callback.middlewareReady(); + } catch (RemoteException e) { + onAppCallbackDied(uid, subscriptionId); + } } }, subscriptionId); } @@ -113,11 +133,11 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub { * * @param subscriptionId The subscription id to use. * @param serviceId The ID of the streaming service that the app has requested. - * @param listener The listener object on which the app wishes to receive updates. + * @param callback The callback object on which the app wishes to receive updates. * @return Any error in {@link android.telephony.mbms.MbmsException.GeneralErrors} */ public int startStreaming(int subscriptionId, String serviceId, - StreamingServiceCallback listener) throws RemoteException { + StreamingServiceCallback callback) throws RemoteException { return 0; } @@ -128,33 +148,60 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub { */ @Override public int startStreaming(int subscriptionId, String serviceId, - IStreamingServiceCallback listener) throws RemoteException { + IStreamingServiceCallback callback) throws RemoteException { + final int uid = Binder.getCallingUid(); + callback.asBinder().linkToDeath(new DeathRecipient() { + @Override + public void binderDied() { + onAppCallbackDied(uid, subscriptionId); + } + }, 0); + return startStreaming(subscriptionId, serviceId, new StreamingServiceCallback() { @Override - public void error(int errorCode, String message) throws RemoteException { - listener.error(errorCode, message); + public void onError(int errorCode, String message) { + try { + callback.error(errorCode, message); + } catch (RemoteException e) { + onAppCallbackDied(uid, subscriptionId); + } } @Override - public void streamStateUpdated(@StreamingService.StreamingState int state, - @StreamingService.StreamingStateChangeReason int reason) - throws RemoteException { - listener.streamStateUpdated(state, reason); + public void onStreamStateUpdated(@StreamingService.StreamingState int state, + @StreamingService.StreamingStateChangeReason int reason) { + try { + callback.streamStateUpdated(state, reason); + } catch (RemoteException e) { + onAppCallbackDied(uid, subscriptionId); + } } @Override - public void mediaDescriptionUpdated() throws RemoteException { - listener.mediaDescriptionUpdated(); + public void onMediaDescriptionUpdated() { + try { + callback.mediaDescriptionUpdated(); + } catch (RemoteException e) { + onAppCallbackDied(uid, subscriptionId); + } } @Override - public void broadcastSignalStrengthUpdated(int signalStrength) throws RemoteException { - listener.broadcastSignalStrengthUpdated(signalStrength); + public void onBroadcastSignalStrengthUpdated(int signalStrength) { + try { + callback.broadcastSignalStrengthUpdated(signalStrength); + } catch (RemoteException e) { + onAppCallbackDied(uid, subscriptionId); + } } @Override - public void streamMethodUpdated(int methodType) throws RemoteException { - listener.streamMethodUpdated(methodType); + public void onStreamMethodUpdated(int methodType) { + try { + callback.streamMethodUpdated(methodType); + } catch (RemoteException e) { + onAppCallbackDied(uid, subscriptionId); + } } }); } @@ -221,4 +268,12 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub { @Override public void dispose(int subscriptionId) throws RemoteException { } + + /** + * Indicates that the app identified by the given UID and subscription ID has died. + * @param uid the UID of the app, as returned by {@link Binder#getCallingUid()}. + * @param subscriptionId The subscription ID the app is using. + */ + public void onAppCallbackDied(int uid, int subscriptionId) { + } } diff --git a/telephony/java/android/telephony/mbms/vendor/VendorIntents.java b/telephony/java/android/telephony/mbms/vendor/VendorIntents.java new file mode 100644 index 000000000000..367c995c6f7d --- /dev/null +++ b/telephony/java/android/telephony/mbms/vendor/VendorIntents.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.telephony.mbms.vendor; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ResolveInfo; +import android.net.Uri; +import android.telephony.mbms.DownloadRequest; +import android.telephony.mbms.MbmsDownloadReceiver; + +import java.io.File; +import java.util.List; + +/** + * @hide + * TODO: future systemapi + */ +public class VendorIntents { + + /** + * The MBMS middleware should send this when a download of single file has completed or + * failed. Mandatory extras are + * {@link android.telephony.MbmsDownloadManager#EXTRA_RESULT} + * {@link android.telephony.MbmsDownloadManager#EXTRA_FILE_INFO} + * {@link #EXTRA_REQUEST} + * {@link #EXTRA_TEMP_LIST} + * {@link #EXTRA_FINAL_URI} + */ + public static final String ACTION_DOWNLOAD_RESULT_INTERNAL = + "android.telephony.mbms.action.DOWNLOAD_RESULT_INTERNAL"; + + /** + * The MBMS middleware should send this when it wishes to request {@code content://} URIs to + * serve as temp files for downloads or when it wishes to resume paused downloads. Mandatory + * extras are + * {@link #EXTRA_REQUEST} + * + * Optional extras are + * {@link #EXTRA_FD_COUNT} (0 if not present) + * {@link #EXTRA_PAUSED_LIST} (empty if not present) + */ + public static final String ACTION_FILE_DESCRIPTOR_REQUEST = + "android.telephony.mbms.action.FILE_DESCRIPTOR_REQUEST"; + + /** + * The MBMS middleware should send this when it wishes to clean up temp files in the app's + * filesystem. Mandatory extras are: + * {@link #EXTRA_TEMP_FILES_IN_USE} + */ + public static final String ACTION_CLEANUP = + "android.telephony.mbms.action.CLEANUP"; + + /** + * Extra containing a {@link List} of {@link Uri}s that were used as temp files for this + * completed file. These {@link Uri}s should have scheme {@code file://}, and the temp + * files will be deleted upon receipt of the intent. + * May be null. + */ + public static final String EXTRA_TEMP_LIST = "android.telephony.mbms.extra.TEMP_LIST"; + + /** + * Extra containing an integer indicating the number of temp files requested. + */ + public static final String EXTRA_FD_COUNT = "android.telephony.mbms.extra.FD_COUNT"; + + /** + * Extra containing a list of {@link Uri}s that the middleware is requesting access to via + * {@link #ACTION_FILE_DESCRIPTOR_REQUEST} in order to resume downloading. These {@link Uri}s + * should have scheme {@code file://}. + */ + public static final String EXTRA_PAUSED_LIST = "android.telephony.mbms.extra.PAUSED_LIST"; + + /** + * Extra containing a list of {@link android.telephony.mbms.UriPathPair}s, used in the + * response to {@link #ACTION_FILE_DESCRIPTOR_REQUEST}. These are temp files that are meant + * to be used for new file downloads. + */ + public static final String EXTRA_FREE_URI_LIST = "android.telephony.mbms.extra.FREE_URI_LIST"; + + /** + * Extra containing a list of {@link android.telephony.mbms.UriPathPair}s, used in the + * response to {@link #ACTION_FILE_DESCRIPTOR_REQUEST}. These + * {@link android.telephony.mbms.UriPathPair}s contain {@code content://} URIs that provide + * access to previously paused downloads. + */ + public static final String EXTRA_PAUSED_URI_LIST = + "android.telephony.mbms.extra.PAUSED_URI_LIST"; + + /** + * Extra containing a string that points to the middleware's knowledge of where the temp file + * root for the app is. The path should be a canonical path as returned by + * {@link File#getCanonicalPath()} + */ + public static final String EXTRA_TEMP_FILE_ROOT = + "android.telephony.mbms.extra.TEMP_FILE_ROOT"; + + /** + * Extra containing a list of {@link Uri}s indicating temp files which the middleware is + * still using. + */ + public static final String EXTRA_TEMP_FILES_IN_USE = + "android.telephony.mbms.extra.TEMP_FILES_IN_USE"; + + /** + * Extra containing the {@link DownloadRequest} for which the download result or file + * descriptor request is for. Must not be null. + */ + public static final String EXTRA_REQUEST = "android.telephony.mbms.extra.REQUEST"; + + /** + * Extra containing a single {@link Uri} indicating the path to the temp file in which the + * decoded downloaded file resides. Must not be null. + */ + public static final String EXTRA_FINAL_URI = "android.telephony.mbms.extra.FINAL_URI"; + + /** + * Extra containing an instance of {@link android.telephony.mbms.ServiceInfo}, used by + * file-descriptor requests and cleanup requests to specify which service they want to + * request temp files or clean up temp files for, respectively. + */ + public static final String EXTRA_SERVICE_INFO = + "android.telephony.mbms.extra.SERVICE_INFO"; + + /** + * Retrieves the {@link ComponentName} for the {@link android.content.BroadcastReceiver} that + * the various intents from the middleware should be targeted towards. + * @param uid The uid of the frontend app. + * @return The component name of the receiver that the middleware should send its intents to, + * or null if the app didn't declare it in the manifest. + */ + public static ComponentName getAppReceiverFromUid(Context context, int uid) { + String[] packageNames = context.getPackageManager().getPackagesForUid(uid); + if (packageNames == null) { + return null; + } + + for (String packageName : packageNames) { + ComponentName candidate = new ComponentName(packageName, + MbmsDownloadReceiver.class.getCanonicalName()); + Intent queryIntent = new Intent(); + queryIntent.setComponent(candidate); + List<ResolveInfo> receivers = + context.getPackageManager().queryBroadcastReceivers(queryIntent, 0); + if (receivers != null && receivers.size() > 0) { + return candidate; + } + } + return null; + } +} diff --git a/telephony/java/com/android/ims/ImsConferenceState.java b/telephony/java/com/android/ims/ImsConferenceState.java index c57ef98abb4d..0afde88b8918 100644 --- a/telephony/java/com/android/ims/ImsConferenceState.java +++ b/telephony/java/com/android/ims/ImsConferenceState.java @@ -79,6 +79,8 @@ public class ImsConferenceState implements Parcelable { public static final String STATUS_DISCONNECTED = "disconnected"; public static final String STATUS_MUTED_VIA_FOCUS = "muted-via-focus"; public static final String STATUS_CONNECT_FAIL = "connect-fail"; + public static final String STATUS_SEND_ONLY = "sendonly"; + public static final String STATUS_SEND_RECV = "sendrecv"; /** * conference-info : SIP status code (integer) @@ -156,15 +158,53 @@ public class ImsConferenceState implements Parcelable { } else if (status.equals(STATUS_ALERTING) || status.equals(STATUS_DIALING_OUT)) { return Connection.STATE_DIALING; - } else if (status.equals(STATUS_ON_HOLD)) { + } else if (status.equals(STATUS_ON_HOLD) || + status.equals(STATUS_SEND_ONLY)) { return Connection.STATE_HOLDING; } else if (status.equals(STATUS_CONNECTED) || status.equals(STATUS_MUTED_VIA_FOCUS) || - status.equals(STATUS_DISCONNECTING)) { + status.equals(STATUS_DISCONNECTING) || + status.equals(STATUS_SEND_RECV)) { return Connection.STATE_ACTIVE; } else if (status.equals(STATUS_DISCONNECTED)) { return Connection.STATE_DISCONNECTED; } return Call.STATE_ACTIVE; } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("["); + sb.append(ImsConferenceState.class.getSimpleName()); + sb.append(" "); + if (mParticipants.size() > 0) { + Set<Entry<String, Bundle>> entries = mParticipants.entrySet(); + + if (entries != null) { + Iterator<Entry<String, Bundle>> iterator = entries.iterator(); + sb.append("<"); + while (iterator.hasNext()) { + Entry<String, Bundle> entry = iterator.next(); + sb.append(entry.getKey()); + sb.append(": "); + Bundle participantData = entry.getValue(); + + for (String key : participantData.keySet()) { + sb.append(key); + sb.append("="); + if (ENDPOINT.equals(key) || USER.equals(key)) { + sb.append(android.telecom.Log.pii(participantData.get(key))); + } else { + sb.append(participantData.get(key)); + } + sb.append(", "); + } + } + sb.append(">"); + } + } + sb.append("]"); + return sb.toString(); + } } diff --git a/telephony/java/com/android/ims/ImsConfig.java b/telephony/java/com/android/ims/ImsConfig.java index e7b22bdfadcc..cf4c47bf541f 100644 --- a/telephony/java/com/android/ims/ImsConfig.java +++ b/telephony/java/com/android/ims/ImsConfig.java @@ -524,6 +524,7 @@ public class ImsConfig { * Defines IMS feature value. */ public static class FeatureValueConstants { + public static final int ERROR = -1; public static final int OFF = 0; public static final int ON = 1; } diff --git a/telephony/java/com/android/internal/telephony/ExponentialBackoff.java b/telephony/java/com/android/internal/telephony/ExponentialBackoff.java new file mode 100644 index 000000000000..80958c077d6a --- /dev/null +++ b/telephony/java/com/android/internal/telephony/ExponentialBackoff.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.telephony; + +import android.annotation.NonNull; +import android.os.Handler; +import android.os.Looper; + +/** The implementation of exponential backoff with jitter applied. */ +public class ExponentialBackoff { + private int mRetryCounter; + private long mStartDelayMs; + private long mMaximumDelayMs; + private long mCurrentDelayMs; + private int mMultiplier; + private Runnable mRunnable; + private Handler mHandler; + + public ExponentialBackoff( + long initialDelayMs, + long maximumDelayMs, + int multiplier, + @NonNull Looper looper, + @NonNull Runnable runnable) { + this(initialDelayMs, maximumDelayMs, multiplier, new Handler(looper), runnable); + } + + public ExponentialBackoff( + long initialDelayMs, + long maximumDelayMs, + int multiplier, + @NonNull Handler handler, + @NonNull Runnable runnable) { + mRetryCounter = 0; + mStartDelayMs = initialDelayMs; + mMaximumDelayMs = maximumDelayMs; + mMultiplier = multiplier; + mHandler = handler; + mRunnable = runnable; + } + + /** Starts the backoff, the runnable will be executed after {@link #mStartDelayMs}. */ + public void start() { + mRetryCounter = 0; + mCurrentDelayMs = mStartDelayMs; + mHandler.removeCallbacks(mRunnable); + mHandler.postDelayed(mRunnable, mCurrentDelayMs); + } + + /** Stops the backoff, all pending messages will be removed from the message queue. */ + public void stop() { + mRetryCounter = 0; + mHandler.removeCallbacks(mRunnable); + } + + /** Should call when the retry action has failed and we want to retry after a longer delay. */ + public void notifyFailed() { + mRetryCounter++; + long temp = Math.min( + mMaximumDelayMs, (long) (mStartDelayMs * Math.pow(mMultiplier, mRetryCounter))); + mCurrentDelayMs = (long) (((1 + Math.random()) / 2) * temp); + mHandler.removeCallbacks(mRunnable); + mHandler.postDelayed(mRunnable, mCurrentDelayMs); + } + + /** Returns the delay for the most recently posted message. */ + public long getCurrentDelay() { + return mCurrentDelayMs; + } +} diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java index ceb3993e1705..0f4960887a33 100644 --- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java +++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java @@ -117,46 +117,6 @@ public class ActivityTestMain extends Activity { } } - private void addThumbnail(LinearLayout container, Bitmap bm, - final ActivityManager.RecentTaskInfo task, - final ActivityManager.TaskThumbnail thumbs) { - ImageView iv = new ImageView(this); - if (bm != null) { - iv.setImageBitmap(bm); - } - iv.setBackgroundResource(android.R.drawable.gallery_thumb); - int w = getResources().getDimensionPixelSize(android.R.dimen.thumbnail_width); - int h = getResources().getDimensionPixelSize(android.R.dimen.thumbnail_height); - container.addView(iv, new LinearLayout.LayoutParams(w, h)); - - iv.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (task.id >= 0 && thumbs != null) { - mAm.moveTaskToFront(task.id, ActivityManager.MOVE_TASK_WITH_HOME); - } else { - try { - startActivity(task.baseIntent); - } catch (ActivityNotFoundException e) { - Log.w("foo", "Unable to start task: " + e); - } - } - buildUi(); - } - }); - iv.setOnLongClickListener(new View.OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - if (task.id >= 0 && thumbs != null) { - mAm.removeTask(task.id); - buildUi(); - return true; - } - return false; - } - }); - } - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -600,7 +560,6 @@ public class ActivityTestMain extends Activity { if (recents != null) { for (int i=0; i<recents.size(); i++) { ActivityManager.RecentTaskInfo r = recents.get(i); - ActivityManager.TaskThumbnail tt = mAm.getTaskThumbnail(r.persistentId); TextView tv = new TextView(this); tv.setText(r.baseIntent.getComponent().flattenToShortString()); top.addView(tv, new LinearLayout.LayoutParams( @@ -608,7 +567,6 @@ public class ActivityTestMain extends Activity { LinearLayout.LayoutParams.WRAP_CONTENT)); LinearLayout item = new LinearLayout(this); item.setOrientation(LinearLayout.HORIZONTAL); - addThumbnail(item, tt != null ? tt.mainThumbnail : null, r, tt); top.addView(item, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)); diff --git a/tests/Internal/src/android/app/WallpaperColorsTest.java b/tests/Internal/src/android/app/WallpaperColorsTest.java index fb529b936e5c..881f6284413f 100644 --- a/tests/Internal/src/android/app/WallpaperColorsTest.java +++ b/tests/Internal/src/android/app/WallpaperColorsTest.java @@ -36,12 +36,12 @@ public class WallpaperColorsTest { final Color color = Color.valueOf(Color.WHITE); // Default should not support dark text! WallpaperColors colors = new WallpaperColors(color, null, null, 0); - Assert.assertTrue("Default behavior is not to support dark text", + Assert.assertTrue("Default behavior is not to support dark text.", (colors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) == 0); // Override it colors = new WallpaperColors(color, null, null, WallpaperColors.HINT_SUPPORTS_DARK_TEXT); - Assert.assertFalse("Forcing dark text support doesn't work", + Assert.assertFalse("Forcing dark text support doesn't work.", (colors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) == 0); } @@ -57,15 +57,18 @@ public class WallpaperColorsTest { int hints = WallpaperColors.fromBitmap(image).getColorHints(); boolean supportsDarkText = (hints & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0; boolean supportsDarkTheme = (hints & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0; - Assert.assertTrue("White surface should support dark text", supportsDarkText); - Assert.assertFalse("White surface shouldn't support dark theme", supportsDarkTheme); + boolean fromBitmap = (hints & WallpaperColors.HINT_FROM_BITMAP) != 0; + Assert.assertTrue("White surface should support dark text.", supportsDarkText); + Assert.assertFalse("White surface shouldn't support dark theme.", supportsDarkTheme); + Assert.assertTrue("From bitmap should be true if object was created " + + "using WallpaperColors#fromBitmap.", fromBitmap); canvas.drawColor(Color.BLACK); hints = WallpaperColors.fromBitmap(image).getColorHints(); supportsDarkText = (hints & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0; supportsDarkTheme = (hints & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0; - Assert.assertFalse("Black surface shouldn't support dark text", supportsDarkText); - Assert.assertTrue("Black surface should support dark theme", supportsDarkTheme); + Assert.assertFalse("Black surface shouldn't support dark text.", supportsDarkText); + Assert.assertTrue("Black surface should support dark theme.", supportsDarkTheme); Paint paint = new Paint(); paint.setStyle(Paint.Style.FILL); @@ -75,7 +78,12 @@ public class WallpaperColorsTest { supportsDarkText = (WallpaperColors.fromBitmap(image) .getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0; Assert.assertFalse("Light surface shouldn't support dark text " - + "when it contains dark pixels", supportsDarkText); + + "when it contains dark pixels.", supportsDarkText); + + WallpaperColors colors = new WallpaperColors(Color.valueOf(Color.GREEN), null, null); + fromBitmap = (colors.getColorHints() & WallpaperColors.HINT_FROM_BITMAP) != 0; + Assert.assertFalse("Object created from public constructor should not contain " + + "HINT_FROM_BITMAP.", fromBitmap); } /** diff --git a/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java b/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java index 6dc9ba7b621f..d46fff4db65a 100644 --- a/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java +++ b/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java @@ -99,20 +99,39 @@ public class TonalTest { } @Test - public void tonal_excludeBlacklistedColor() { + public void tonal_blacklistTest() { // Make sure that palette generation will fail. - Tonal tonal = new Tonal(InstrumentationRegistry.getContext()); + final Tonal tonal = new Tonal(InstrumentationRegistry.getContext()); // Creating a WallpaperColors object that contains *only* blacklisted colors. - float[] hsl = tonal.getBlacklistedColors().get(0).getCenter(); - WallpaperColors colors = new WallpaperColors(Color.valueOf(ColorUtils.HSLToColor(hsl)), - null, null, 0); + final float[] hsl = tonal.getBlacklistedColors().get(0).getCenter(); + final int blacklistedColor = ColorUtils.HSLToColor(hsl); + WallpaperColors colorsFromBitmap = new WallpaperColors(Color.valueOf(blacklistedColor), + null, null, WallpaperColors.HINT_FROM_BITMAP); // Make sure that palette generation will fail - GradientColors normal = new GradientColors(); - tonal.extractInto(colors, normal, new GradientColors(), + final GradientColors normal = new GradientColors(); + tonal.extractInto(colorsFromBitmap, normal, new GradientColors(), new GradientColors()); assertTrue("Cannot generate a tonal palette from blacklisted colors.", normal.getMainColor() == Tonal.MAIN_COLOR_DARK); } + + @Test + public void tonal_ignoreBlacklistTest() { + final Tonal tonal = new Tonal(InstrumentationRegistry.getContext()); + + // Creating a WallpaperColors object that contains *only* blacklisted colors. + final float[] hsl = tonal.getBlacklistedColors().get(0).getCenter(); + final int blacklistedColor = ColorUtils.HSLToColor(hsl); + WallpaperColors colors = new WallpaperColors(Color.valueOf(blacklistedColor), + null, null); + + // Blacklist should be ignored when HINT_FROM_BITMAP isn't present. + final GradientColors normal = new GradientColors(); + tonal.extractInto(colors, normal, new GradientColors(), + new GradientColors()); + assertTrue("Blacklist should never be used on WallpaperColors generated using " + + "default constructor.", normal.getMainColor() == blacklistedColor); + } } diff --git a/core/tests/coretests/src/android/net/IpPrefixTest.java b/tests/net/java/android/net/IpPrefixTest.java index 4f2387dcf5c1..b5b2c07cbc4e 100644 --- a/core/tests/coretests/src/android/net/IpPrefixTest.java +++ b/tests/net/java/android/net/IpPrefixTest.java @@ -16,18 +16,27 @@ package android.net; -import android.net.IpPrefix; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import android.os.Parcel; -import android.test.suitebuilder.annotation.SmallTest; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + import java.net.InetAddress; import java.util.Random; -import junit.framework.TestCase; -import static android.test.MoreAsserts.assertNotEqual; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; +import org.junit.runner.RunWith; +import org.junit.Test; -public class IpPrefixTest extends TestCase { +@RunWith(AndroidJUnit4.class) +@SmallTest +public class IpPrefixTest { private static InetAddress Address(String addr) { return InetAddress.parseNumericAddress(addr); @@ -42,7 +51,7 @@ public class IpPrefixTest extends TestCase { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xa0 }; - @SmallTest + @Test public void testConstructor() { IpPrefix p; try { @@ -103,6 +112,7 @@ public class IpPrefixTest extends TestCase { } catch(IllegalArgumentException expected) {} } + @Test public void testTruncation() { IpPrefix p; @@ -170,7 +180,7 @@ public class IpPrefixTest extends TestCase { assertFalse(o2.equals(o1)); } - @SmallTest + @Test public void testEquals() { IpPrefix p1, p2; @@ -212,7 +222,7 @@ public class IpPrefixTest extends TestCase { assertAreNotEqual(p1, p2); } - @SmallTest + @Test public void testContains() { IpPrefix p = new IpPrefix("2001:db8:f00::ace:d00d/127"); assertTrue(p.contains(Address("2001:db8:f00::ace:d00c"))); @@ -240,7 +250,7 @@ public class IpPrefixTest extends TestCase { assertFalse(ipv4Default.contains(Address("2001:db8::f00"))); } - @SmallTest + @Test public void testHashCode() { IpPrefix p = new IpPrefix(new byte[4], 0); Random random = new Random(); @@ -261,12 +271,12 @@ public class IpPrefixTest extends TestCase { assertEquals(p.hashCode(), oldP.hashCode()); } if (p.hashCode() != oldP.hashCode()) { - assertNotEqual(p, oldP); + assertNotEquals(p, oldP); } } } - @SmallTest + @Test public void testHashCodeIsNotConstant() { IpPrefix[] prefixes = { new IpPrefix("2001:db8:f00::ace:d00d/127"), @@ -276,12 +286,12 @@ public class IpPrefixTest extends TestCase { }; for (int i = 0; i < prefixes.length; i++) { for (int j = i + 1; j < prefixes.length; j++) { - assertNotEqual(prefixes[i].hashCode(), prefixes[j].hashCode()); + assertNotEquals(prefixes[i].hashCode(), prefixes[j].hashCode()); } } } - @SmallTest + @Test public void testMappedAddressesAreBroken() { // 192.0.2.0/24 != ::ffff:c000:0204/120, but because we use InetAddress, // we are unable to comprehend that. @@ -318,13 +328,16 @@ public class IpPrefixTest extends TestCase { assertEquals(p, p2); } + @Test public void testParceling() { IpPrefix p; p = new IpPrefix("2001:4860:db8::/64"); assertParcelingIsLossless(p); + assertTrue(p.isIPv6()); p = new IpPrefix("192.0.2.0/25"); assertParcelingIsLossless(p); + assertTrue(p.isIPv4()); } } diff --git a/core/tests/coretests/src/android/net/LinkAddressTest.java b/tests/net/java/android/net/LinkAddressTest.java index adf8d95c0b66..c1ad94669508 100644 --- a/core/tests/coretests/src/android/net/LinkAddressTest.java +++ b/tests/net/java/android/net/LinkAddressTest.java @@ -16,6 +16,23 @@ package android.net; +import static android.system.OsConstants.IFA_F_DADFAILED; +import static android.system.OsConstants.IFA_F_DEPRECATED; +import static android.system.OsConstants.IFA_F_OPTIMISTIC; +import static android.system.OsConstants.IFA_F_PERMANENT; +import static android.system.OsConstants.IFA_F_TEMPORARY; +import static android.system.OsConstants.IFA_F_TENTATIVE; +import static android.system.OsConstants.RT_SCOPE_HOST; +import static android.system.OsConstants.RT_SCOPE_LINK; +import static android.system.OsConstants.RT_SCOPE_SITE; +import static android.system.OsConstants.RT_SCOPE_UNIVERSE; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; @@ -27,44 +44,35 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; -import android.net.LinkAddress; import android.os.Parcel; -import android.test.AndroidTestCase; -import static android.test.MoreAsserts.assertNotEqual; -import android.test.suitebuilder.annotation.SmallTest; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; -import static android.system.OsConstants.IFA_F_DADFAILED; -import static android.system.OsConstants.IFA_F_DEPRECATED; -import static android.system.OsConstants.IFA_F_OPTIMISTIC; -import static android.system.OsConstants.IFA_F_PERMANENT; -import static android.system.OsConstants.IFA_F_TEMPORARY; -import static android.system.OsConstants.IFA_F_TENTATIVE; -import static android.system.OsConstants.RT_SCOPE_HOST; -import static android.system.OsConstants.RT_SCOPE_LINK; -import static android.system.OsConstants.RT_SCOPE_SITE; -import static android.system.OsConstants.RT_SCOPE_UNIVERSE; +import org.junit.runner.RunWith; +import org.junit.Test; -/** - * Tests for {@link LinkAddress}. - */ -public class LinkAddressTest extends AndroidTestCase { +@RunWith(AndroidJUnit4.class) +@SmallTest +public class LinkAddressTest { private static final String V4 = "192.0.2.1"; private static final String V6 = "2001:db8::1"; private static final InetAddress V4_ADDRESS = NetworkUtils.numericToInetAddress(V4); private static final InetAddress V6_ADDRESS = NetworkUtils.numericToInetAddress(V6); + @Test public void testConstants() { // RT_SCOPE_UNIVERSE = 0, but all the other constants should be nonzero. - assertNotEqual(0, RT_SCOPE_HOST); - assertNotEqual(0, RT_SCOPE_LINK); - assertNotEqual(0, RT_SCOPE_SITE); + assertNotEquals(0, RT_SCOPE_HOST); + assertNotEquals(0, RT_SCOPE_LINK); + assertNotEquals(0, RT_SCOPE_SITE); - assertNotEqual(0, IFA_F_DEPRECATED); - assertNotEqual(0, IFA_F_PERMANENT); - assertNotEqual(0, IFA_F_TENTATIVE); + assertNotEquals(0, IFA_F_DEPRECATED); + assertNotEquals(0, IFA_F_PERMANENT); + assertNotEquals(0, IFA_F_TENTATIVE); } + @Test public void testConstructors() throws SocketException { LinkAddress address; @@ -74,12 +82,14 @@ public class LinkAddressTest extends AndroidTestCase { assertEquals(25, address.getPrefixLength()); assertEquals(0, address.getFlags()); assertEquals(RT_SCOPE_UNIVERSE, address.getScope()); + assertTrue(address.isIPv4()); address = new LinkAddress(V6_ADDRESS, 127); assertEquals(V6_ADDRESS, address.getAddress()); assertEquals(127, address.getPrefixLength()); assertEquals(0, address.getFlags()); assertEquals(RT_SCOPE_UNIVERSE, address.getScope()); + assertTrue(address.isIPv6()); // Nonsensical flags/scopes or combinations thereof are acceptable. address = new LinkAddress(V6 + "/64", IFA_F_DEPRECATED | IFA_F_PERMANENT, RT_SCOPE_LINK); @@ -87,12 +97,14 @@ public class LinkAddressTest extends AndroidTestCase { assertEquals(64, address.getPrefixLength()); assertEquals(IFA_F_DEPRECATED | IFA_F_PERMANENT, address.getFlags()); assertEquals(RT_SCOPE_LINK, address.getScope()); + assertTrue(address.isIPv6()); address = new LinkAddress(V4 + "/23", 123, 456); assertEquals(V4_ADDRESS, address.getAddress()); assertEquals(23, address.getPrefixLength()); assertEquals(123, address.getFlags()); assertEquals(456, address.getScope()); + assertTrue(address.isIPv4()); // InterfaceAddress doesn't have a constructor. Fetch some from an interface. List<InterfaceAddress> addrs = NetworkInterface.getByName("lo").getInterfaceAddresses(); @@ -174,6 +186,7 @@ public class LinkAddressTest extends AndroidTestCase { } catch(IllegalArgumentException expected) {} } + @Test public void testAddressScopes() { assertEquals(RT_SCOPE_HOST, new LinkAddress("::/128").getScope()); assertEquals(RT_SCOPE_HOST, new LinkAddress("0.0.0.0/32").getScope()); @@ -216,6 +229,7 @@ public class LinkAddressTest extends AndroidTestCase { assertFalse(l2 + " unexpectedly equal to " + l1, l2.equals(l1)); } + @Test public void testEqualsAndSameAddressAs() { LinkAddress l1, l2, l3; @@ -293,26 +307,17 @@ public class LinkAddressTest extends AndroidTestCase { assertIsSameAddressAs(l1, l2); } + @Test public void testHashCode() { - LinkAddress l; - - l = new LinkAddress(V4_ADDRESS, 23); - assertEquals(-982787, l.hashCode()); - - l = new LinkAddress(V4_ADDRESS, 23, 0, RT_SCOPE_HOST); - assertEquals(-971865, l.hashCode()); - - l = new LinkAddress(V4_ADDRESS, 27); - assertEquals(-982743, l.hashCode()); - - l = new LinkAddress(V6_ADDRESS, 64); - assertEquals(1076522926, l.hashCode()); + LinkAddress l1, l2; - l = new LinkAddress(V6_ADDRESS, 128); - assertEquals(1076523630, l.hashCode()); + l1 = new LinkAddress(V4_ADDRESS, 23); + l2 = new LinkAddress(V4_ADDRESS, 23, 0, RT_SCOPE_HOST); + assertNotEquals(l1.hashCode(), l2.hashCode()); - l = new LinkAddress(V6_ADDRESS, 128, IFA_F_TENTATIVE, RT_SCOPE_UNIVERSE); - assertEquals(1076524846, l.hashCode()); + l1 = new LinkAddress(V6_ADDRESS, 128); + l2 = new LinkAddress(V6_ADDRESS, 128, IFA_F_TENTATIVE, RT_SCOPE_UNIVERSE); + assertNotEquals(l1.hashCode(), l2.hashCode()); } private LinkAddress passThroughParcel(LinkAddress l) { @@ -334,6 +339,7 @@ public class LinkAddressTest extends AndroidTestCase { assertEquals(l, l2); } + @Test public void testParceling() { LinkAddress l; @@ -352,6 +358,7 @@ public class LinkAddressTest extends AndroidTestCase { assertFalse(msg, l.isGlobalPreferred()); } + @Test public void testIsGlobalPreferred() { LinkAddress l; diff --git a/tests/net/java/android/net/NetworkStatsHistoryTest.java b/tests/net/java/android/net/NetworkStatsHistoryTest.java index e7b91b568d74..1c0c14eac08b 100644 --- a/tests/net/java/android/net/NetworkStatsHistoryTest.java +++ b/tests/net/java/android/net/NetworkStatsHistoryTest.java @@ -485,6 +485,21 @@ public class NetworkStatsHistoryTest extends AndroidTestCase { assertTrue(stats.intersects(Long.MIN_VALUE, TEST_START + 1)); } + public void testSetValues() throws Exception { + stats = new NetworkStatsHistory(HOUR_IN_MILLIS); + stats.recordData(TEST_START, TEST_START + 1, + new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L)); + + assertEquals(1024L + 2048L, stats.getTotalBytes()); + + final NetworkStatsHistory.Entry entry = stats.getValues(0, null); + entry.rxBytes /= 2; + entry.txBytes *= 2; + stats.setValues(0, entry); + + assertEquals(512L + 4096L, stats.getTotalBytes()); + } + private static void assertIndexBeforeAfter( NetworkStatsHistory stats, int before, int after, long time) { assertEquals("unexpected before", before, stats.getIndexBefore(time)); diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java index bfbb8cc541d7..5008a4188905 100644 --- a/tests/net/java/android/net/apf/ApfTest.java +++ b/tests/net/java/android/net/apf/ApfTest.java @@ -614,9 +614,10 @@ public class ApfTest extends AndroidTestCase { private final long mFixedTimeMs = SystemClock.elapsedRealtime(); public TestApfFilter(IpManager.Callback ipManagerCallback, boolean multicastFilter, - boolean ieee802_3Filter, IpConnectivityLog log) throws Exception { + boolean ieee802_3Filter, int[] ethTypeBlackList, + IpConnectivityLog log) throws Exception { super(new ApfCapabilities(2, 1700, ARPHRD_ETHER), NetworkInterface.getByName("lo"), - ipManagerCallback, multicastFilter, ieee802_3Filter, log); + ipManagerCallback, multicastFilter, ieee802_3Filter, ethTypeBlackList, log); } // Pretend an RA packet has been received and show it to ApfFilter. @@ -744,9 +745,10 @@ public class ApfTest extends AndroidTestCase { LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19); LinkProperties lp = new LinkProperties(); lp.addLinkAddress(link); + final int[] ethTypeBlackList = {}; ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, - ALLOW_802_3_FRAMES, mLog); + ALLOW_802_3_FRAMES, ethTypeBlackList, mLog); apfFilter.setLinkProperties(lp); byte[] program = ipManagerCallback.getApfProgram(); @@ -796,9 +798,10 @@ public class ApfTest extends AndroidTestCase { @SmallTest public void testApfFilterIPv6() throws Exception { + final int[] ethTypeBlackList = {}; MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, - ALLOW_802_3_FRAMES, mLog); + ALLOW_802_3_FRAMES, ethTypeBlackList, mLog); byte[] program = ipManagerCallback.getApfProgram(); // Verify empty IPv6 packet is passed @@ -833,6 +836,7 @@ public class ApfTest extends AndroidTestCase { final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255}; final byte[] multicastIpv4Addr = {(byte)224,0,0,1}; final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb}; + final int[] ethTypeBlackList = {}; MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); LinkAddress link = new LinkAddress(InetAddress.getByAddress(unicastIpv4Addr), 24); @@ -840,7 +844,7 @@ public class ApfTest extends AndroidTestCase { lp.addLinkAddress(link); ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, - DROP_802_3_FRAMES, mLog); + DROP_802_3_FRAMES, ethTypeBlackList, mLog); apfFilter.setLinkProperties(lp); byte[] program = ipManagerCallback.getApfProgram(); @@ -903,7 +907,7 @@ public class ApfTest extends AndroidTestCase { ipManagerCallback.resetApfProgramWait(); apfFilter.shutdown(); apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, - DROP_802_3_FRAMES, mLog); + DROP_802_3_FRAMES, ethTypeBlackList, mLog); apfFilter.setLinkProperties(lp); program = ipManagerCallback.getApfProgram(); assertDrop(program, mcastv4packet.array()); @@ -924,9 +928,10 @@ public class ApfTest extends AndroidTestCase { LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19); LinkProperties lp = new LinkProperties(); lp.addLinkAddress(link); + final int[] ethTypeBlackList = {}; ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, - ALLOW_802_3_FRAMES, mLog); + ALLOW_802_3_FRAMES, ethTypeBlackList, mLog); apfFilter.setLinkProperties(lp); byte[] program = ipManagerCallback.getApfProgram(); @@ -948,7 +953,7 @@ public class ApfTest extends AndroidTestCase { ipManagerCallback.resetApfProgramWait(); apfFilter.shutdown(); apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, - DROP_802_3_FRAMES, mLog); + DROP_802_3_FRAMES, ethTypeBlackList, mLog); apfFilter.setLinkProperties(lp); program = ipManagerCallback.getApfProgram(); @@ -968,6 +973,70 @@ public class ApfTest extends AndroidTestCase { apfFilter.shutdown(); } + @SmallTest + public void testApfFilterEthTypeBL() throws Exception { + MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); + LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19); + LinkProperties lp = new LinkProperties(); + lp.addLinkAddress(link); + final int[] emptyBlackList = {}; + final int[] ipv4BlackList = {ETH_P_IP}; + final int[] ipv4Ipv6BlackList = {ETH_P_IP, ETH_P_IPV6}; + + ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, + ALLOW_802_3_FRAMES, emptyBlackList, mLog); + apfFilter.setLinkProperties(lp); + + byte[] program = ipManagerCallback.getApfProgram(); + + // Verify empty packet of 100 zero bytes is passed + // Note that eth-type = 0 makes it an IEEE802.3 frame + ByteBuffer packet = ByteBuffer.wrap(new byte[100]); + assertPass(program, packet.array()); + + // Verify empty packet with IPv4 is passed + packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); + assertPass(program, packet.array()); + + // Verify empty IPv6 packet is passed + packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); + assertPass(program, packet.array()); + + // Now add IPv4 to the black list + ipManagerCallback.resetApfProgramWait(); + apfFilter.shutdown(); + apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, + ALLOW_802_3_FRAMES, ipv4BlackList, mLog); + apfFilter.setLinkProperties(lp); + program = ipManagerCallback.getApfProgram(); + + // Verify that IPv4 frame will be dropped + packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); + assertDrop(program, packet.array()); + + // Verify that IPv6 frame will pass + packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); + assertPass(program, packet.array()); + + // Now let us have both IPv4 and IPv6 in the black list + ipManagerCallback.resetApfProgramWait(); + apfFilter.shutdown(); + apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, + ALLOW_802_3_FRAMES, ipv4Ipv6BlackList, mLog); + apfFilter.setLinkProperties(lp); + program = ipManagerCallback.getApfProgram(); + + // Verify that IPv4 frame will be dropped + packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP); + assertDrop(program, packet.array()); + + // Verify that IPv6 frame will be dropped + packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6); + assertDrop(program, packet.array()); + + apfFilter.shutdown(); + } + private byte[] getProgram(MockIpManagerCallback cb, ApfFilter filter, LinkProperties lp) { cb.resetApfProgramWait(); filter.setLinkProperties(lp); @@ -991,9 +1060,10 @@ public class ApfTest extends AndroidTestCase { @SmallTest public void testApfFilterArp() throws Exception { + final int[] ethTypeBlackList = {}; MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, - DROP_802_3_FRAMES, mLog); + DROP_802_3_FRAMES, ethTypeBlackList, mLog); // Verify initially ARP request filter is off, and GARP filter is on. verifyArpFilter(ipManagerCallback.getApfProgram(), PASS); @@ -1114,8 +1184,9 @@ public class ApfTest extends AndroidTestCase { @SmallTest public void testApfFilterRa() throws Exception { MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback(); + final int[] ethTypeBlackList = {}; TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, - DROP_802_3_FRAMES, mLog); + DROP_802_3_FRAMES, ethTypeBlackList, mLog); byte[] program = ipManagerCallback.getApfProgram(); final int ROUTER_LIFETIME = 1000; @@ -1256,9 +1327,10 @@ public class ApfTest extends AndroidTestCase { public void testRaParsing() throws Exception { final int maxRandomPacketSize = 512; final Random r = new Random(); + final int[] ethTypeBlackList = {}; MockIpManagerCallback cb = new MockIpManagerCallback(); TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST, - DROP_802_3_FRAMES, mLog); + DROP_802_3_FRAMES, ethTypeBlackList, mLog); for (int i = 0; i < 1000; i++) { byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)]; r.nextBytes(packet); @@ -1275,9 +1347,10 @@ public class ApfTest extends AndroidTestCase { public void testRaProcessing() throws Exception { final int maxRandomPacketSize = 512; final Random r = new Random(); + final int[] ethTypeBlackList = {}; MockIpManagerCallback cb = new MockIpManagerCallback(); TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST, - DROP_802_3_FRAMES, mLog); + DROP_802_3_FRAMES, ethTypeBlackList, mLog); for (int i = 0; i < 1000; i++) { byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)]; r.nextBytes(packet); diff --git a/tests/net/java/android/net/ip/IpManagerTest.java b/tests/net/java/android/net/ip/IpManagerTest.java index dc77e22082ba..541f91adf747 100644 --- a/tests/net/java/android/net/ip/IpManagerTest.java +++ b/tests/net/java/android/net/ip/IpManagerTest.java @@ -17,6 +17,8 @@ package android.net.ip; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Mockito.any; import static org.mockito.Mockito.eq; @@ -32,8 +34,11 @@ import android.app.AlarmManager; import android.content.ContentResolver; import android.content.Context; import android.content.res.Resources; +import android.net.INetd; import android.net.IpPrefix; import android.net.LinkAddress; +import android.net.LinkProperties; +import android.net.RouteInfo; import android.net.ip.IpManager.Callback; import android.net.ip.IpManager.InitialConfiguration; import android.net.ip.IpManager.ProvisioningConfiguration; @@ -45,16 +50,20 @@ import android.test.mock.MockContentResolver; import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.R; +import com.android.server.net.BaseNetworkObserver; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; +import java.util.Arrays; +import java.util.List; import java.util.HashSet; import java.util.Set; @@ -71,11 +80,14 @@ public class IpManagerTest { @Mock private Context mContext; @Mock private INetworkManagementService mNMService; + @Mock private INetd mNetd; @Mock private Resources mResources; @Mock private Callback mCb; @Mock private AlarmManager mAlarm; private MockContentResolver mContentResolver; + BaseNetworkObserver mObserver; + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -91,9 +103,13 @@ public class IpManagerTest { } private IpManager makeIpManager(String ifname) throws Exception { - final IpManager ipm = new IpManager(mContext, ifname, mCb, mNMService); + final IpManager ipm = new IpManager(mContext, ifname, mCb, mNMService, mNetd); verify(mNMService, timeout(100).times(1)).disableIpv6(ifname); verify(mNMService, timeout(100).times(1)).clearInterfaceAddresses(ifname); + ArgumentCaptor<BaseNetworkObserver> arg = + ArgumentCaptor.forClass(BaseNetworkObserver.class); + verify(mNMService, times(1)).registerObserver(arg.capture()); + mObserver = arg.getValue(); reset(mNMService); return ipm; } @@ -131,6 +147,134 @@ public class IpManagerTest { } @Test + public void testProvisioningWithInitialConfiguration() throws Exception { + final String iface = "test_wlan0"; + final IpManager ipm = makeIpManager(iface); + + String[] addresses = { + "fe80::a4be:f92:e1f7:22d1/64", + "fe80::f04a:8f6:6a32:d756/64", + "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64" + }; + String[] prefixes = { "fe80::/64", "fd2c:4e57:8e3c::/64" }; + + ProvisioningConfiguration config = new ProvisioningConfiguration.Builder() + .withoutIPv4() + .withoutIpReachabilityMonitor() + .withInitialConfiguration(conf(links(addresses), prefixes(prefixes), ips())) + .build(); + + ipm.startProvisioning(config); + verify(mCb, times(1)).setNeighborDiscoveryOffload(true); + verify(mCb, timeout(100).times(1)).setFallbackMulticastFilter(false); + verify(mCb, never()).onProvisioningFailure(any()); + + for (String addr : addresses) { + String[] parts = addr.split("/"); + verify(mNetd, timeout(100).times(1)) + .interfaceAddAddress(iface, parts[0], Integer.parseInt(parts[1])); + } + + final int lastAddr = addresses.length - 1; + + // Add N - 1 addresses + for (int i = 0; i < lastAddr; i++) { + mObserver.addressUpdated(iface, new LinkAddress(addresses[i])); + verify(mCb, timeout(100).times(1)).onLinkPropertiesChange(any()); + } + + // Add Nth address + mObserver.addressUpdated(iface, new LinkAddress(addresses[lastAddr])); + LinkProperties want = linkproperties(links(addresses), routes(prefixes)); + want.setInterfaceName(iface); + verify(mCb, timeout(100).times(1)).onProvisioningSuccess(eq(want)); + + ipm.stop(); + verify(mNMService, timeout(100).times(1)).disableIpv6(iface); + verify(mNMService, timeout(100).times(1)).clearInterfaceAddresses(iface); + } + + @Test + public void testIsProvisioned() throws Exception { + InitialConfiguration empty = conf(links(), prefixes()); + IsProvisionedTestCase[] testcases = { + // nothing + notProvisionedCase(links(), routes(), dns(), null), + notProvisionedCase(links(), routes(), dns(), empty), + + // IPv4 + provisionedCase(links("192.0.2.12/24"), routes(), dns(), empty), + + // IPv6 + notProvisionedCase( + links("fe80::a4be:f92:e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"), + routes(), dns(), empty), + notProvisionedCase( + links("fe80::a4be:f92:e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"), + routes("fe80::/64", "fd2c:4e57:8e3c::/64"), dns("fd00:1234:5678::1000"), empty), + provisionedCase( + links("2001:db8:dead:beef:f00::a0/64", "fe80::1/64"), + routes("::/0"), + dns("2001:db8:dead:beef:f00::02"), empty), + + // Initial configuration + provisionedCase( + links("fe80::e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"), + routes("fe80::/64", "fd2c:4e57:8e3c::/64"), + dns(), + conf(links("fe80::e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"), + prefixes( "fe80::/64", "fd2c:4e57:8e3c::/64"), ips())) + }; + + for (IsProvisionedTestCase testcase : testcases) { + if (IpManager.isProvisioned(testcase.lp, testcase.config) != testcase.isProvisioned) { + fail(testcase.errorMessage()); + } + } + } + + static class IsProvisionedTestCase { + boolean isProvisioned; + LinkProperties lp; + InitialConfiguration config; + + String errorMessage() { + return String.format("expected %s with config %s to be %s, but was %s", + lp, config, provisioned(isProvisioned), provisioned(!isProvisioned)); + } + + static String provisioned(boolean isProvisioned) { + return isProvisioned ? "provisioned" : "not provisioned"; + } + } + + static IsProvisionedTestCase provisionedCase(Set<LinkAddress> lpAddrs, Set<RouteInfo> lpRoutes, + Set<InetAddress> lpDns, InitialConfiguration config) { + return provisioningTest(true, lpAddrs, lpRoutes, lpDns, config); + } + + static IsProvisionedTestCase notProvisionedCase(Set<LinkAddress> lpAddrs, + Set<RouteInfo> lpRoutes, Set<InetAddress> lpDns, InitialConfiguration config) { + return provisioningTest(false, lpAddrs, lpRoutes, lpDns, config); + } + + static IsProvisionedTestCase provisioningTest(boolean isProvisioned, Set<LinkAddress> lpAddrs, + Set<RouteInfo> lpRoutes, Set<InetAddress> lpDns, InitialConfiguration config) { + IsProvisionedTestCase testcase = new IsProvisionedTestCase(); + testcase.isProvisioned = isProvisioned; + testcase.lp = new LinkProperties(); + testcase.lp.setLinkAddresses(lpAddrs); + for (RouteInfo route : lpRoutes) { + testcase.lp.addRoute(route); + } + for (InetAddress dns : lpDns) { + testcase.lp.addDnsServer(dns); + } + testcase.config = config; + return testcase; + } + + @Test public void testInitialConfigurations() throws Exception { InitialConfigurationTestCase[] testcases = { validConf("valid IPv4 configuration", @@ -152,6 +296,7 @@ public class IpManagerTest { prefixes("fd00:1234:5678::/48"), dns("fd00:1234:5678::1000")), + invalidConf("empty configuration", links(), prefixes(), dns()), invalidConf("v4 addr and dns not in any prefix", links("192.0.2.12/24"), prefixes("198.51.100.0/24"), dns("192.0.2.2")), invalidConf("v4 addr not in any prefix", @@ -189,10 +334,9 @@ public class IpManagerTest { return String.format("%s: expected configuration %s to be %s, but was %s", descr, config, validString(isValid), validString(!isValid)); } - } - - static String validString(boolean isValid) { - return isValid ? VALID : INVALID; + static String validString(boolean isValid) { + return isValid ? VALID : INVALID; + } } static InitialConfigurationTestCase validConf(String descr, Set<LinkAddress> links, @@ -214,6 +358,19 @@ public class IpManagerTest { return testcase; } + static LinkProperties linkproperties(Set<LinkAddress> addresses, Set<RouteInfo> routes) { + LinkProperties lp = new LinkProperties(); + lp.setLinkAddresses(addresses); + for (RouteInfo route : routes) { + lp.addRoute(route); + } + return lp; + } + + static InitialConfiguration conf(Set<LinkAddress> links, Set<IpPrefix> prefixes) { + return conf(links, prefixes, new HashSet<>()); + } + static InitialConfiguration conf( Set<LinkAddress> links, Set<IpPrefix> prefixes, Set<InetAddress> dns) { InitialConfiguration conf = new InitialConfiguration(); @@ -223,6 +380,10 @@ public class IpManagerTest { return conf; } + static Set<RouteInfo> routes(String... routes) { + return mapIntoSet(routes, (r) -> new RouteInfo(new IpPrefix(r))); + } + static Set<IpPrefix> prefixes(String... prefixes) { return mapIntoSet(prefixes, IpPrefix::new); } @@ -254,4 +415,44 @@ public class IpManagerTest { interface Fn<A,B> { B call(A a) throws Exception; } + + @Test + public void testAll() { + List<String> list1 = Arrays.asList(); + List<String> list2 = Arrays.asList("foo"); + List<String> list3 = Arrays.asList("bar", "baz"); + List<String> list4 = Arrays.asList("foo", "bar", "baz"); + + assertTrue(IpManager.all(list1, (x) -> false)); + assertFalse(IpManager.all(list2, (x) -> false)); + assertTrue(IpManager.all(list3, (x) -> true)); + assertTrue(IpManager.all(list2, (x) -> x.charAt(0) == 'f')); + assertFalse(IpManager.all(list4, (x) -> x.charAt(0) == 'f')); + } + + @Test + public void testAny() { + List<String> list1 = Arrays.asList(); + List<String> list2 = Arrays.asList("foo"); + List<String> list3 = Arrays.asList("bar", "baz"); + List<String> list4 = Arrays.asList("foo", "bar", "baz"); + + assertFalse(IpManager.any(list1, (x) -> true)); + assertTrue(IpManager.any(list2, (x) -> true)); + assertTrue(IpManager.any(list2, (x) -> x.charAt(0) == 'f')); + assertFalse(IpManager.any(list3, (x) -> x.charAt(0) == 'f')); + assertTrue(IpManager.any(list4, (x) -> x.charAt(0) == 'f')); + } + + @Test + public void testFindAll() { + List<String> list1 = Arrays.asList(); + List<String> list2 = Arrays.asList("foo"); + List<String> list3 = Arrays.asList("foo", "bar", "baz"); + + assertEquals(list1, IpManager.findAll(list1, (x) -> true)); + assertEquals(list1, IpManager.findAll(list3, (x) -> false)); + assertEquals(list3, IpManager.findAll(list3, (x) -> true)); + assertEquals(list2, IpManager.findAll(list3, (x) -> x.charAt(0) == 'f')); + } } diff --git a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java b/tests/net/java/com/android/server/NetworkManagementServiceTest.java index f841bf9bff22..2ac73dbd4f52 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java +++ b/tests/net/java/com/android/server/NetworkManagementServiceTest.java @@ -16,16 +16,6 @@ package com.android.server; -import android.content.Context; -import android.net.LinkAddress; -import android.net.LocalSocket; -import android.net.LocalServerSocket; -import android.os.Binder; -import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; -import com.android.server.net.BaseNetworkObserver; -import com.android.internal.util.test.BroadcastInterceptingContext; - import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; @@ -33,14 +23,37 @@ import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import android.content.Context; +import android.net.INetd; +import android.net.LinkAddress; +import android.net.LocalSocket; +import android.net.LocalServerSocket; +import android.os.BatteryStats; +import android.os.Binder; +import android.os.IBinder; +import android.support.test.runner.AndroidJUnit4; +import android.test.suitebuilder.annotation.SmallTest; + +import com.android.internal.app.IBatteryStats; +import com.android.server.NetworkManagementService.SystemServices; +import com.android.server.net.BaseNetworkObserver; + import java.io.IOException; import java.io.OutputStream; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + /** * Tests for {@link NetworkManagementService}. */ -@LargeTest -public class NetworkManagementServiceTest extends AndroidTestCase { +@RunWith(AndroidJUnit4.class) +@SmallTest +public class NetworkManagementServiceTest { private static final String SOCKET_NAME = "__test__NetworkManagementServiceTest"; private NetworkManagementService mNMService; @@ -48,27 +61,46 @@ public class NetworkManagementServiceTest extends AndroidTestCase { private LocalSocket mSocket; private OutputStream mOutputStream; - @Override + @Mock private Context mContext; + @Mock private IBatteryStats.Stub mBatteryStatsService; + @Mock private INetd.Stub mNetdService; + + private final SystemServices mServices = new SystemServices() { + @Override + public IBinder getService(String name) { + switch (name) { + case BatteryStats.SERVICE_NAME: + return mBatteryStatsService; + default: + throw new UnsupportedOperationException("Unknown service " + name); + } + } + @Override + public void registerLocalService(NetworkManagementInternal nmi) { + } + @Override + public INetd getNetd() { + return mNetdService; + } + }; + + @Before public void setUp() throws Exception { - super.setUp(); - // TODO: make this unnecessary. runtest might already make it unnecessary. - System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString()); + MockitoAnnotations.initMocks(this); // Set up a sheltered test environment. - BroadcastInterceptingContext context = new BroadcastInterceptingContext(getContext()); mServerSocket = new LocalServerSocket(SOCKET_NAME); // Start the service and wait until it connects to our socket. - mNMService = NetworkManagementService.create(context, SOCKET_NAME); + mNMService = NetworkManagementService.create(mContext, SOCKET_NAME, mServices); mSocket = mServerSocket.accept(); mOutputStream = mSocket.getOutputStream(); } - @Override + @After public void tearDown() throws Exception { if (mSocket != null) mSocket.close(); if (mServerSocket != null) mServerSocket.close(); - super.tearDown(); } /** @@ -80,12 +112,13 @@ public class NetworkManagementServiceTest extends AndroidTestCase { } private static <T> T expectSoon(T mock) { - return verify(mock, timeout(100)); + return verify(mock, timeout(200)); } /** * Tests that network observers work properly. */ + @Test public void testNetworkObservers() throws Exception { BaseNetworkObserver observer = mock(BaseNetworkObserver.class); doReturn(new Binder()).when(observer).asBinder(); // Used by registerObserver. @@ -143,22 +176,16 @@ public class NetworkManagementServiceTest extends AndroidTestCase { * Interface class activity. */ - sendMessage("613 IfaceClass active rmnet0"); - expectSoon(observer).interfaceClassDataActivityChanged("rmnet0", true, 0); - - sendMessage("613 IfaceClass active rmnet0 1234"); - expectSoon(observer).interfaceClassDataActivityChanged("rmnet0", true, 1234); - - sendMessage("613 IfaceClass idle eth0"); - expectSoon(observer).interfaceClassDataActivityChanged("eth0", false, 0); + sendMessage("613 IfaceClass active 1 1234 10012"); + expectSoon(observer).interfaceClassDataActivityChanged("1", true, 1234); - sendMessage("613 IfaceClass idle eth0 1234"); - expectSoon(observer).interfaceClassDataActivityChanged("eth0", false, 1234); + sendMessage("613 IfaceClass idle 9 5678"); + expectSoon(observer).interfaceClassDataActivityChanged("9", false, 5678); - sendMessage("613 IfaceClass reallyactive rmnet0 1234"); - expectSoon(observer).interfaceClassDataActivityChanged("rmnet0", false, 1234); + sendMessage("613 IfaceClass reallyactive 9 4321"); + expectSoon(observer).interfaceClassDataActivityChanged("9", false, 4321); - sendMessage("613 InterfaceClass reallyactive rmnet0"); + sendMessage("613 InterfaceClass reallyactive 1"); // Invalid group. diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index f0b3724955aa..4f18da7056ef 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -32,6 +32,7 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.UserInfo; +import android.content.res.Resources; import android.net.NetworkInfo.DetailedState; import android.net.UidRange; import android.net.VpnService; @@ -46,6 +47,7 @@ import android.test.suitebuilder.annotation.SmallTest; import android.util.ArrayMap; import android.util.ArraySet; +import com.android.internal.R; import com.android.internal.net.VpnConfig; import org.mockito.Answers; @@ -116,6 +118,9 @@ public class VpnTest extends AndroidTestCase { when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOps); when(mContext.getSystemService(eq(Context.NOTIFICATION_SERVICE))) .thenReturn(mNotificationManager); + when(mContext.getString(R.string.config_customVpnAlwaysOnDisconnectedDialogComponent)) + .thenReturn(Resources.getSystem().getString( + R.string.config_customVpnAlwaysOnDisconnectedDialogComponent)); // Used by {@link Notification.Builder} ApplicationInfo applicationInfo = new ApplicationInfo(); @@ -346,7 +351,7 @@ public class VpnTest extends AndroidTestCase { // Apps that opt out explicitly are not supported appInfo.targetSdkVersion = VERSION_CODES.CUR_DEVELOPMENT; Bundle metaData = new Bundle(); - metaData.putBoolean(VpnService.METADATA_SUPPORTS_ALWAYS_ON, false); + metaData.putBoolean(VpnService.SERVICE_META_DATA_SUPPORTS_ALWAYS_ON, false); svcInfo.metaData = metaData; assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0])); } diff --git a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java index dcb9723fa5e2..dfe3f982e5bf 100644 --- a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java +++ b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java @@ -17,7 +17,10 @@ package com.android.server.connectivity.tethering; import static android.net.NetworkStats.SET_DEFAULT; +import static android.net.NetworkStats.STATS_PER_IFACE; +import static android.net.NetworkStats.STATS_PER_UID; import static android.net.NetworkStats.TAG_NONE; +import static android.net.NetworkStats.UID_ALL; import static android.net.TrafficStats.UID_TETHERING; import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED; import static com.android.server.connectivity.tethering.OffloadHardwareInterface.ForwardedStats; @@ -25,6 +28,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; @@ -45,6 +49,7 @@ import android.net.LinkProperties; import android.net.NetworkStats; import android.net.RouteInfo; import android.net.util.SharedLog; +import android.os.ConditionVariable; import android.os.Handler; import android.os.Looper; import android.os.INetworkManagementService; @@ -74,6 +79,15 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) @SmallTest public class OffloadControllerTest { + private static final String RNDIS0 = "test_rndis0"; + private static final String RMNET0 = "test_rmnet_data0"; + private static final String WLAN0 = "test_wlan0"; + + private static final String IPV6_LINKLOCAL = "fe80::/64"; + private static final String IPV6_DOC_PREFIX = "2001:db8::/64"; + private static final String IPV6_DISCARD_PREFIX = "100::/64"; + private static final String USB_PREFIX = "192.168.42.0/24"; + private static final String WIFI_PREFIX = "192.168.43.0/24"; @Mock private OffloadHardwareInterface mHardware; @Mock private ApplicationInfo mApplicationInfo; @@ -83,6 +97,8 @@ public class OffloadControllerTest { ArgumentCaptor.forClass(ArrayList.class); private final ArgumentCaptor<ITetheringStatsProvider.Stub> mTetherStatsProviderCaptor = ArgumentCaptor.forClass(ITetheringStatsProvider.Stub.class); + private final ArgumentCaptor<OffloadHardwareInterface.ControlCallback> mControlCallbackCaptor = + ArgumentCaptor.forClass(OffloadHardwareInterface.ControlCallback.class); private MockContentResolver mContentResolver; @Before public void setUp() { @@ -101,15 +117,23 @@ public class OffloadControllerTest { private void setupFunctioningHardwareInterface() { when(mHardware.initOffloadConfig()).thenReturn(true); - when(mHardware.initOffloadControl(any(OffloadHardwareInterface.ControlCallback.class))) + when(mHardware.initOffloadControl(mControlCallbackCaptor.capture())) .thenReturn(true); + when(mHardware.setUpstreamParameters(anyString(), any(), any(), any())).thenReturn(true); when(mHardware.getForwardedStats(any())).thenReturn(new ForwardedStats()); + when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(true); } private void enableOffload() { Settings.Global.putInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 0); } + private void waitForIdle() { + ConditionVariable cv = new ConditionVariable(); + new Handler(Looper.getMainLooper()).post(() -> { cv.open(); }); + cv.block(); + } + private OffloadController makeOffloadController() throws Exception { OffloadController offload = new OffloadController(new Handler(Looper.getMainLooper()), mHardware, mContentResolver, mNMService, new SharedLog("test")); @@ -219,10 +243,8 @@ public class OffloadControllerTest { inOrder.verify(mHardware, times(1)).setLocalPrefixes(mStringArrayCaptor.capture()); ArrayList<String> localPrefixes = mStringArrayCaptor.getValue(); assertEquals(4, localPrefixes.size()); - assertTrue(localPrefixes.contains("127.0.0.0/8")); - assertTrue(localPrefixes.contains("192.0.2.0/24")); - assertTrue(localPrefixes.contains("fe80::/64")); - assertTrue(localPrefixes.contains("2001:db8::/64")); + assertArrayListContains(localPrefixes, + "127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64"); inOrder.verifyNoMoreInteractions(); offload.setUpstreamLinkProperties(null); @@ -243,6 +265,7 @@ public class OffloadControllerTest { inOrder.verify(mHardware, never()).setLocalPrefixes(mStringArrayCaptor.capture()); inOrder.verify(mHardware, times(1)).setUpstreamParameters( eq(testIfName), eq(null), eq(null), eq(null)); + inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE)); inOrder.verifyNoMoreInteractions(); final String ipv4Addr = "192.0.2.5"; @@ -260,6 +283,7 @@ public class OffloadControllerTest { inOrder.verify(mHardware, times(1)).setUpstreamParameters( eq(testIfName), eq(ipv4Addr), eq(null), eq(null)); inOrder.verify(mHardware, times(1)).getForwardedStats(eq(testIfName)); + inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE)); inOrder.verifyNoMoreInteractions(); final String ipv4Gateway = "192.0.2.1"; @@ -270,6 +294,7 @@ public class OffloadControllerTest { inOrder.verify(mHardware, times(1)).setUpstreamParameters( eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), eq(null)); inOrder.verify(mHardware, times(1)).getForwardedStats(eq(testIfName)); + inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE)); inOrder.verifyNoMoreInteractions(); final String ipv6Gw1 = "fe80::cafe"; @@ -283,6 +308,7 @@ public class OffloadControllerTest { ArrayList<String> v6gws = mStringArrayCaptor.getValue(); assertEquals(1, v6gws.size()); assertTrue(v6gws.contains(ipv6Gw1)); + inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE)); inOrder.verifyNoMoreInteractions(); final String ipv6Gw2 = "fe80::d00d"; @@ -297,6 +323,7 @@ public class OffloadControllerTest { assertEquals(2, v6gws.size()); assertTrue(v6gws.contains(ipv6Gw1)); assertTrue(v6gws.contains(ipv6Gw2)); + inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE)); inOrder.verifyNoMoreInteractions(); final LinkProperties stacked = new LinkProperties(); @@ -315,6 +342,7 @@ public class OffloadControllerTest { assertEquals(2, v6gws.size()); assertTrue(v6gws.contains(ipv6Gw1)); assertTrue(v6gws.contains(ipv6Gw2)); + inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE)); inOrder.verifyNoMoreInteractions(); // Add in some IPv6 upstream info. When there is a tethered downstream @@ -331,12 +359,9 @@ public class OffloadControllerTest { inOrder.verify(mHardware, times(1)).setLocalPrefixes(mStringArrayCaptor.capture()); localPrefixes = mStringArrayCaptor.getValue(); assertEquals(6, localPrefixes.size()); - assertTrue(localPrefixes.contains("127.0.0.0/8")); - assertTrue(localPrefixes.contains("192.0.2.0/24")); - assertTrue(localPrefixes.contains("fe80::/64")); - assertTrue(localPrefixes.contains("2001:db8::/64")); - assertTrue(localPrefixes.contains("2001:db8::6173:7369:676e:6564/128")); - assertTrue(localPrefixes.contains("2001:db8::7261:6e64:6f6d/128")); + assertArrayListContains(localPrefixes, + "127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64", + "2001:db8::6173:7369:676e:6564/128", "2001:db8::7261:6e64:6f6d/128"); // The relevant parts of the LinkProperties have not changed, but at the // moment we do not de-dup upstream LinkProperties this carefully. inOrder.verify(mHardware, times(1)).setUpstreamParameters( @@ -346,6 +371,7 @@ public class OffloadControllerTest { assertTrue(v6gws.contains(ipv6Gw1)); assertTrue(v6gws.contains(ipv6Gw2)); inOrder.verify(mHardware, times(1)).getForwardedStats(eq(testIfName)); + inOrder.verify(mHardware, times(1)).setDataLimit(eq(testIfName), eq(Long.MAX_VALUE)); inOrder.verifyNoMoreInteractions(); // Completely identical LinkProperties updates are de-duped. @@ -363,7 +389,6 @@ public class OffloadControllerTest { assertEquals(stats.txBytes, entry.txBytes); assertEquals(SET_DEFAULT, entry.set); assertEquals(TAG_NONE, entry.tag); - assertEquals(UID_TETHERING, entry.uid); } @Test @@ -388,33 +413,217 @@ public class OffloadControllerTest { when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn(ethernetStats); when(mHardware.getForwardedStats(eq(mobileIface))).thenReturn(mobileStats); + InOrder inOrder = inOrder(mHardware); + final LinkProperties lp = new LinkProperties(); lp.setInterfaceName(ethernetIface); offload.setUpstreamLinkProperties(lp); + // Previous upstream was null, so no stats are fetched. + inOrder.verify(mHardware, never()).getForwardedStats(any()); lp.setInterfaceName(mobileIface); offload.setUpstreamLinkProperties(lp); + // Expect that we fetch stats from the previous upstream. + inOrder.verify(mHardware, times(1)).getForwardedStats(eq(ethernetIface)); lp.setInterfaceName(ethernetIface); offload.setUpstreamLinkProperties(lp); + // Expect that we fetch stats from the previous upstream. + inOrder.verify(mHardware, times(1)).getForwardedStats(eq(mobileIface)); + ethernetStats = new ForwardedStats(); ethernetStats.rxBytes = 100000; ethernetStats.txBytes = 100000; + when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn(ethernetStats); offload.setUpstreamLinkProperties(null); + // Expect that we fetch stats from the previous upstream. + inOrder.verify(mHardware, times(1)).getForwardedStats(eq(ethernetIface)); + + ITetheringStatsProvider provider = mTetherStatsProviderCaptor.getValue(); + NetworkStats stats = provider.getTetherStats(STATS_PER_IFACE); + NetworkStats perUidStats = provider.getTetherStats(STATS_PER_UID); + waitForIdle(); + // There is no current upstream, so no stats are fetched. + inOrder.verify(mHardware, never()).getForwardedStats(any()); + inOrder.verify(mHardware, times(1)).setUpstreamParameters( + eq(null), eq(null), eq(null), eq(null)); + inOrder.verifyNoMoreInteractions(); - NetworkStats stats = mTetherStatsProviderCaptor.getValue().getTetherStats(); assertEquals(2, stats.size()); + assertEquals(2, perUidStats.size()); NetworkStats.Entry entry = null; + for (int i = 0; i < stats.size(); i++) { + assertEquals(UID_ALL, stats.getValues(i, entry).uid); + assertEquals(UID_TETHERING, perUidStats.getValues(i, entry).uid); + } + int ethernetPosition = ethernetIface.equals(stats.getValues(0, entry).iface) ? 0 : 1; int mobilePosition = 1 - ethernetPosition; entry = stats.getValues(mobilePosition, entry); assertNetworkStats(mobileIface, mobileStats, entry); + entry = perUidStats.getValues(mobilePosition, entry); + assertNetworkStats(mobileIface, mobileStats, entry); ethernetStats.rxBytes = 12345 + 100000; ethernetStats.txBytes = 54321 + 100000; entry = stats.getValues(ethernetPosition, entry); assertNetworkStats(ethernetIface, ethernetStats, entry); + entry = perUidStats.getValues(ethernetPosition, entry); + assertNetworkStats(ethernetIface, ethernetStats, entry); + } + + @Test + public void testSetInterfaceQuota() throws Exception { + setupFunctioningHardwareInterface(); + enableOffload(); + + final OffloadController offload = makeOffloadController(); + offload.start(); + + final String ethernetIface = "eth1"; + final String mobileIface = "rmnet_data0"; + final long ethernetLimit = 12345; + final long mobileLimit = 12345678; + + final LinkProperties lp = new LinkProperties(); + lp.setInterfaceName(ethernetIface); + offload.setUpstreamLinkProperties(lp); + + ITetheringStatsProvider provider = mTetherStatsProviderCaptor.getValue(); + final InOrder inOrder = inOrder(mHardware); + when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(true); + when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(true); + + // Applying an interface quota to the current upstream immediately sends it to the hardware. + provider.setInterfaceQuota(ethernetIface, ethernetLimit); + waitForIdle(); + inOrder.verify(mHardware).setDataLimit(ethernetIface, ethernetLimit); + inOrder.verifyNoMoreInteractions(); + + // Applying an interface quota to another upstream does not take any immediate action. + provider.setInterfaceQuota(mobileIface, mobileLimit); + waitForIdle(); + inOrder.verify(mHardware, never()).setDataLimit(anyString(), anyLong()); + + // Switching to that upstream causes the quota to be applied if the parameters were applied + // correctly. + lp.setInterfaceName(mobileIface); + offload.setUpstreamLinkProperties(lp); + waitForIdle(); + inOrder.verify(mHardware).setDataLimit(mobileIface, mobileLimit); + + // Setting a limit of ITetheringStatsProvider.QUOTA_UNLIMITED causes the limit to be set + // to Long.MAX_VALUE. + provider.setInterfaceQuota(mobileIface, ITetheringStatsProvider.QUOTA_UNLIMITED); + waitForIdle(); + inOrder.verify(mHardware).setDataLimit(mobileIface, Long.MAX_VALUE); + + // If setting upstream parameters fails, then the data limit is not set. + when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(false); + lp.setInterfaceName(ethernetIface); + offload.setUpstreamLinkProperties(lp); + provider.setInterfaceQuota(mobileIface, mobileLimit); + waitForIdle(); + inOrder.verify(mHardware, never()).setDataLimit(anyString(), anyLong()); + + // If setting the data limit fails while changing upstreams, offload is stopped. + when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(true); + when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(false); + lp.setInterfaceName(mobileIface); + offload.setUpstreamLinkProperties(lp); + provider.setInterfaceQuota(mobileIface, mobileLimit); + waitForIdle(); + inOrder.verify(mHardware).getForwardedStats(ethernetIface); + inOrder.verify(mHardware).stopOffloadControl(); + } + + @Test + public void testDataLimitCallback() throws Exception { + setupFunctioningHardwareInterface(); + enableOffload(); + + final OffloadController offload = makeOffloadController(); + offload.start(); + + OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue(); + callback.onStoppedLimitReached(); + verify(mNMService, times(1)).tetherLimitReached(mTetherStatsProviderCaptor.getValue()); + } + + @Test + public void testAddRemoveDownstreams() throws Exception { + setupFunctioningHardwareInterface(); + enableOffload(); + + final OffloadController offload = makeOffloadController(); + offload.start(); + + final InOrder inOrder = inOrder(mHardware); + inOrder.verify(mHardware, times(1)).initOffloadConfig(); + inOrder.verify(mHardware, times(1)).initOffloadControl( + any(OffloadHardwareInterface.ControlCallback.class)); + inOrder.verifyNoMoreInteractions(); + + // Tethering makes several calls to setLocalPrefixes() before add/remove + // downstream calls are made. This is not tested here; only the behavior + // of notifyDownstreamLinkProperties() and removeDownstreamInterface() + // are tested. + + // [1] USB tethering is started. + final LinkProperties usbLinkProperties = new LinkProperties(); + usbLinkProperties.setInterfaceName(RNDIS0); + usbLinkProperties.addLinkAddress(new LinkAddress("192.168.42.1/24")); + usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(USB_PREFIX))); + offload.notifyDownstreamLinkProperties(usbLinkProperties); + inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, USB_PREFIX); + inOrder.verifyNoMoreInteractions(); + + // [2] Routes for IPv6 link-local prefixes should never be added. + usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(IPV6_LINKLOCAL))); + offload.notifyDownstreamLinkProperties(usbLinkProperties); + inOrder.verify(mHardware, never()).addDownstreamPrefix(eq(RNDIS0), anyString()); + inOrder.verifyNoMoreInteractions(); + + // [3] Add an IPv6 prefix for good measure. Only new offload-able + // prefixes should be passed to the HAL. + usbLinkProperties.addLinkAddress(new LinkAddress("2001:db8::1/64")); + usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(IPV6_DOC_PREFIX))); + offload.notifyDownstreamLinkProperties(usbLinkProperties); + inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, IPV6_DOC_PREFIX); + inOrder.verifyNoMoreInteractions(); + + // [4] Adding addresses doesn't affect notifyDownstreamLinkProperties(). + // The address is passed in by a separate setLocalPrefixes() invocation. + usbLinkProperties.addLinkAddress(new LinkAddress("2001:db8::2/64")); + offload.notifyDownstreamLinkProperties(usbLinkProperties); + inOrder.verify(mHardware, never()).addDownstreamPrefix(eq(RNDIS0), anyString()); + + // [5] Differences in local routes are converted into addDownstream() + // and removeDownstream() invocations accordingly. + usbLinkProperties.removeRoute(new RouteInfo(new IpPrefix(IPV6_DOC_PREFIX), null, RNDIS0)); + usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(IPV6_DISCARD_PREFIX))); + offload.notifyDownstreamLinkProperties(usbLinkProperties); + inOrder.verify(mHardware, times(1)).removeDownstreamPrefix(RNDIS0, IPV6_DOC_PREFIX); + inOrder.verify(mHardware, times(1)).addDownstreamPrefix(RNDIS0, IPV6_DISCARD_PREFIX); + inOrder.verifyNoMoreInteractions(); + + // [6] Removing a downstream interface which was never added causes no + // interactions with the HAL. + offload.removeDownstreamInterface(WLAN0); + inOrder.verifyNoMoreInteractions(); + + // [7] Removing an active downstream removes all remaining prefixes. + offload.removeDownstreamInterface(RNDIS0); + inOrder.verify(mHardware, times(1)).removeDownstreamPrefix(RNDIS0, USB_PREFIX); + inOrder.verify(mHardware, times(1)).removeDownstreamPrefix(RNDIS0, IPV6_DISCARD_PREFIX); + inOrder.verifyNoMoreInteractions(); + } + + private static void assertArrayListContains(ArrayList<String> list, String... elems) { + for (String element : elems) { + assertTrue(list.contains(element)); + } } } diff --git a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java index 2a32b73d56da..0c2ad38a11fe 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java @@ -17,26 +17,35 @@ package com.android.server.net; import static android.net.ConnectivityManager.TYPE_MOBILE; +import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; +import static android.net.NetworkStatsHistory.FIELD_ALL; import static android.net.NetworkTemplate.buildTemplateMobileAll; +import static android.os.Process.myUid; import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import android.content.res.Resources; import android.net.NetworkIdentity; import android.net.NetworkStats; +import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.os.Process; import android.os.UserHandle; +import android.telephony.SubscriptionPlan; import android.telephony.TelephonyManager; -import android.support.test.filters.SmallTest; import android.test.AndroidTestCase; import android.test.MoreAsserts; +import android.test.suitebuilder.annotation.SmallTest; +import android.text.format.DateUtils; import com.android.frameworks.tests.net.R; +import libcore.io.IoUtils; +import libcore.io.Streams; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; @@ -44,9 +53,9 @@ import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; - -import libcore.io.IoUtils; -import libcore.io.Streams; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.List; /** * Tests for {@link NetworkStatsCollection}. @@ -57,6 +66,10 @@ public class NetworkStatsCollectionTest extends AndroidTestCase { private static final String TEST_FILE = "test.bin"; private static final String TEST_IMSI = "310260000000000"; + private static final long TIME_A = 1326088800000L; // UTC: Monday 9th January 2012 06:00:00 AM + private static final long TIME_B = 1326110400000L; // UTC: Monday 9th January 2012 12:00:00 PM + private static final long TIME_C = 1326132000000L; // UTC: Monday 9th January 2012 06:00:00 PM + @Override public void setUp() throws Exception { super.setUp(); @@ -198,11 +211,11 @@ public class NetworkStatsCollectionTest extends AndroidTestCase { collection.getRelevantUids(NetworkStatsAccess.Level.DEVICE)); // Verify security check in getHistory. - assertNotNull(collection.getHistory(buildTemplateMobileAll(TEST_IMSI), myUid, SET_DEFAULT, - TAG_NONE, 0, NetworkStatsAccess.Level.DEFAULT)); + assertNotNull(collection.getHistory(buildTemplateMobileAll(TEST_IMSI), null, myUid, SET_DEFAULT, + TAG_NONE, 0, 0L, 0L, NetworkStatsAccess.Level.DEFAULT, myUid)); try { - collection.getHistory(buildTemplateMobileAll(TEST_IMSI), otherUidInSameUser, - SET_DEFAULT, TAG_NONE, 0, NetworkStatsAccess.Level.DEFAULT); + collection.getHistory(buildTemplateMobileAll(TEST_IMSI), null, otherUidInSameUser, + SET_DEFAULT, TAG_NONE, 0, 0L, 0L, NetworkStatsAccess.Level.DEFAULT, myUid); fail("Should have thrown SecurityException for accessing different UID"); } catch (SecurityException e) { // expected @@ -217,6 +230,213 @@ public class NetworkStatsCollectionTest extends AndroidTestCase { 0, NetworkStatsAccess.Level.DEVICE); } + public void testAugmentPlan() throws Exception { + final File testFile = new File(getContext().getFilesDir(), TEST_FILE); + stageFile(R.raw.netstats_v1, testFile); + + final NetworkStatsCollection emptyCollection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS); + final NetworkStatsCollection collection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS); + collection.readLegacyNetwork(testFile); + + // Test a bunch of plans that should result in no augmentation + final List<SubscriptionPlan> plans = new ArrayList<>(); + + // No plan + plans.add(null); + // No usage anchor + plans.add(SubscriptionPlan.Builder + .createRecurringMonthly(ZonedDateTime.parse("2011-01-14T00:00:00.00Z")).build()); + // Usage anchor far in past + plans.add(SubscriptionPlan.Builder + .createRecurringMonthly(ZonedDateTime.parse("2011-01-14T00:00:00.00Z")) + .setDataUsage(1000L, TIME_A - DateUtils.YEAR_IN_MILLIS).build()); + // Usage anchor far in future + plans.add(SubscriptionPlan.Builder + .createRecurringMonthly(ZonedDateTime.parse("2011-01-14T00:00:00.00Z")) + .setDataUsage(1000L, TIME_A + DateUtils.YEAR_IN_MILLIS).build()); + // Usage anchor near but outside cycle + plans.add(SubscriptionPlan.Builder + .createNonrecurring(ZonedDateTime.parse("2012-01-09T09:00:00.00Z"), + ZonedDateTime.parse("2012-01-09T15:00:00.00Z")) + .setDataUsage(1000L, TIME_C).build()); + + for (SubscriptionPlan plan : plans) { + int i; + NetworkStatsHistory history; + + // Empty collection should be untouched + history = getHistory(emptyCollection, plan, TIME_A, TIME_C); + assertEquals(0L, history.getTotalBytes()); + + // Normal collection should be untouched + history = getHistory(collection, plan, TIME_A, TIME_C); i = 0; + assertEntry(100647, 197, 23649, 185, history.getValues(i++, null)); + assertEntry(100647, 196, 23648, 185, history.getValues(i++, null)); + assertEntry(18323, 76, 15032, 76, history.getValues(i++, null)); + assertEntry(18322, 75, 15031, 75, history.getValues(i++, null)); + assertEntry(527798, 761, 78570, 652, history.getValues(i++, null)); + assertEntry(527797, 760, 78570, 651, history.getValues(i++, null)); + assertEntry(10747, 50, 16838, 55, history.getValues(i++, null)); + assertEntry(10747, 49, 16838, 54, history.getValues(i++, null)); + assertEntry(89191, 151, 18021, 140, history.getValues(i++, null)); + assertEntry(89190, 150, 18020, 139, history.getValues(i++, null)); + assertEntry(3821, 22, 4525, 26, history.getValues(i++, null)); + assertEntry(3820, 22, 4524, 26, history.getValues(i++, null)); + assertEntry(91686, 159, 18575, 146, history.getValues(i++, null)); + assertEntry(91685, 159, 18575, 146, history.getValues(i++, null)); + assertEntry(8289, 35, 6863, 38, history.getValues(i++, null)); + assertEntry(8289, 35, 6863, 38, history.getValues(i++, null)); + assertEntry(113914, 174, 18364, 157, history.getValues(i++, null)); + assertEntry(113913, 173, 18364, 157, history.getValues(i++, null)); + assertEntry(11378, 49, 9261, 49, history.getValues(i++, null)); + assertEntry(11377, 48, 9261, 49, history.getValues(i++, null)); + assertEntry(201765, 328, 41808, 291, history.getValues(i++, null)); + assertEntry(201765, 328, 41807, 290, history.getValues(i++, null)); + assertEntry(106106, 218, 39917, 201, history.getValues(i++, null)); + assertEntry(106105, 217, 39917, 201, history.getValues(i++, null)); + assertEquals(history.size(), i); + + // Slice from middle should be untouched + history = getHistory(collection, plan, TIME_B - HOUR_IN_MILLIS, + TIME_B + HOUR_IN_MILLIS); i = 0; + assertEntry(3821, 22, 4525, 26, history.getValues(i++, null)); + assertEntry(3820, 22, 4524, 26, history.getValues(i++, null)); + assertEntry(91686, 159, 18575, 146, history.getValues(i++, null)); + assertEntry(91685, 159, 18575, 146, history.getValues(i++, null)); + assertEquals(history.size(), i); + } + + // Lower anchor in the middle of plan + { + int i; + NetworkStatsHistory history; + + final SubscriptionPlan plan = SubscriptionPlan.Builder + .createNonrecurring(ZonedDateTime.parse("2012-01-09T09:00:00.00Z"), + ZonedDateTime.parse("2012-01-09T15:00:00.00Z")) + .setDataUsage(200000L, TIME_B).build(); + + // Empty collection should be augmented + history = getHistory(emptyCollection, plan, TIME_A, TIME_C); + assertEquals(200000L, history.getTotalBytes()); + + // Normal collection should be augmented + history = getHistory(collection, plan, TIME_A, TIME_C); i = 0; + assertEntry(100647, 197, 23649, 185, history.getValues(i++, null)); + assertEntry(100647, 196, 23648, 185, history.getValues(i++, null)); + assertEntry(18323, 76, 15032, 76, history.getValues(i++, null)); + assertEntry(18322, 75, 15031, 75, history.getValues(i++, null)); + assertEntry(527798, 761, 78570, 652, history.getValues(i++, null)); + assertEntry(527797, 760, 78570, 651, history.getValues(i++, null)); + // Cycle point; start data normalization + assertEntry(7507, 0, 11763, 0, history.getValues(i++, null)); + assertEntry(7507, 0, 11763, 0, history.getValues(i++, null)); + assertEntry(62309, 0, 12589, 0, history.getValues(i++, null)); + assertEntry(62309, 0, 12588, 0, history.getValues(i++, null)); + assertEntry(2669, 0, 3161, 0, history.getValues(i++, null)); + assertEntry(2668, 0, 3160, 0, history.getValues(i++, null)); + // Anchor point; end data normalization + assertEntry(91686, 159, 18575, 146, history.getValues(i++, null)); + assertEntry(91685, 159, 18575, 146, history.getValues(i++, null)); + assertEntry(8289, 35, 6863, 38, history.getValues(i++, null)); + assertEntry(8289, 35, 6863, 38, history.getValues(i++, null)); + assertEntry(113914, 174, 18364, 157, history.getValues(i++, null)); + assertEntry(113913, 173, 18364, 157, history.getValues(i++, null)); + // Cycle point + assertEntry(11378, 49, 9261, 49, history.getValues(i++, null)); + assertEntry(11377, 48, 9261, 49, history.getValues(i++, null)); + assertEntry(201765, 328, 41808, 291, history.getValues(i++, null)); + assertEntry(201765, 328, 41807, 290, history.getValues(i++, null)); + assertEntry(106106, 218, 39917, 201, history.getValues(i++, null)); + assertEntry(106105, 217, 39917, 201, history.getValues(i++, null)); + assertEquals(history.size(), i); + + // Slice from middle should be augmented + history = getHistory(collection, plan, TIME_B - HOUR_IN_MILLIS, + TIME_B + HOUR_IN_MILLIS); i = 0; + assertEntry(2669, 0, 3161, 0, history.getValues(i++, null)); + assertEntry(2668, 0, 3160, 0, history.getValues(i++, null)); + assertEntry(91686, 159, 18575, 146, history.getValues(i++, null)); + assertEntry(91685, 159, 18575, 146, history.getValues(i++, null)); + assertEquals(history.size(), i); + } + + // Higher anchor in the middle of plan + { + int i; + NetworkStatsHistory history; + + final SubscriptionPlan plan = SubscriptionPlan.Builder + .createNonrecurring(ZonedDateTime.parse("2012-01-09T09:00:00.00Z"), + ZonedDateTime.parse("2012-01-09T15:00:00.00Z")) + .setDataUsage(400000L, TIME_B + MINUTE_IN_MILLIS).build(); + + // Empty collection should be augmented + history = getHistory(emptyCollection, plan, TIME_A, TIME_C); + assertEquals(400000L, history.getTotalBytes()); + + // Normal collection should be augmented + history = getHistory(collection, plan, TIME_A, TIME_C); i = 0; + assertEntry(100647, 197, 23649, 185, history.getValues(i++, null)); + assertEntry(100647, 196, 23648, 185, history.getValues(i++, null)); + assertEntry(18323, 76, 15032, 76, history.getValues(i++, null)); + assertEntry(18322, 75, 15031, 75, history.getValues(i++, null)); + assertEntry(527798, 761, 78570, 652, history.getValues(i++, null)); + assertEntry(527797, 760, 78570, 651, history.getValues(i++, null)); + // Cycle point; start data normalization + assertEntry(15015, 0, 23526, 0, history.getValues(i++, null)); + assertEntry(15015, 0, 23526, 0, history.getValues(i++, null)); + assertEntry(124619, 0, 25179, 0, history.getValues(i++, null)); + assertEntry(124618, 0, 25177, 0, history.getValues(i++, null)); + assertEntry(5338, 0, 6322, 0, history.getValues(i++, null)); + assertEntry(5337, 0, 6320, 0, history.getValues(i++, null)); + // Anchor point; end data normalization + assertEntry(91686, 159, 18575, 146, history.getValues(i++, null)); + assertEntry(91685, 159, 18575, 146, history.getValues(i++, null)); + assertEntry(8289, 35, 6863, 38, history.getValues(i++, null)); + assertEntry(8289, 35, 6863, 38, history.getValues(i++, null)); + assertEntry(113914, 174, 18364, 157, history.getValues(i++, null)); + assertEntry(113913, 173, 18364, 157, history.getValues(i++, null)); + // Cycle point + assertEntry(11378, 49, 9261, 49, history.getValues(i++, null)); + assertEntry(11377, 48, 9261, 49, history.getValues(i++, null)); + assertEntry(201765, 328, 41808, 291, history.getValues(i++, null)); + assertEntry(201765, 328, 41807, 290, history.getValues(i++, null)); + assertEntry(106106, 218, 39917, 201, history.getValues(i++, null)); + assertEntry(106105, 217, 39917, 201, history.getValues(i++, null)); + + // Slice from middle should be augmented + history = getHistory(collection, plan, TIME_B - HOUR_IN_MILLIS, + TIME_B + HOUR_IN_MILLIS); i = 0; + assertEntry(5338, 0, 6322, 0, history.getValues(i++, null)); + assertEntry(5337, 0, 6320, 0, history.getValues(i++, null)); + assertEntry(91686, 159, 18575, 146, history.getValues(i++, null)); + assertEntry(91685, 159, 18575, 146, history.getValues(i++, null)); + assertEquals(history.size(), i); + } + } + + public void testRounding() throws Exception { + final NetworkStatsCollection coll = new NetworkStatsCollection(HOUR_IN_MILLIS); + + // Special values should remain unchanged + for (long time : new long[] { + Long.MIN_VALUE, Long.MAX_VALUE, SubscriptionPlan.TIME_UNKNOWN + }) { + assertEquals(time, coll.roundUp(time)); + assertEquals(time, coll.roundDown(time)); + } + + assertEquals(TIME_A, coll.roundUp(TIME_A)); + assertEquals(TIME_A, coll.roundDown(TIME_A)); + + assertEquals(TIME_A + HOUR_IN_MILLIS, coll.roundUp(TIME_A + 1)); + assertEquals(TIME_A, coll.roundDown(TIME_A + 1)); + + assertEquals(TIME_A, coll.roundUp(TIME_A - 1)); + assertEquals(TIME_A - HOUR_IN_MILLIS, coll.roundDown(TIME_A - 1)); + } + /** * Copy a {@link Resources#openRawResource(int)} into {@link File} for * testing purposes. @@ -235,28 +455,50 @@ public class NetworkStatsCollectionTest extends AndroidTestCase { } } + private static NetworkStatsHistory getHistory(NetworkStatsCollection collection, + SubscriptionPlan augmentPlan, long start, long end) { + return collection.getHistory(buildTemplateMobileAll(TEST_IMSI), augmentPlan, UID_ALL, + SET_ALL, TAG_NONE, FIELD_ALL, start, end, NetworkStatsAccess.Level.DEVICE, myUid()); + } + private static void assertSummaryTotal(NetworkStatsCollection collection, NetworkTemplate template, long rxBytes, long rxPackets, long txBytes, long txPackets, @NetworkStatsAccess.Level int accessLevel) { - final NetworkStats.Entry entry = collection.getSummary( - template, Long.MIN_VALUE, Long.MAX_VALUE, accessLevel) + final NetworkStats.Entry actual = collection.getSummary( + template, Long.MIN_VALUE, Long.MAX_VALUE, accessLevel, myUid()) .getTotal(null); - assertEntry(entry, rxBytes, rxPackets, txBytes, txPackets); + assertEntry(rxBytes, rxPackets, txBytes, txPackets, actual); } private static void assertSummaryTotalIncludingTags(NetworkStatsCollection collection, NetworkTemplate template, long rxBytes, long rxPackets, long txBytes, long txPackets) { - final NetworkStats.Entry entry = collection.getSummary( - template, Long.MIN_VALUE, Long.MAX_VALUE, NetworkStatsAccess.Level.DEVICE) + final NetworkStats.Entry actual = collection.getSummary( + template, Long.MIN_VALUE, Long.MAX_VALUE, NetworkStatsAccess.Level.DEVICE, myUid()) .getTotalIncludingTags(null); - assertEntry(entry, rxBytes, rxPackets, txBytes, txPackets); + assertEntry(rxBytes, rxPackets, txBytes, txPackets, actual); + } + + private static void assertEntry(long rxBytes, long rxPackets, long txBytes, long txPackets, + NetworkStats.Entry actual) { + assertEntry(new NetworkStats.Entry(rxBytes, rxPackets, txBytes, txPackets, 0L), actual); + } + + private static void assertEntry(long rxBytes, long rxPackets, long txBytes, long txPackets, + NetworkStatsHistory.Entry actual) { + assertEntry(new NetworkStats.Entry(rxBytes, rxPackets, txBytes, txPackets, 0L), actual); + } + + private static void assertEntry(NetworkStats.Entry expected, + NetworkStatsHistory.Entry actual) { + assertEntry(expected, new NetworkStats.Entry(actual.rxBytes, actual.rxPackets, + actual.txBytes, actual.txPackets, 0L)); } - private static void assertEntry( - NetworkStats.Entry entry, long rxBytes, long rxPackets, long txBytes, long txPackets) { - assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); - assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets); - assertEquals("unexpected txBytes", txBytes, entry.txBytes); - assertEquals("unexpected txPackets", txPackets, entry.txPackets); + private static void assertEntry(NetworkStats.Entry expected, + NetworkStats.Entry actual) { + assertEquals("unexpected rxBytes", expected.rxBytes, actual.rxBytes); + assertEquals("unexpected rxPackets", expected.rxPackets, actual.rxPackets); + assertEquals("unexpected txBytes", expected.txBytes, actual.txBytes); + assertEquals("unexpected txPackets", expected.txPackets, actual.txPackets); } } diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java index feb46d39b563..814a62663333 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java @@ -31,6 +31,8 @@ import static android.net.NetworkStats.ROAMING_YES; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_FOREGROUND; +import static android.net.NetworkStats.STATS_PER_IFACE; +import static android.net.NetworkStats.STATS_PER_UID; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkStatsHistory.FIELD_ALL; @@ -44,19 +46,17 @@ import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static android.text.format.DateUtils.WEEK_IN_MILLIS; -import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL; import static com.android.internal.util.TestUtils.waitForIdleHandler; +import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Mockito.when; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.app.AlarmManager; import android.app.usage.NetworkStatsManager; @@ -77,24 +77,21 @@ import android.net.NetworkTemplate; import android.os.ConditionVariable; import android.os.Handler; import android.os.HandlerThread; -import android.os.INetworkManagementService; import android.os.IBinder; +import android.os.INetworkManagementService; import android.os.Looper; -import android.os.Messenger; -import android.os.MessageQueue; -import android.os.MessageQueue.IdleHandler; import android.os.Message; +import android.os.Messenger; import android.os.PowerManager; import android.support.test.InstrumentationRegistry; -import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.telephony.TelephonyManager; -import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.Log; import android.util.TrustedTime; import com.android.internal.net.VpnInfo; import com.android.internal.util.test.BroadcastInterceptingContext; -import com.android.server.net.NetworkStatsService; import com.android.server.net.NetworkStatsService.NetworkStatsSettings; import com.android.server.net.NetworkStatsService.NetworkStatsSettings.Config; @@ -110,9 +107,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.File; -import java.util.ArrayList; import java.util.Objects; -import java.util.List; /** * Tests for {@link NetworkStatsService}. @@ -823,17 +818,24 @@ public class NetworkStatsServiceTest { incrementCurrentTime(HOUR_IN_MILLIS); expectCurrentTime(); expectDefaultSettings(); - expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .addIfaceValues(TEST_IFACE, 2048L, 16L, 512L, 4L)); + // Traffic seen by kernel counters (includes software tethering). + final NetworkStats ifaceStats = new NetworkStats(getElapsedRealtime(), 1) + .addIfaceValues(TEST_IFACE, 1536L, 12L, 384L, 3L); + // Hardware tethering traffic, not seen by kernel counters. + final NetworkStats tetherStatsHardware = new NetworkStats(getElapsedRealtime(), 1) + .addIfaceValues(TEST_IFACE, 512L, 4L, 128L, 1L); + + // Traffic for UID_RED. final NetworkStats uidStats = new NetworkStats(getElapsedRealtime(), 1) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L); - final String[] tetherIfacePairs = new String[] { TEST_IFACE, "wlan0" }; + // All tethering traffic, both hardware and software. final NetworkStats tetherStats = new NetworkStats(getElapsedRealtime(), 1) .addValues(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L, 0L); - expectNetworkStatsUidDetail(uidStats, tetherIfacePairs, tetherStats); + expectNetworkStatsSummary(ifaceStats, tetherStatsHardware); + expectNetworkStatsUidDetail(uidStats, tetherStats); forcePollAndWaitForIdle(); // verify service recorded history @@ -974,7 +976,7 @@ public class NetworkStatsServiceTest { // verify summary API final NetworkStats stats = mSession.getSummaryForNetwork(template, start, end); - assertValues(stats, IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_ALL, ROAMING_NO, + assertValues(stats, IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, rxBytes, rxPackets, txBytes, txPackets, operations); } @@ -1013,10 +1015,16 @@ public class NetworkStatsServiceTest { } private void expectNetworkStatsSummary(NetworkStats summary) throws Exception { + expectNetworkStatsSummary(summary, new NetworkStats(0L, 0)); + } + + private void expectNetworkStatsSummary(NetworkStats summary, NetworkStats tetherStats) + throws Exception { when(mConnManager.getAllVpnInfo()).thenReturn(new VpnInfo[0]); - expectNetworkStatsSummaryDev(summary); - expectNetworkStatsSummaryXt(summary); + expectNetworkStatsTethering(STATS_PER_IFACE, tetherStats); + expectNetworkStatsSummaryDev(summary.clone()); + expectNetworkStatsSummaryXt(summary.clone()); } private void expectNetworkStatsSummaryDev(NetworkStats summary) throws Exception { @@ -1027,17 +1035,21 @@ public class NetworkStatsServiceTest { when(mNetManager.getNetworkStatsSummaryXt()).thenReturn(summary); } + private void expectNetworkStatsTethering(int how, NetworkStats stats) + throws Exception { + when(mNetManager.getNetworkStatsTethering(how)).thenReturn(stats); + } + private void expectNetworkStatsUidDetail(NetworkStats detail) throws Exception { - expectNetworkStatsUidDetail(detail, new String[0], new NetworkStats(0L, 0)); + expectNetworkStatsUidDetail(detail, new NetworkStats(0L, 0)); } - private void expectNetworkStatsUidDetail( - NetworkStats detail, String[] tetherIfacePairs, NetworkStats tetherStats) + private void expectNetworkStatsUidDetail(NetworkStats detail, NetworkStats tetherStats) throws Exception { when(mNetManager.getNetworkStatsUidDetail(UID_ALL)).thenReturn(detail); // also include tethering details, since they are folded into UID - when(mNetManager.getNetworkStatsTethering()).thenReturn(tetherStats); + when(mNetManager.getNetworkStatsTethering(STATS_PER_UID)).thenReturn(tetherStats); } private void expectDefaultSettings() throws Exception { @@ -1088,28 +1100,25 @@ public class NetworkStatsServiceTest { int tag, int metered, int roaming, long rxBytes, long rxPackets, long txBytes, long txPackets, int operations) { final NetworkStats.Entry entry = new NetworkStats.Entry(); - List<Integer> sets = new ArrayList<>(); - if (set == SET_DEFAULT || set == SET_ALL) { - sets.add(SET_DEFAULT); - } - if (set == SET_FOREGROUND || set == SET_ALL) { - sets.add(SET_FOREGROUND); + final int[] sets; + if (set == SET_ALL) { + sets = new int[] { SET_ALL, SET_DEFAULT, SET_FOREGROUND }; + } else { + sets = new int[] { set }; } - List<Integer> roamings = new ArrayList<>(); - if (roaming == ROAMING_NO || roaming == ROAMING_ALL) { - roamings.add(ROAMING_NO); - } - if (roaming == ROAMING_YES || roaming == ROAMING_ALL) { - roamings.add(ROAMING_YES); + final int[] roamings; + if (roaming == ROAMING_ALL) { + roamings = new int[] { ROAMING_ALL, ROAMING_YES, ROAMING_NO }; + } else { + roamings = new int[] { roaming }; } - List<Integer> meterings = new ArrayList<>(); - if (metered == METERED_NO || metered == METERED_ALL) { - meterings.add(METERED_NO); - } - if (metered == METERED_YES || metered == METERED_ALL) { - meterings.add(METERED_YES); + final int[] meterings; + if (metered == METERED_ALL) { + meterings = new int[] { METERED_ALL, METERED_YES, METERED_NO }; + } else { + meterings = new int[] { metered }; } for (int s : sets) { diff --git a/tools/aapt/AaptXml.cpp b/tools/aapt/AaptXml.cpp index b04a55d91b9c..6801a4ec7325 100644 --- a/tools/aapt/AaptXml.cpp +++ b/tools/aapt/AaptXml.cpp @@ -99,24 +99,40 @@ String8 getResolvedAttribute(const ResTable& resTable, const ResXMLTree& tree, if (idx < 0) { return String8(); } + Res_value value; - if (tree.getAttributeValue(idx, &value) != NO_ERROR) { - if (value.dataType == Res_value::TYPE_STRING) { - size_t len; - const char16_t* str = tree.getAttributeStringValue(idx, &len); - return str ? String8(str, len) : String8(); + if (tree.getAttributeValue(idx, &value) == BAD_TYPE) { + if (outError != NULL) { + *outError = "attribute value is corrupt"; } - resTable.resolveReference(&value, 0); - if (value.dataType != Res_value::TYPE_STRING) { - if (outError != NULL) { - *outError = "attribute is not a string value"; - } - return String8(); + return String8(); + } + + // Check if the string is inline in the XML. + if (value.dataType == Res_value::TYPE_STRING) { + size_t len; + const char16_t* str = tree.getAttributeStringValue(idx, &len); + return str ? String8(str, len) : String8(); + } + + // Resolve the reference if there is one. + ssize_t block = resTable.resolveReference(&value, 0); + if (block < 0) { + if (outError != NULL) { + *outError = "attribute value reference does not exist"; + } + return String8(); + } + + if (value.dataType != Res_value::TYPE_STRING) { + if (outError != NULL) { + *outError = "attribute is not a string value"; } + return String8(); } + size_t len; - const Res_value* value2 = &value; - const char16_t* str = resTable.valueToString(value2, 0, NULL, &len); + const char16_t* str = resTable.valueToString(&value, static_cast<size_t>(block), NULL, &len); return str ? String8(str, len) : String8(); } diff --git a/tools/aapt/SdkConstants.h b/tools/aapt/SdkConstants.h index 0dbf4ee8153e..b982d0d2ea63 100644 --- a/tools/aapt/SdkConstants.h +++ b/tools/aapt/SdkConstants.h @@ -42,7 +42,8 @@ enum { SDK_NOUGAT = 24, SDK_NOUGAT_MR1 = 25, SDK_O = 26, - SDK_O_MR1 = 10000, // STOPSHIP Replace with the real version. + SDK_O_MR1 = 27, + SDK_P = 10000, // STOPSHIP Replace with the real version. }; #endif // H_AAPT_SDK_CONSTANTS diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp index 53794e641b0f..24aa6ebbcbc2 100644 --- a/tools/aapt2/Android.bp +++ b/tools/aapt2/Android.bp @@ -106,6 +106,7 @@ cc_library_host_static { "link/XmlCompatVersioner.cpp", "link/XmlNamespaceRemover.cpp", "link/XmlReferenceLinker.cpp", + "optimize/MultiApkGenerator.cpp", "optimize/ResourceDeduper.cpp", "optimize/VersionCollapser.cpp", "process/SymbolTable.cpp", @@ -142,7 +143,8 @@ cc_library_host_static { "xml/XmlDom.cpp", "xml/XmlPullParser.cpp", "xml/XmlUtil.cpp", - "Format.proto", + "Resources.proto", + "ResourcesInternal.proto", ], proto: { export_proto_headers: true, diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp index b872ebbeb159..49ed7780f950 100644 --- a/tools/aapt2/Debug.cpp +++ b/tools/aapt2/Debug.cpp @@ -33,6 +33,8 @@ namespace aapt { +namespace { + class PrintVisitor : public ValueVisitor { public: using ValueVisitor::Visit; @@ -88,9 +90,13 @@ class PrintVisitor : public ValueVisitor { } } - void Visit(Array* array) override { array->Print(&std::cout); } + void Visit(Array* array) override { + array->Print(&std::cout); + } - void Visit(Plural* plural) override { plural->Print(&std::cout); } + void Visit(Plural* plural) override { + plural->Print(&std::cout); + } void Visit(Styleable* styleable) override { std::cout << "(styleable)"; @@ -110,11 +116,14 @@ class PrintVisitor : public ValueVisitor { } } - void VisitItem(Item* item) override { item->Print(&std::cout); } + void VisitItem(Item* item) override { + item->Print(&std::cout); + } }; -void Debug::PrintTable(ResourceTable* table, - const DebugPrintTableOptions& options) { +} // namespace + +void Debug::PrintTable(ResourceTable* table, const DebugPrintTableOptions& options) { PrintVisitor visitor; for (auto& package : table->packages) { @@ -148,10 +157,9 @@ void Debug::PrintTable(ResourceTable* table, } for (const ResourceEntry* entry : sorted_entries) { - ResourceId id(package->id ? package->id.value() : uint8_t(0), - type->id ? type->id.value() : uint8_t(0), - entry->id ? entry->id.value() : uint16_t(0)); - ResourceName name(package->name, type->type, entry->name); + const ResourceId id(package->id.value_or_default(0), type->id.value_or_default(0), + entry->id.value_or_default(0)); + const ResourceName name(package->name, type->type, entry->name); std::cout << " spec resource " << id << " " << name; switch (entry->symbol_status.state) { @@ -180,16 +188,14 @@ void Debug::PrintTable(ResourceTable* table, } } -static size_t GetNodeIndex(const std::vector<ResourceName>& names, - const ResourceName& name) { +static size_t GetNodeIndex(const std::vector<ResourceName>& names, const ResourceName& name) { auto iter = std::lower_bound(names.begin(), names.end(), name); CHECK(iter != names.end()); CHECK(*iter == name); return std::distance(names.begin(), iter); } -void Debug::PrintStyleGraph(ResourceTable* table, - const ResourceName& target_style) { +void Debug::PrintStyleGraph(ResourceTable* table, const ResourceName& target_style) { std::map<ResourceName, std::set<ResourceName>> graph; std::queue<ResourceName> styles_to_visit; @@ -223,8 +229,7 @@ void Debug::PrintStyleGraph(ResourceTable* table, std::cout << "digraph styles {\n"; for (const auto& name : names) { - std::cout << " node_" << GetNodeIndex(names, name) << " [label=\"" << name - << "\"];\n"; + std::cout << " node_" << GetNodeIndex(names, name) << " [label=\"" << name << "\"];\n"; } for (const auto& entry : graph) { @@ -243,8 +248,7 @@ void Debug::PrintStyleGraph(ResourceTable* table, void Debug::DumpHex(const void* data, size_t len) { const uint8_t* d = (const uint8_t*)data; for (size_t i = 0; i < len; i++) { - std::cerr << std::hex << std::setfill('0') << std::setw(2) << (uint32_t)d[i] - << " "; + std::cerr << std::hex << std::setfill('0') << std::setw(2) << (uint32_t)d[i] << " "; if (i % 8 == 7) { std::cerr << "\n"; } @@ -262,8 +266,15 @@ class XmlPrinter : public xml::Visitor { using xml::Visitor::Visit; void Visit(xml::Element* el) override { - std::cerr << prefix_; - std::cerr << "E: "; + const size_t previous_size = prefix_.size(); + + for (const xml::NamespaceDecl& decl : el->namespace_decls) { + std::cerr << prefix_ << "N: " << decl.prefix << "=" << decl.uri + << " (line=" << decl.line_number << ")\n"; + prefix_ += " "; + } + + std::cerr << prefix_ << "E: "; if (!el->namespace_uri.empty()) { std::cerr << el->namespace_uri << ":"; } @@ -283,26 +294,13 @@ class XmlPrinter : public xml::Visitor { std::cerr << "=" << attr.value << "\n"; } - const size_t previous_size = prefix_.size(); prefix_ += " "; xml::Visitor::Visit(el); prefix_.resize(previous_size); } - void Visit(xml::Namespace* ns) override { - std::cerr << prefix_; - std::cerr << "N: " << ns->namespace_prefix << "=" << ns->namespace_uri - << " (line=" << ns->line_number << ")\n"; - - const size_t previous_size = prefix_.size(); - prefix_ += " "; - xml::Visitor::Visit(ns); - prefix_.resize(previous_size); - } - void Visit(xml::Text* text) override { - std::cerr << prefix_; - std::cerr << "T: '" << text->text << "'\n"; + std::cerr << prefix_ << "T: '" << text->text << "'\n"; } private: diff --git a/tools/aapt2/LoadedApk.cpp b/tools/aapt2/LoadedApk.cpp index abc0e4c1b89d..b80780e33dfa 100644 --- a/tools/aapt2/LoadedApk.cpp +++ b/tools/aapt2/LoadedApk.cpp @@ -58,14 +58,15 @@ std::unique_ptr<LoadedApk> LoadedApk::LoadApkFromPath(IAaptContext* context, bool LoadedApk::WriteToArchive(IAaptContext* context, const TableFlattenerOptions& options, IArchiveWriter* writer) { FilterChain empty; - return WriteToArchive(context, options, &empty, writer); + return WriteToArchive(context, table_.get(), options, &empty, writer); } -bool LoadedApk::WriteToArchive(IAaptContext* context, const TableFlattenerOptions& options, - FilterChain* filters, IArchiveWriter* writer) { +bool LoadedApk::WriteToArchive(IAaptContext* context, ResourceTable* split_table, + const TableFlattenerOptions& options, FilterChain* filters, + IArchiveWriter* writer) { std::set<std::string> referenced_resources; // List the files being referenced in the resource table. - for (auto& pkg : table_->packages) { + for (auto& pkg : split_table->packages) { for (auto& type : pkg->types) { for (auto& entry : type->entries) { for (auto& config_value : entry->values) { @@ -108,7 +109,7 @@ bool LoadedApk::WriteToArchive(IAaptContext* context, const TableFlattenerOption // TODO(adamlesinski): How to determine if there were sparse entries (and if to encode // with sparse entries) b/35389232. TableFlattener flattener(options, &buffer); - if (!flattener.Consume(context, table_.get())) { + if (!flattener.Consume(context, split_table)) { return false; } diff --git a/tools/aapt2/LoadedApk.h b/tools/aapt2/LoadedApk.h index 8aa9674aa2ed..dacd0c2130a9 100644 --- a/tools/aapt2/LoadedApk.h +++ b/tools/aapt2/LoadedApk.h @@ -47,16 +47,17 @@ class LoadedApk { * Writes the APK on disk at the given path, while also removing the resource * files that are not referenced in the resource table. */ - bool WriteToArchive(IAaptContext* context, const TableFlattenerOptions& options, - IArchiveWriter* writer); + virtual bool WriteToArchive(IAaptContext* context, const TableFlattenerOptions& options, + IArchiveWriter* writer); /** * Writes the APK on disk at the given path, while also removing the resource * files that are not referenced in the resource table. The provided filter * chain is applied to each entry in the APK file. */ - bool WriteToArchive(IAaptContext* context, const TableFlattenerOptions& options, - FilterChain* filters, IArchiveWriter* writer); + virtual bool WriteToArchive(IAaptContext* context, ResourceTable* split_table, + const TableFlattenerOptions& options, FilterChain* filters, + IArchiveWriter* writer); static std::unique_ptr<LoadedApk> LoadApkFromPath(IAaptContext* context, const android::StringPiece& path); diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp index 89cce5ffca53..86f4c42c72a7 100644 --- a/tools/aapt2/Main.cpp +++ b/tools/aapt2/Main.cpp @@ -24,10 +24,16 @@ #include <iostream> #include <vector> +#include "android-base/stringprintf.h" #include "android-base/utf8.h" #include "androidfw/StringPiece.h" #include "Diagnostics.h" +#include "util/Files.h" +#include "util/Util.h" + +using ::android::StringPiece; +using ::android::base::StringPrintf; namespace aapt { @@ -37,53 +43,111 @@ static const char* sMajorVersion = "2"; // Update minor version whenever a feature or flag is added. static const char* sMinorVersion = "18"; -int PrintVersion() { - std::cerr << "Android Asset Packaging Tool (aapt) " << sMajorVersion << "." - << sMinorVersion << std::endl; - return 0; +static void PrintVersion() { + std::cerr << StringPrintf("Android Asset Packaging Tool (aapt) %s:%s", sMajorVersion, + sMinorVersion) + << std::endl; } -extern int Compile(const std::vector<android::StringPiece>& args, IDiagnostics* diagnostics); -extern int Link(const std::vector<android::StringPiece>& args, IDiagnostics* diagnostics); -extern int Dump(const std::vector<android::StringPiece>& args); -extern int Diff(const std::vector<android::StringPiece>& args); -extern int Optimize(const std::vector<android::StringPiece>& args); +static void PrintUsage() { + std::cerr << "\nusage: aapt2 [compile|link|dump|diff|optimize|version] ..." << std::endl; +} -} // namespace aapt +extern int Compile(const std::vector<StringPiece>& args, IDiagnostics* diagnostics); +extern int Link(const std::vector<StringPiece>& args, IDiagnostics* diagnostics); +extern int Dump(const std::vector<StringPiece>& args); +extern int Diff(const std::vector<StringPiece>& args); +extern int Optimize(const std::vector<StringPiece>& args); + +static int ExecuteCommand(const StringPiece& command, const std::vector<StringPiece>& args, + IDiagnostics* diagnostics) { + if (command == "compile" || command == "c") { + return Compile(args, diagnostics); + } else if (command == "link" || command == "l") { + return Link(args, diagnostics); + } else if (command == "dump" || command == "d") { + return Dump(args); + } else if (command == "diff") { + return Diff(args); + } else if (command == "optimize") { + return Optimize(args); + } else if (command == "version") { + PrintVersion(); + return 0; + } + diagnostics->Error(DiagMessage() << "unknown command '" << command << "'"); + return -1; +} -int MainImpl(int argc, char** argv) { - if (argc >= 2) { - argv += 1; - argc -= 1; +static void RunDaemon(IDiagnostics* diagnostics) { + std::cout << "Ready" << std::endl; + + // Run in daemon mode. The first line of input is the command. This can be 'quit' which ends + // the daemon mode. Each subsequent line is a single parameter to the command. The end of a + // invocation is signaled by providing an empty line. At any point, an EOF signal or the + // command 'quit' will end the daemon mode. + while (true) { + std::vector<std::string> raw_args; + for (std::string line; std::getline(std::cin, line) && !line.empty();) { + raw_args.push_back(line); + } + + if (!std::cin) { + break; + } - std::vector<android::StringPiece> args; - for (int i = 1; i < argc; i++) { - args.push_back(argv[i]); + // An empty command does nothing. + if (raw_args.empty()) { + continue; } - android::StringPiece command(argv[0]); - if (command == "compile" || command == "c") { - aapt::StdErrDiagnostics diagnostics; - return aapt::Compile(args, &diagnostics); - } else if (command == "link" || command == "l") { - aapt::StdErrDiagnostics diagnostics; - return aapt::Link(args, &diagnostics); - } else if (command == "dump" || command == "d") { - return aapt::Dump(args); - } else if (command == "diff") { - return aapt::Diff(args); - } else if (command == "optimize") { - return aapt::Optimize(args); - } else if (command == "version") { - return aapt::PrintVersion(); + if (raw_args[0] == "quit") { + break; } - std::cerr << "unknown command '" << command << "'\n"; - } else { + + std::vector<StringPiece> args; + args.insert(args.end(), ++raw_args.begin(), raw_args.end()); + int ret = ExecuteCommand(raw_args[0], args, diagnostics); + if (ret != 0) { + std::cerr << "Error" << std::endl; + } + std::cerr << "Done" << std::endl; + } + std::cout << "Exiting daemon" << std::endl; +} + +} // namespace aapt + +int MainImpl(int argc, char** argv) { + if (argc < 2) { std::cerr << "no command specified\n"; + aapt::PrintUsage(); + return -1; } - std::cerr << "\nusage: aapt2 [compile|link|dump|diff|optimize|version] ..." << std::endl; - return 1; + argv += 1; + argc -= 1; + + aapt::StdErrDiagnostics diagnostics; + + // Collect the arguments starting after the program name and command name. + std::vector<StringPiece> args; + for (int i = 1; i < argc; i++) { + args.push_back(argv[i]); + } + + const StringPiece command(argv[0]); + if (command != "daemon" && command != "m") { + // Single execution. + const int result = aapt::ExecuteCommand(command, args, &diagnostics); + if (result < 0) { + aapt::PrintUsage(); + } + return result; + } + + aapt::RunDaemon(&diagnostics); + return 0; } int main(int argc, char** argv) { diff --git a/tools/aapt2/NameMangler.h b/tools/aapt2/NameMangler.h index 1305a4cf0710..f1aad29a5c58 100644 --- a/tools/aapt2/NameMangler.h +++ b/tools/aapt2/NameMangler.h @@ -69,8 +69,7 @@ class NameMangler { * The mangled name should contain symbols that are illegal to define in XML, * so that there will never be name mangling collisions. */ - static std::string MangleEntry(const std::string& package, - const std::string& name) { + static std::string MangleEntry(const std::string& package, const std::string& name) { return package + "$" + name; } @@ -86,8 +85,8 @@ class NameMangler { } out_package->assign(out_name->data(), pivot); - out_name->assign(out_name->data() + pivot + 1, - out_name->size() - (pivot + 1)); + std::string new_name = out_name->substr(pivot + 1); + *out_name = std::move(new_name); return true; } diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp index a5783a532e23..47549f01f8ca 100644 --- a/tools/aapt2/ResourceParser.cpp +++ b/tools/aapt2/ResourceParser.cpp @@ -605,7 +605,7 @@ std::unique_ptr<Item> ResourceParser::ParseXml(xml::XmlPullParser* parser, if (processed_item) { // Fix up the reference. if (Reference* ref = ValueCast<Reference>(processed_item.get())) { - TransformReferenceFromNamespace(parser, "", ref); + ResolvePackage(parser, ref); } return processed_item; } @@ -1074,15 +1074,13 @@ bool ResourceParser::ParseStyleItem(xml::XmlPullParser* parser, Style* style) { return false; } - Maybe<Reference> maybe_key = - ResourceUtils::ParseXmlAttributeName(maybe_name.value()); + Maybe<Reference> maybe_key = ResourceUtils::ParseXmlAttributeName(maybe_name.value()); if (!maybe_key) { - diag_->Error(DiagMessage(source) << "invalid attribute name '" - << maybe_name.value() << "'"); + diag_->Error(DiagMessage(source) << "invalid attribute name '" << maybe_name.value() << "'"); return false; } - TransformReferenceFromNamespace(parser, "", &maybe_key.value()); + ResolvePackage(parser, &maybe_key.value()); maybe_key.value().SetSource(source); std::unique_ptr<Item> value = ParseXml(parser, 0, kAllowRawString); @@ -1091,8 +1089,7 @@ bool ResourceParser::ParseStyleItem(xml::XmlPullParser* parser, Style* style) { return false; } - style->entries.push_back( - Style::Entry{std::move(maybe_key.value()), std::move(value)}); + style->entries.push_back(Style::Entry{std::move(maybe_key.value()), std::move(value)}); return true; } @@ -1104,21 +1101,18 @@ bool ResourceParser::ParseStyle(const ResourceType type, xml::XmlPullParser* par Maybe<StringPiece> maybe_parent = xml::FindAttribute(parser, "parent"); if (maybe_parent) { - // If the parent is empty, we don't have a parent, but we also don't infer - // either. + // If the parent is empty, we don't have a parent, but we also don't infer either. if (!maybe_parent.value().empty()) { std::string err_str; - style->parent = ResourceUtils::ParseStyleParentReference( - maybe_parent.value(), &err_str); + style->parent = ResourceUtils::ParseStyleParentReference(maybe_parent.value(), &err_str); if (!style->parent) { diag_->Error(DiagMessage(out_resource->source) << err_str); return false; } - // Transform the namespace prefix to the actual package name, and mark the - // reference as + // Transform the namespace prefix to the actual package name, and mark the reference as // private if appropriate. - TransformReferenceFromNamespace(parser, "", &style->parent.value()); + ResolvePackage(parser, &style->parent.value()); } } else { @@ -1127,8 +1121,7 @@ bool ResourceParser::ParseStyle(const ResourceType type, xml::XmlPullParser* par size_t pos = style_name.find_last_of(u'.'); if (pos != std::string::npos) { style->parent_inferred = true; - style->parent = Reference( - ResourceName({}, ResourceType::kStyle, style_name.substr(0, pos))); + style->parent = Reference(ResourceName({}, ResourceType::kStyle, style_name.substr(0, pos))); } } @@ -1219,7 +1212,7 @@ bool ResourceParser::ParseArrayImpl(xml::XmlPullParser* parser, continue; } item->SetSource(item_source); - array->items.emplace_back(std::move(item)); + array->elements.emplace_back(std::move(item)); } else if (!ShouldIgnoreElement(element_namespace, element_name)) { diag_->Error(DiagMessage(source_.WithLine(parser->line_number())) @@ -1373,7 +1366,7 @@ bool ResourceParser::ParseDeclareStyleable(xml::XmlPullParser* parser, } Reference& child_ref = maybe_ref.value(); - xml::TransformReferenceFromNamespace(parser, "", &child_ref); + xml::ResolvePackage(parser, &child_ref); // Create the ParsedResource that will add the attribute to the table. ParsedResource child_resource; diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp index 971b45eff35f..144ebd22e105 100644 --- a/tools/aapt2/ResourceParser_test.cpp +++ b/tools/aapt2/ResourceParser_test.cpp @@ -540,11 +540,11 @@ TEST_F(ResourceParserTest, ParseArray) { Array* array = test::GetValue<Array>(&table_, "array/foo"); ASSERT_THAT(array, NotNull()); - ASSERT_THAT(array->items, SizeIs(3)); + ASSERT_THAT(array->elements, SizeIs(3)); - EXPECT_THAT(ValueCast<Reference>(array->items[0].get()), NotNull()); - EXPECT_THAT(ValueCast<String>(array->items[1].get()), NotNull()); - EXPECT_THAT(ValueCast<BinaryPrimitive>(array->items[2].get()), NotNull()); + EXPECT_THAT(ValueCast<Reference>(array->elements[0].get()), NotNull()); + EXPECT_THAT(ValueCast<String>(array->elements[1].get()), NotNull()); + EXPECT_THAT(ValueCast<BinaryPrimitive>(array->elements[2].get()), NotNull()); } TEST_F(ResourceParserTest, ParseStringArray) { @@ -565,9 +565,9 @@ TEST_F(ResourceParserTest, ParseArrayWithFormat) { Array* array = test::GetValue<Array>(&table_, "array/foo"); ASSERT_THAT(array, NotNull()); - ASSERT_THAT(array->items, SizeIs(1)); + ASSERT_THAT(array->elements, SizeIs(1)); - String* str = ValueCast<String>(array->items[0].get()); + String* str = ValueCast<String>(array->elements[0].get()); ASSERT_THAT(str, NotNull()); EXPECT_THAT(*str, StrValueEq("100")); } diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp index ab59560d33a3..0304e21698df 100644 --- a/tools/aapt2/ResourceTable.cpp +++ b/tools/aapt2/ResourceTable.cpp @@ -546,4 +546,34 @@ Maybe<ResourceTable::SearchResult> ResourceTable::FindResource(const ResourceNam return SearchResult{package, type, entry}; } +std::unique_ptr<ResourceTable> ResourceTable::Clone() const { + std::unique_ptr<ResourceTable> new_table = util::make_unique<ResourceTable>(); + for (const auto& pkg : packages) { + ResourceTablePackage* new_pkg = new_table->CreatePackage(pkg->name, pkg->id); + for (const auto& type : pkg->types) { + ResourceTableType* new_type = new_pkg->FindOrCreateType(type->type); + if (!new_type->id) { + new_type->id = type->id; + new_type->symbol_status = type->symbol_status; + } + + for (const auto& entry : type->entries) { + ResourceEntry* new_entry = new_type->FindOrCreateEntry(entry->name); + if (!new_entry->id) { + new_entry->id = entry->id; + new_entry->symbol_status = entry->symbol_status; + } + + for (const auto& config_value : entry->values) { + ResourceConfigValue* new_value = + new_entry->FindOrCreateValue(config_value->config, config_value->product); + Value* value = config_value->value->Clone(&new_table->string_pool); + new_value->value = std::unique_ptr<Value>(value); + } + } + } + } + return new_table; +} + } // namespace aapt diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h index 4295d0674774..d5db67e77f51 100644 --- a/tools/aapt2/ResourceTable.h +++ b/tools/aapt2/ResourceTable.h @@ -251,6 +251,8 @@ class ResourceTable { ResourceTablePackage* CreatePackage(const android::StringPiece& name, Maybe<uint8_t> id = {}); + std::unique_ptr<ResourceTable> Clone() const; + /** * The string pool used by this resource table. Values that reference strings * must use diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp index eb59175edf3b..1cba19462839 100644 --- a/tools/aapt2/ResourceValues.cpp +++ b/tools/aapt2/ResourceValues.cpp @@ -805,13 +805,12 @@ bool Array::Equals(const Value* value) const { return false; } - if (items.size() != other->items.size()) { + if (elements.size() != other->elements.size()) { return false; } - return std::equal(items.begin(), items.end(), other->items.begin(), - [](const std::unique_ptr<Item>& a, - const std::unique_ptr<Item>& b) -> bool { + return std::equal(elements.begin(), elements.end(), other->elements.begin(), + [](const std::unique_ptr<Item>& a, const std::unique_ptr<Item>& b) -> bool { return a->Equals(b.get()); }); } @@ -820,14 +819,14 @@ Array* Array::Clone(StringPool* new_pool) const { Array* array = new Array(); array->comment_ = comment_; array->source_ = source_; - for (auto& item : items) { - array->items.emplace_back(std::unique_ptr<Item>(item->Clone(new_pool))); + for (auto& item : elements) { + array->elements.emplace_back(std::unique_ptr<Item>(item->Clone(new_pool))); } return array; } void Array::Print(std::ostream* out) const { - *out << "(array) [" << util::Joiner(items, ", ") << "]"; + *out << "(array) [" << util::Joiner(elements, ", ") << "]"; } bool Plural::Equals(const Value* value) const { diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h index 7e7547fc1b94..275864bbcd3e 100644 --- a/tools/aapt2/ResourceValues.h +++ b/tools/aapt2/ResourceValues.h @@ -292,7 +292,7 @@ struct Style : public BaseValue<Style> { }; struct Array : public BaseValue<Array> { - std::vector<std::unique_ptr<Item>> items; + std::vector<std::unique_ptr<Item>> elements; bool Equals(const Value* value) const override; Array* Clone(StringPool* new_pool) const override; diff --git a/tools/aapt2/ResourceValues_test.cpp b/tools/aapt2/ResourceValues_test.cpp index 06c3404561de..10f9b55ede08 100644 --- a/tools/aapt2/ResourceValues_test.cpp +++ b/tools/aapt2/ResourceValues_test.cpp @@ -54,19 +54,19 @@ TEST(ResourceValuesTest, ArrayEquals) { StringPool pool; Array a; - a.items.push_back(util::make_unique<String>(pool.MakeRef("one"))); - a.items.push_back(util::make_unique<String>(pool.MakeRef("two"))); + a.elements.push_back(util::make_unique<String>(pool.MakeRef("one"))); + a.elements.push_back(util::make_unique<String>(pool.MakeRef("two"))); Array b; - b.items.push_back(util::make_unique<String>(pool.MakeRef("une"))); - b.items.push_back(util::make_unique<String>(pool.MakeRef("deux"))); + b.elements.push_back(util::make_unique<String>(pool.MakeRef("une"))); + b.elements.push_back(util::make_unique<String>(pool.MakeRef("deux"))); Array c; - c.items.push_back(util::make_unique<String>(pool.MakeRef("uno"))); + c.elements.push_back(util::make_unique<String>(pool.MakeRef("uno"))); Array d; - d.items.push_back(util::make_unique<String>(pool.MakeRef("one"))); - d.items.push_back(util::make_unique<String>(pool.MakeRef("two"))); + d.elements.push_back(util::make_unique<String>(pool.MakeRef("one"))); + d.elements.push_back(util::make_unique<String>(pool.MakeRef("two"))); EXPECT_FALSE(a.Equals(&b)); EXPECT_FALSE(a.Equals(&c)); @@ -78,8 +78,8 @@ TEST(ResourceValuesTest, ArrayClone) { StringPool pool; Array a; - a.items.push_back(util::make_unique<String>(pool.MakeRef("one"))); - a.items.push_back(util::make_unique<String>(pool.MakeRef("two"))); + a.elements.push_back(util::make_unique<String>(pool.MakeRef("one"))); + a.elements.push_back(util::make_unique<String>(pool.MakeRef("two"))); std::unique_ptr<Array> b(a.Clone(&pool)); EXPECT_TRUE(a.Equals(b.get())); diff --git a/tools/aapt2/Format.proto b/tools/aapt2/Resources.proto index 6be7f02dc7d2..71f33b0853ad 100644 --- a/tools/aapt2/Format.proto +++ b/tools/aapt2/Resources.proto @@ -14,14 +14,18 @@ * limitations under the License. */ +// Keep proto2 syntax because we require the distinction between fields that +// are set and unset. syntax = "proto2"; +option java_package = "com.android.aapt"; option optimize_for = LITE_RUNTIME; package aapt.pb; // A configuration description that wraps the binary form of the C++ class // aapt::ConfigDescription, with an added product definition. +// TODO(adamlesinski): Flesh this out to be represented in proto. message ConfigDescription { optional bytes data = 1; optional string product = 2; @@ -32,37 +36,17 @@ message StringPool { optional bytes data = 1; } +// The position of a declared entity within a file. +message SourcePosition { + optional uint32 line_number = 1; + optional uint32 column_number = 2; +} + // Developer friendly source file information for an entity in the resource table. message Source { // The index of the string path within the source string pool of a ResourceTable. optional uint32 path_idx = 1; - - optional uint32 line_no = 2; - optional uint32 col_no = 3; -} - -// The top level message representing an external resource file (layout XML, PNG, etc). -message CompiledFile { - message Symbol { - // The name of the symbol (in the form package:type/name). - optional string resource_name = 1; - - // Line number in the file at which this symbol is defined. For debug use. - optional uint32 line_no = 2; - } - - // The name of the resource (in the form package:type/name). - optional string resource_name = 1; - - // The configuration for which the resource is defined. - optional ConfigDescription config = 2; - - // The filesystem path to where the source file originated. - // Mainly used to display helpful error messages. - optional string source_path = 3; - - // Any symbols this file auto-generates/exports (eg. @+id/foo in an XML file). - repeated Symbol exported_symbols = 4; + optional SourcePosition position = 2; } // Top level message representing a resource table. @@ -72,7 +56,7 @@ message ResourceTable { optional StringPool source_pool = 1; // Resource definitions corresponding to an Android package. - repeated Package packages = 2; + repeated Package package = 2; } // Defines resources for an Android package. @@ -89,7 +73,7 @@ message Package { optional string package_name = 2; // The series of types defined by the package. - repeated Type types = 3; + repeated Type type = 3; } // A set of resources grouped under a common type. Such types include string, layout, xml, dimen, @@ -103,7 +87,7 @@ message Type { optional string name = 2; // The entries defined for this type. - repeated Entry entries = 3; + repeated Entry entry = 3; } // The status of a symbol/entry. This contains information like visibility (public/private), @@ -115,17 +99,17 @@ message SymbolStatus { // The distinction is important when two separate R.java files are generated: a public and // private one. An unknown visibility, in this case, would cause the resource to be omitted // from either R.java. - Unknown = 0; + UNKNOWN = 0; // A resource was explicitly marked as private. This means the resource can not be accessed // outside of its package unless the @*package:type/entry notation is used (the asterisk being // the private accessor). If two R.java files are generated (private + public), the resource // will only be emitted to the private R.java file. - Private = 1; + PRIVATE = 1; // A resource was explicitly marked as public. This means the resource can be accessed // from any package, and is emitted into all R.java files, public and private. - Public = 2; + PUBLIC = 2; } optional Visibility visibility = 1; @@ -159,7 +143,7 @@ message Entry { // The set of values defined for this entry, each corresponding to a different // configuration/variant. - repeated ConfigValue config_values = 4; + repeated ConfigValue config_value = 4; } // A Configuration/Value pair. @@ -214,10 +198,10 @@ message CompoundValue { message Reference { enum Type { // A plain reference (@package:type/entry). - Ref = 0; + REFERENCE = 0; // A reference to a theme attribute (?package:type/entry). - Attr = 1; + ATTRIBUTE = 1; } optional Type type = 1; @@ -301,21 +285,38 @@ message Attribute { optional uint32 value = 4; } - // A bitmask of types that this XML attribute accepts. Corresponds to the flags in the C struct - // android::ResTable_map. + // Bitmask of formats allowed for an attribute. + enum FormatFlags { + ANY = 0x0000ffff; // Allows any type except ENUM and FLAGS. + REFERENCE = 0x01; // Allows Reference values. + STRING = 0x02; // Allows String/StyledString values. + INTEGER = 0x04; // Allows any integer BinaryPrimitive values. + BOOLEAN = 0x08; // Allows any boolean BinaryPrimitive values. + COLOR = 0x010; // Allows any color BinaryPrimitive values. + FLOAT = 0x020; // Allows any float BinaryPrimitive values. + DIMENSION = 0x040; // Allows any dimension BinaryPrimitive values. + FRACTION = 0x080; // Allows any fraction BinaryPrimitive values. + ENUM = 0x00010000; // Allows enums that are defined in the Attribute's symbols. + // ENUM and FLAGS cannot BOTH be set. + FLAGS = 0x00020000; // Allows flags that are defined in the Attribute's symbols. + // ENUM and FLAGS cannot BOTH be set. + } + + // A bitmask of types that this XML attribute accepts. Corresponds to the flags in the + // enum FormatFlags. optional uint32 format_flags = 1; // The smallest integer allowed for this XML attribute. Only makes sense if the format includes - // TYPE_INTEGER. + // FormatFlags::INTEGER. optional int32 min_int = 2; // The largest integer allowed for this XML attribute. Only makes sense if the format includes - // TYPE_INTEGER. + // FormatFlags::INTEGER. optional int32 max_int = 3; // The set of enums/flags defined in this attribute. Only makes sense if the format includes - // either TYPE_ENUM or TYPE_FLAGS. Having both is an error. - repeated Symbol symbols = 4; + // either FormatFlags::ENUM or FormatFlags::FLAGS. Having both is an error. + repeated Symbol symbol = 4; } // A value that represents a style. @@ -342,7 +343,7 @@ message Style { optional Source parent_source = 2; // The set of XML attribute/value pairs for this style. - repeated Entry entries = 3; + repeated Entry entry = 3; } // A value that represents a <declare-styleable> XML resource. These are not real resources and @@ -361,13 +362,13 @@ message Styleable { } // The set of attribute declarations. - repeated Entry entries = 1; + repeated Entry entry = 1; } // A value that represents an array of resource values. message Array { // A single element of the array. - message Entry { + message Element { // Where the element was defined. optional Source source = 1; @@ -379,19 +380,19 @@ message Array { } // The list of array elements. - repeated Entry entries = 1; + repeated Element element = 1; } // A value that represents a string and its many variations based on plurality. message Plural { // The arity of the plural. enum Arity { - Zero = 0; - One = 1; - Two = 2; - Few = 3; - Many = 4; - Other = 5; + ZERO = 0; + ONE = 1; + TWO = 2; + FEW = 3; + MANY = 4; + OTHER = 5; } // The plural value for a given arity. @@ -410,5 +411,61 @@ message Plural { } // The set of arity/plural mappings. - repeated Entry entries = 1; + repeated Entry entry = 1; +} + +// Defines an abstract XmlNode that must be either an XmlElement, or +// a text node represented by a string. +message XmlNode { + // If set, this node is an element/tag. + optional XmlElement element = 1; + + // If set, this node is a chunk of text. + optional string text = 2; + + // Source line and column info. + optional SourcePosition source = 3; +} + +// An <element> in an XML document. +message XmlElement { + // Namespaces defined on this element. + repeated XmlNamespace namespace_declaration = 1; + + // The namespace URI of this element. + optional string namespace_uri = 2; + + // The name of this element. + optional string name = 3; + + // The attributes of this element. + repeated XmlAttribute attribute = 4; + + // The children of this element. + repeated XmlNode child = 5; +} + +// A namespace declaration on an XmlElement (xmlns:android="http://..."). +message XmlNamespace { + optional string prefix = 1; + optional string uri = 2; + + // Source line and column info. + optional SourcePosition source = 3; +} + +// An attribute defined on an XmlElement (android:text="..."). +message XmlAttribute { + optional string namespace_uri = 1; + optional string name = 2; + optional string value = 3; + + // Source line and column info. + optional SourcePosition source = 4; + + // The resource ID (0xPPTTEEEE) of the attribute. + optional uint32 resource_id = 5; + + // The interpreted/compiled version of the `value` string. + optional Item compiled_item = 6; } diff --git a/tools/aapt2/ResourcesInternal.proto b/tools/aapt2/ResourcesInternal.proto new file mode 100644 index 000000000000..31179174b843 --- /dev/null +++ b/tools/aapt2/ResourcesInternal.proto @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto2"; + +option java_package = "android.aapt.pb.internal"; +option optimize_for = LITE_RUNTIME; + +import "frameworks/base/tools/aapt2/Resources.proto"; + +package aapt.pb.internal; + +// The top level message representing an external resource file (layout XML, PNG, etc). +// This is used to represent a compiled file before it is linked. Only useful to aapt2. +message CompiledFile { + message Symbol { + // The name of the symbol (in the form package:type/name). + optional string resource_name = 1; + + // The position in the file at which this symbol is defined. For debug use. + optional aapt.pb.SourcePosition source = 2; + } + + // The name of the resource (in the form package:type/name). + optional string resource_name = 1; + + // The configuration for which the resource is defined. + optional aapt.pb.ConfigDescription config = 2; + + // The filesystem path to where the source file originated. + // Mainly used to display helpful error messages. + optional string source_path = 3; + + // Any symbols this file auto-generates/exports (eg. @+id/foo in an XML file). + repeated Symbol exported_symbol = 4; + + // If this is a compiled XML file, this is the root node. + optional aapt.pb.XmlNode xml_root = 5; +} diff --git a/tools/aapt2/SdkConstants.h b/tools/aapt2/SdkConstants.h index 864e57d644a6..13584c0bf840 100644 --- a/tools/aapt2/SdkConstants.h +++ b/tools/aapt2/SdkConstants.h @@ -52,7 +52,8 @@ enum : ApiVersion { SDK_NOUGAT = 24, SDK_NOUGAT_MR1 = 25, SDK_O = 26, - SDK_O_MR1 = 10000, // STOPSHIP Replace with the real version. + SDK_O_MR1 = 27, + SDK_P = 10000, // STOPSHIP Replace with the real version. }; ApiVersion FindAttributeSdkLevel(const ResourceId& id); diff --git a/tools/aapt2/ValueVisitor.h b/tools/aapt2/ValueVisitor.h index 2763d49f15c4..eb4fa494e53f 100644 --- a/tools/aapt2/ValueVisitor.h +++ b/tools/aapt2/ValueVisitor.h @@ -80,7 +80,7 @@ struct ValueVisitor : public RawValueVisitor { } void VisitSubValues(Array* array) { - for (std::unique_ptr<Item>& item : array->items) { + for (std::unique_ptr<Item>& item : array->elements) { item->Accept(this); } } diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp index 8536edb34b70..7f5bbf042766 100644 --- a/tools/aapt2/cmd/Compile.cpp +++ b/tools/aapt2/cmd/Compile.cpp @@ -282,7 +282,7 @@ static bool WriteHeaderAndBufferToWriter(const StringPiece& output_path, const R // Number of CompiledFiles. output_stream.WriteLittleEndian32(1); - std::unique_ptr<pb::CompiledFile> compiled_file = SerializeCompiledFileToPb(file); + std::unique_ptr<pb::internal::CompiledFile> compiled_file = SerializeCompiledFileToPb(file); output_stream.WriteCompiledFile(compiled_file.get()); output_stream.WriteData(&buffer); @@ -319,7 +319,7 @@ static bool WriteHeaderAndMmapToWriter(const StringPiece& output_path, const Res // Number of CompiledFiles. output_stream.WriteLittleEndian32(1); - std::unique_ptr<pb::CompiledFile> compiled_file = SerializeCompiledFileToPb(file); + std::unique_ptr<pb::internal::CompiledFile> compiled_file = SerializeCompiledFileToPb(file); output_stream.WriteCompiledFile(compiled_file.get()); output_stream.WriteData(map.getDataPtr(), map.getDataLength()); @@ -346,7 +346,8 @@ static bool FlattenXmlToOutStream(IAaptContext* context, const StringPiece& outp return false; } - std::unique_ptr<pb::CompiledFile> pb_compiled_file = SerializeCompiledFileToPb(xmlres->file); + std::unique_ptr<pb::internal::CompiledFile> pb_compiled_file = + SerializeCompiledFileToPb(xmlres->file); out->WriteCompiledFile(pb_compiled_file.get()); out->WriteData(&buffer); diff --git a/tools/aapt2/cmd/Dump.cpp b/tools/aapt2/cmd/Dump.cpp index aa9472361def..0965910ca853 100644 --- a/tools/aapt2/cmd/Dump.cpp +++ b/tools/aapt2/cmd/Dump.cpp @@ -27,11 +27,11 @@ #include "unflatten/BinaryResourceParser.h" #include "util/Files.h" -using android::StringPiece; +using ::android::StringPiece; namespace aapt { -bool DumpCompiledFile(const pb::CompiledFile& pb_file, const void* data, size_t len, +bool DumpCompiledFile(const pb::internal::CompiledFile& pb_file, const void* data, size_t len, const Source& source, IAaptContext* context) { std::unique_ptr<ResourceFile> file = DeserializeCompiledFileFromPb(pb_file, source, context->GetDiagnostics()); @@ -118,7 +118,7 @@ bool TryDumpFile(IAaptContext* context, const std::string& file_path) { } for (uint32_t i = 0; i < num_files; i++) { - pb::CompiledFile compiled_file; + pb::internal::CompiledFile compiled_file; if (!input.ReadCompiledFile(&compiled_file)) { context->GetDiagnostics()->Warn(DiagMessage() << "failed to read compiled file"); return false; diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index 9005c5bf1a19..3a2faa9f0368 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -457,7 +457,8 @@ std::vector<std::unique_ptr<xml::XmlResource>> ResourceFileFlattener::LinkAndVer const Source& src = doc->file.source; if (context_->IsVerbose()) { - context_->GetDiagnostics()->Note(DiagMessage() << "linking " << src.path); + context_->GetDiagnostics()->Note(DiagMessage() + << "linking " << src.path << " (" << doc->file.name << ")"); } XmlReferenceLinker xml_linker; @@ -482,7 +483,7 @@ std::vector<std::unique_ptr<xml::XmlResource>> ResourceFileFlattener::LinkAndVer if (options_.no_version_vectors || options_.no_version_transitions) { // Skip this if it is a vector or animated-vector. - xml::Element* el = xml::FindRootElement(doc); + xml::Element* el = doc->root.get(); if (el && el->namespace_uri.empty()) { if ((options_.no_version_vectors && IsVectorElement(el->name)) || (options_.no_version_transitions && IsTransitionElement(el->name))) { @@ -505,6 +506,8 @@ bool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archiv std::map<std::pair<ConfigDescription, StringPiece>, FileOperation> config_sorted_files; for (auto& pkg : table->packages) { + CHECK(!pkg->name.empty()) << "Packages must have names when being linked"; + for (auto& type : pkg->types) { // Sort by config and name, so that we get better locality in the zip file. config_sorted_files.clear(); @@ -574,6 +577,11 @@ bool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archiv if (file_op.xml_to_flatten) { std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs = LinkAndVersionXmlFile(table, &file_op); + if (versioned_docs.empty()) { + error = true; + continue; + } + for (std::unique_ptr<xml::XmlResource>& doc : versioned_docs) { std::string dst_path = file_op.dst_path; if (doc->file.config != file_op.config) { @@ -696,7 +704,7 @@ class LinkCommand { util::make_unique<AssetManagerSymbolSource>(); for (const std::string& path : options_.include_paths) { if (context_->IsVerbose()) { - context_->GetDiagnostics()->Note(DiagMessage(path) << "loading include path"); + context_->GetDiagnostics()->Note(DiagMessage() << "including " << path); } // First try to load the file as a static lib. @@ -814,11 +822,9 @@ class LinkCommand { return app_info; } - /** - * Precondition: ResourceTable doesn't have any IDs assigned yet, nor is it linked. - * Postcondition: ResourceTable has only one package left. All others are - * stripped, or there is an error and false is returned. - */ + // Precondition: ResourceTable doesn't have any IDs assigned yet, nor is it linked. + // Postcondition: ResourceTable has only one package left. All others are + // stripped, or there is an error and false is returned. bool VerifyNoExternalPackages() { auto is_ext_package_func = [&](const std::unique_ptr<ResourceTablePackage>& pkg) -> bool { return context_->GetCompilationPackage() != pkg->name || !pkg->id || @@ -960,7 +966,91 @@ class LinkCommand { context_->GetDiagnostics()->Error(DiagMessage() << "failed writing to '" << out_path << "': " << android::base::SystemErrorCodeToString(errno)); + return false; + } + return true; + } + + bool GenerateJavaClasses() { + // The set of packages whose R class to call in the main classes onResourcesLoaded callback. + std::vector<std::string> packages_to_callback; + + JavaClassGeneratorOptions template_options; + template_options.types = JavaClassGeneratorOptions::SymbolTypes::kAll; + template_options.javadoc_annotations = options_.javadoc_annotations; + + if (context_->GetPackageType() == PackageType::kStaticLib || options_.generate_non_final_ids) { + template_options.use_final = false; + } + + if (context_->GetPackageType() == PackageType::kSharedLib) { + template_options.use_final = false; + template_options.rewrite_callback_options = OnResourcesLoadedCallbackOptions{}; + } + + const StringPiece actual_package = context_->GetCompilationPackage(); + StringPiece output_package = context_->GetCompilationPackage(); + if (options_.custom_java_package) { + // Override the output java package to the custom one. + output_package = options_.custom_java_package.value(); + } + + // Generate the private symbols if required. + if (options_.private_symbols) { + packages_to_callback.push_back(options_.private_symbols.value()); + + // If we defined a private symbols package, we only emit Public symbols + // to the original package, and private and public symbols to the private package. + JavaClassGeneratorOptions options = template_options; + options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate; + if (!WriteJavaFile(&final_table_, actual_package, options_.private_symbols.value(), + options)) { + return false; + } + } + + // Generate copies of the original package R class but with different package names. + // This is to support non-namespaced builds. + for (const std::string& extra_package : options_.extra_java_packages) { + packages_to_callback.push_back(extra_package); + + JavaClassGeneratorOptions options = template_options; + options.types = JavaClassGeneratorOptions::SymbolTypes::kAll; + if (!WriteJavaFile(&final_table_, actual_package, extra_package, options)) { + return false; + } + } + + // Generate R classes for each package that was merged (static library). + // Use the actual package's resources only. + for (const std::string& package : table_merger_->merged_packages()) { + packages_to_callback.push_back(package); + + JavaClassGeneratorOptions options = template_options; + options.types = JavaClassGeneratorOptions::SymbolTypes::kAll; + if (!WriteJavaFile(&final_table_, package, package, options)) { + return false; + } + } + + // Generate the main public R class. + JavaClassGeneratorOptions options = template_options; + + // Only generate public symbols if we have a private package. + if (options_.private_symbols) { + options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic; } + + if (options.rewrite_callback_options) { + options.rewrite_callback_options.value().packages_to_callback = + std::move(packages_to_callback); + } + + if (!WriteJavaFile(&final_table_, actual_package, output_package, options, + options_.generate_text_symbols_path)) { + return false; + } + return true; } @@ -1092,15 +1182,17 @@ class LinkCommand { bool result; if (options_.no_static_lib_packages) { - // Merge all resources as if they were in the compilation package. This is - // the old behavior of aapt. + // Merge all resources as if they were in the compilation package. This is the old behavior + // of aapt. - // Add the package to the set of --extra-packages so we emit an R.java for - // each library package. + // Add the package to the set of --extra-packages so we emit an R.java for each library + // package. if (!pkg->name.empty()) { options_.extra_java_packages.insert(pkg->name); } + // Clear the package name, so as to make the resources look like they are coming from the + // local package. pkg->name = ""; if (override) { result = table_merger_->MergeOverlay(Source(input), table.get(), collection.get()); @@ -1290,7 +1382,7 @@ class LinkCommand { } for (uint32_t i = 0; i < num_files; i++) { - pb::CompiledFile compiled_file; + pb::internal::CompiledFile compiled_file; if (!input_stream.ReadCompiledFile(&compiled_file)) { context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to read compiled file header"); @@ -1668,8 +1760,7 @@ class LinkCommand { bool error = false; { - // AndroidManifest.xml has no resource name, but the CallSite is built - // from the name + // AndroidManifest.xml has no resource name, but the CallSite is built from the name // (aka, which package the AndroidManifest.xml is coming from). // So we give it a package name so it can see local resources. manifest_xml->file.name.package = context_->GetCompilationPackage(); @@ -1722,72 +1813,7 @@ class LinkCommand { } if (options_.generate_java_class_path) { - // The set of packages whose R class to call in the main classes - // onResourcesLoaded callback. - std::vector<std::string> packages_to_callback; - - JavaClassGeneratorOptions template_options; - template_options.types = JavaClassGeneratorOptions::SymbolTypes::kAll; - template_options.javadoc_annotations = options_.javadoc_annotations; - - if (context_->GetPackageType() == PackageType::kStaticLib || - options_.generate_non_final_ids) { - template_options.use_final = false; - } - - if (context_->GetPackageType() == PackageType::kSharedLib) { - template_options.use_final = false; - template_options.rewrite_callback_options = OnResourcesLoadedCallbackOptions{}; - } - - const StringPiece actual_package = context_->GetCompilationPackage(); - StringPiece output_package = context_->GetCompilationPackage(); - if (options_.custom_java_package) { - // Override the output java package to the custom one. - output_package = options_.custom_java_package.value(); - } - - // Generate the private symbols if required. - if (options_.private_symbols) { - packages_to_callback.push_back(options_.private_symbols.value()); - - // If we defined a private symbols package, we only emit Public symbols - // to the original package, and private and public symbols to the - // private package. - JavaClassGeneratorOptions options = template_options; - options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate; - if (!WriteJavaFile(&final_table_, actual_package, options_.private_symbols.value(), - options)) { - return 1; - } - } - - // Generate all the symbols for all extra packages. - for (const std::string& extra_package : options_.extra_java_packages) { - packages_to_callback.push_back(extra_package); - - JavaClassGeneratorOptions options = template_options; - options.types = JavaClassGeneratorOptions::SymbolTypes::kAll; - if (!WriteJavaFile(&final_table_, actual_package, extra_package, options)) { - return 1; - } - } - - // Generate the main public R class. - JavaClassGeneratorOptions options = template_options; - - // Only generate public symbols if we have a private package. - if (options_.private_symbols) { - options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic; - } - - if (options.rewrite_callback_options) { - options.rewrite_callback_options.value().packages_to_callback = - std::move(packages_to_callback); - } - - if (!WriteJavaFile(&final_table_, actual_package, output_package, options, - options_.generate_text_symbols_path)) { + if (!GenerateJavaClasses()) { return 1; } } diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp index 9d71775889d4..887803e147da 100644 --- a/tools/aapt2/cmd/Optimize.cpp +++ b/tools/aapt2/cmd/Optimize.cpp @@ -18,6 +18,7 @@ #include <vector> #include "android-base/stringprintf.h" +#include "androidfw/ResourceTypes.h" #include "androidfw/StringPiece.h" #include "Diagnostics.h" @@ -33,15 +34,19 @@ #include "flatten/XmlFlattener.h" #include "io/BigBufferInputStream.h" #include "io/Util.h" +#include "optimize/MultiApkGenerator.h" #include "optimize/ResourceDeduper.h" #include "optimize/VersionCollapser.h" #include "split/TableSplitter.h" #include "util/Files.h" +#include "util/Util.h" using ::aapt::configuration::Abi; using ::aapt::configuration::Artifact; using ::aapt::configuration::PostProcessingConfiguration; +using ::android::ResTable_config; using ::android::StringPiece; +using ::android::base::StringAppendF; using ::android::base::StringPrintf; namespace aapt { @@ -188,42 +193,10 @@ class OptimizeCommand { } if (options_.configuration && options_.output_dir) { - PostProcessingConfiguration& config = options_.configuration.value(); - - // For now, just write out the stripped APK since ABI splitting doesn't modify anything else. - for (const Artifact& artifact : config.artifacts) { - if (artifact.abi_group) { - const std::string& group = artifact.abi_group.value(); - - auto abi_group = config.abi_groups.find(group); - // TODO: Remove validation when configuration parser ensures referential integrity. - if (abi_group == config.abi_groups.end()) { - context_->GetDiagnostics()->Note( - DiagMessage() << "could not find referenced ABI group '" << group << "'"); - return 1; - } - FilterChain filters; - filters.AddFilter(AbiFilter::FromAbiList(abi_group->second)); - - const std::string& path = apk->GetSource().path; - const StringPiece ext = file::GetExtension(path); - const std::string name = path.substr(0, path.rfind(ext.to_string())); - - // Name is hard coded for now since only one split dimension is supported. - // TODO: Incorporate name generation into the configuration objects. - const std::string file_name = - StringPrintf("%s.%s%s", name.c_str(), group.c_str(), ext.data()); - std::string out = options_.output_dir.value(); - file::AppendPath(&out, file_name); - - std::unique_ptr<IArchiveWriter> writer = - CreateZipFileArchiveWriter(context_->GetDiagnostics(), out); - - if (!apk->WriteToArchive(context_, options_.table_flattener_options, &filters, - writer.get())) { - return 1; - } - } + MultiApkGenerator generator{apk.get(), context_}; + if (!generator.FromBaseApk(options_.output_dir.value(), options_.configuration.value(), + options_.table_flattener_options)) { + return 1; } } @@ -260,7 +233,7 @@ class OptimizeCommand { for (auto& entry : type->entries) { for (auto& config_value : entry->values) { - FileReference* file_ref = ValueCast<FileReference>(config_value->value.get()); + auto* file_ref = ValueCast<FileReference>(config_value->value.get()); if (file_ref == nullptr) { continue; } @@ -297,11 +270,8 @@ class OptimizeCommand { } io::BigBufferInputStream table_buffer_in(&table_buffer); - if (!io::CopyInputStreamToArchive(context_, &table_buffer_in, "resources.arsc", - ArchiveEntry::kAlign, writer)) { - return false; - } - return true; + return io::CopyInputStreamToArchive(context_, &table_buffer_in, "resources.arsc", + ArchiveEntry::kAlign, writer); } OptimizeOptions options_; @@ -349,20 +319,29 @@ int Optimize(const std::vector<StringPiece>& args) { OptimizeOptions options; Maybe<std::string> config_path; Maybe<std::string> target_densities; + Maybe<std::string> target_abis; std::vector<std::string> configs; std::vector<std::string> split_args; bool verbose = false; + bool print_only = false; Flags flags = Flags() .OptionalFlag("-o", "Path to the output APK.", &options.output_path) .OptionalFlag("-d", "Path to the output directory (for splits).", &options.output_dir) .OptionalFlag("-x", "Path to XML configuration file.", &config_path) + .OptionalSwitch("-p", "Print the multi APK artifacts and exit.", &print_only) .OptionalFlag( "--target-densities", "Comma separated list of the screen densities that the APK will be optimized for.\n" "All the resources that would be unused on devices of the given densities will be \n" "removed from the APK.", &target_densities) + .OptionalFlag( + "--target-abis", + "Comma separated list of the CPU ABIs that the APK will be optimized for.\n" + "All the native libraries that would be unused on devices of the given ABIs will \n" + "be removed from the APK.", + &target_abis) .OptionalFlagList("-c", "Comma separated list of configurations to include. The default\n" "is all configurations.", @@ -388,18 +367,19 @@ int Optimize(const std::vector<StringPiece>& args) { return 1; } - std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(&context, flags.GetArgs()[0]); + const std::string& apk_path = flags.GetArgs()[0]; + std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(&context, apk_path); if (!apk) { return 1; } context.SetVerbose(verbose); + IDiagnostics* diag = context.GetDiagnostics(); if (target_densities) { // Parse the target screen densities. for (const StringPiece& config_str : util::Tokenize(target_densities.value(), ',')) { - Maybe<uint16_t> target_density = - ParseTargetDensityParameter(config_str, context.GetDiagnostics()); + Maybe<uint16_t> target_density = ParseTargetDensityParameter(config_str, diag); if (!target_density) { return 1; } @@ -409,7 +389,7 @@ int Optimize(const std::vector<StringPiece>& args) { std::unique_ptr<IConfigFilter> filter; if (!configs.empty()) { - filter = ParseConfigFilterParameters(configs, context.GetDiagnostics()); + filter = ParseConfigFilterParameters(configs, diag); if (filter == nullptr) { return 1; } @@ -418,28 +398,47 @@ int Optimize(const std::vector<StringPiece>& args) { // Parse the split parameters. for (const std::string& split_arg : split_args) { - options.split_paths.push_back({}); - options.split_constraints.push_back({}); - if (!ParseSplitParameter(split_arg, context.GetDiagnostics(), &options.split_paths.back(), + options.split_paths.emplace_back(); + options.split_constraints.emplace_back(); + if (!ParseSplitParameter(split_arg, diag, &options.split_paths.back(), &options.split_constraints.back())) { return 1; } } if (config_path) { - if (!options.output_dir) { - context.GetDiagnostics()->Error( - DiagMessage() << "Output directory is required when using a configuration file"); - return 1; - } std::string& path = config_path.value(); Maybe<ConfigurationParser> for_path = ConfigurationParser::ForPath(path); if (for_path) { - options.configuration = for_path.value().WithDiagnostics(context.GetDiagnostics()).Parse(); + options.configuration = for_path.value().WithDiagnostics(diag).Parse(); } else { - context.GetDiagnostics()->Error(DiagMessage() << "Could not parse config file " << path); + diag->Error(DiagMessage() << "Could not parse config file " << path); return 1; } + + if (print_only) { + std::vector<std::string> names; + const PostProcessingConfiguration& config = options.configuration.value(); + if (!config.AllArtifactNames(file::GetFilename(apk_path), &names, diag)) { + diag->Error(DiagMessage() << "Failed to generate output artifact list"); + return 1; + } + + for (const auto& name : names) { + std::cout << name << std::endl; + } + return 0; + } + + // Since we know that we are going to process the APK (not just print targets), make sure we + // have somewhere to write them to. + if (!options.output_dir) { + diag->Error(DiagMessage() << "Output directory is required when using a configuration file"); + return 1; + } + } else if (print_only) { + diag->Error(DiagMessage() << "Asked to print artifacts without providing a configurations"); + return 1; } if (!ExtractAppDataFromManifest(&context, apk.get(), &options)) { diff --git a/tools/aapt2/cmd/Util.cpp b/tools/aapt2/cmd/Util.cpp index e1c45d68f611..d17858d45d08 100644 --- a/tools/aapt2/cmd/Util.cpp +++ b/tools/aapt2/cmd/Util.cpp @@ -28,7 +28,7 @@ #include "util/Maybe.h" #include "util/Util.h" -using android::StringPiece; +using ::android::StringPiece; namespace aapt { @@ -134,19 +134,21 @@ static xml::AaptAttribute CreateAttributeWithId(const ResourceId& id) { return xml::AaptAttribute(Attribute(), id); } +static xml::NamespaceDecl CreateAndroidNamespaceDecl() { + xml::NamespaceDecl decl; + decl.prefix = "android"; + decl.uri = xml::kSchemaAndroid; + return decl; +} + std::unique_ptr<xml::XmlResource> GenerateSplitManifest(const AppInfo& app_info, const SplitConstraints& constraints) { const ResourceId kVersionCode(0x0101021b); const ResourceId kRevisionCode(0x010104d5); const ResourceId kHasCode(0x0101000c); - std::unique_ptr<xml::XmlResource> doc = util::make_unique<xml::XmlResource>(); - - std::unique_ptr<xml::Namespace> namespace_android = util::make_unique<xml::Namespace>(); - namespace_android->namespace_uri = xml::kSchemaAndroid; - namespace_android->namespace_prefix = "android"; - std::unique_ptr<xml::Element> manifest_el = util::make_unique<xml::Element>(); + manifest_el->namespace_decls.push_back(CreateAndroidNamespaceDecl()); manifest_el->name = "manifest"; manifest_el->attributes.push_back(xml::Attribute{"", "package", app_info.package}); @@ -179,8 +181,8 @@ std::unique_ptr<xml::XmlResource> GenerateSplitManifest(const AppInfo& app_info, xml::Attribute{"", "configForSplit", app_info.split_name.value()}); } - // Splits may contain more configurations than originally desired (fallback densities, etc.). - // This makes programmatic discovery of split targetting difficult. Encode the original + // Splits may contain more configurations than originally desired (fall-back densities, etc.). + // This makes programmatic discovery of split targeting difficult. Encode the original // split constraints intended for this split. std::stringstream target_config_str; target_config_str << util::Joiner(constraints.configs, ","); @@ -193,8 +195,9 @@ std::unique_ptr<xml::XmlResource> GenerateSplitManifest(const AppInfo& app_info, util::make_unique<BinaryPrimitive>(android::Res_value::TYPE_INT_BOOLEAN, 0u)}); manifest_el->AppendChild(std::move(application_el)); - namespace_android->AppendChild(std::move(manifest_el)); - doc->root = std::move(namespace_android); + + std::unique_ptr<xml::XmlResource> doc = util::make_unique<xml::XmlResource>(); + doc->root = std::move(manifest_el); return doc; } @@ -284,7 +287,7 @@ static Maybe<int> ExtractSdkVersion(xml::Attribute* attr, std::string* out_error Maybe<AppInfo> ExtractAppInfoFromBinaryManifest(xml::XmlResource* xml_res, IDiagnostics* diag) { // Make sure the first element is <manifest> with package attribute. - xml::Element* manifest_el = xml::FindRootElement(xml_res->root.get()); + xml::Element* manifest_el = xml_res->root.get(); if (manifest_el == nullptr) { return {}; } diff --git a/tools/aapt2/compile/InlineXmlFormatParser.cpp b/tools/aapt2/compile/InlineXmlFormatParser.cpp index 786494b6ad1c..a17926067a0b 100644 --- a/tools/aapt2/compile/InlineXmlFormatParser.cpp +++ b/tools/aapt2/compile/InlineXmlFormatParser.cpp @@ -16,12 +16,8 @@ #include "compile/InlineXmlFormatParser.h" -#include <sstream> #include <string> -#include "android-base/macros.h" - -#include "Debug.h" #include "ResourceUtils.h" #include "util/Util.h" #include "xml/XmlDom.h" @@ -31,19 +27,17 @@ namespace aapt { namespace { -/** - * XML Visitor that will find all <aapt:attr> elements for extraction. - */ +struct InlineDeclaration { + xml::Element* el; + std::string attr_namespace_uri; + std::string attr_name; +}; + +// XML Visitor that will find all <aapt:attr> elements for extraction. class Visitor : public xml::PackageAwareVisitor { public: using xml::PackageAwareVisitor::Visit; - struct InlineDeclaration { - xml::Element* el; - std::string attr_namespace_uri; - std::string attr_name; - }; - explicit Visitor(IAaptContext* context, xml::XmlResource* xml_resource) : context_(context), xml_resource_(xml_resource) {} @@ -53,51 +47,44 @@ class Visitor : public xml::PackageAwareVisitor { return; } - const Source& src = xml_resource_->file.source.WithLine(el->line_number); + const Source src = xml_resource_->file.source.WithLine(el->line_number); xml::Attribute* attr = el->FindAttribute({}, "name"); if (!attr) { - context_->GetDiagnostics()->Error(DiagMessage(src) - << "missing 'name' attribute"); + context_->GetDiagnostics()->Error(DiagMessage(src) << "missing 'name' attribute"); error_ = true; return; } Maybe<Reference> ref = ResourceUtils::ParseXmlAttributeName(attr->value); if (!ref) { - context_->GetDiagnostics()->Error( - DiagMessage(src) << "invalid XML attribute '" << attr->value << "'"); + context_->GetDiagnostics()->Error(DiagMessage(src) << "invalid XML attribute '" << attr->value + << "'"); error_ = true; return; } const ResourceName& name = ref.value().name.value(); - // Use an empty string for the compilation package because we don't want to - // default to - // the local package if the user specified name="style" or something. This - // should just + // Use an empty string for the compilation package because we don't want to default to + // the local package if the user specified name="style" or something. This should just // be the default namespace. - Maybe<xml::ExtractedPackage> maybe_pkg = - TransformPackageAlias(name.package, {}); + Maybe<xml::ExtractedPackage> maybe_pkg = TransformPackageAlias(name.package); if (!maybe_pkg) { context_->GetDiagnostics()->Error(DiagMessage(src) - << "invalid namespace prefix '" - << name.package << "'"); + << "invalid namespace prefix '" << name.package << "'"); error_ = true; return; } const xml::ExtractedPackage& pkg = maybe_pkg.value(); - const bool private_namespace = - pkg.private_namespace || ref.value().private_reference; + const bool private_namespace = pkg.private_namespace || ref.value().private_reference; InlineDeclaration decl; decl.el = el; decl.attr_name = name.entry; if (!pkg.package.empty()) { - decl.attr_namespace_uri = - xml::BuildPackageNamespace(pkg.package, private_namespace); + decl.attr_namespace_uri = xml::BuildPackageNamespace(pkg.package, private_namespace); } inline_declarations_.push_back(std::move(decl)); @@ -107,7 +94,9 @@ class Visitor : public xml::PackageAwareVisitor { return inline_declarations_; } - bool HasError() const { return error_; } + bool HasError() const { + return error_; + } private: DISALLOW_COPY_AND_ASSIGN(Visitor); @@ -120,8 +109,7 @@ class Visitor : public xml::PackageAwareVisitor { } // namespace -bool InlineXmlFormatParser::Consume(IAaptContext* context, - xml::XmlResource* doc) { +bool InlineXmlFormatParser::Consume(IAaptContext* context, xml::XmlResource* doc) { Visitor visitor(context, doc); doc->root->Accept(&visitor); if (visitor.HasError()) { @@ -129,69 +117,53 @@ bool InlineXmlFormatParser::Consume(IAaptContext* context, } size_t name_suffix_counter = 0; - for (const Visitor::InlineDeclaration& decl : - visitor.GetInlineDeclarations()) { + for (const InlineDeclaration& decl : visitor.GetInlineDeclarations()) { auto new_doc = util::make_unique<xml::XmlResource>(); new_doc->file.config = doc->file.config; new_doc->file.source = doc->file.source.WithLine(decl.el->line_number); new_doc->file.name = doc->file.name; // Modify the new entry name. We need to suffix the entry with a number to - // avoid - // local collisions, then mangle it with the empty package, such that it - // won't show up + // avoid local collisions, then mangle it with the empty package, such that it won't show up // in R.java. - - new_doc->file.name.entry = - NameMangler::MangleEntry({}, new_doc->file.name.entry + "__" + - std::to_string(name_suffix_counter)); + new_doc->file.name.entry = NameMangler::MangleEntry( + {}, new_doc->file.name.entry + "__" + std::to_string(name_suffix_counter)); // Extracted elements must be the only child of <aapt:attr>. // Make sure there is one root node in the children (ignore empty text). - for (auto& child : decl.el->children) { + for (std::unique_ptr<xml::Node>& child : decl.el->children) { const Source child_source = doc->file.source.WithLine(child->line_number); if (xml::Text* t = xml::NodeCast<xml::Text>(child.get())) { if (!util::TrimWhitespace(t->text).empty()) { - context->GetDiagnostics()->Error( - DiagMessage(child_source) - << "can't extract text into its own resource"); + context->GetDiagnostics()->Error(DiagMessage(child_source) + << "can't extract text into its own resource"); return false; } } else if (new_doc->root) { - context->GetDiagnostics()->Error( - DiagMessage(child_source) - << "inline XML resources must have a single root"); + context->GetDiagnostics()->Error(DiagMessage(child_source) + << "inline XML resources must have a single root"); return false; } else { - new_doc->root = std::move(child); + new_doc->root.reset(static_cast<xml::Element*>(child.release())); new_doc->root->parent = nullptr; } } - // Walk up and find the parent element. - xml::Node* node = decl.el; - xml::Element* parent_el = nullptr; - while (node->parent && - (parent_el = xml::NodeCast<xml::Element>(node->parent)) == nullptr) { - node = node->parent; - } - + // Get the parent element of <aapt:attr> + xml::Element* parent_el = decl.el->parent; if (!parent_el) { - context->GetDiagnostics()->Error( - DiagMessage(new_doc->file.source) - << "no suitable parent for inheriting attribute"); + context->GetDiagnostics()->Error(DiagMessage(new_doc->file.source) + << "no suitable parent for inheriting attribute"); return false; } // Add the inline attribute to the parent. - parent_el->attributes.push_back( - xml::Attribute{decl.attr_namespace_uri, decl.attr_name, - "@" + new_doc->file.name.ToString()}); + parent_el->attributes.push_back(xml::Attribute{decl.attr_namespace_uri, decl.attr_name, + "@" + new_doc->file.name.ToString()}); // Delete the subtree. - for (auto iter = parent_el->children.begin(); - iter != parent_el->children.end(); ++iter) { - if (iter->get() == node) { + for (auto iter = parent_el->children.begin(); iter != parent_el->children.end(); ++iter) { + if (iter->get() == decl.el) { parent_el->children.erase(iter); break; } diff --git a/tools/aapt2/compile/InlineXmlFormatParser.h b/tools/aapt2/compile/InlineXmlFormatParser.h index 1a658fd6a180..4300023e7726 100644 --- a/tools/aapt2/compile/InlineXmlFormatParser.h +++ b/tools/aapt2/compile/InlineXmlFormatParser.h @@ -26,35 +26,30 @@ namespace aapt { -/** - * Extracts Inline XML definitions into their own xml::XmlResource objects. - * - * Inline XML looks like: - * - * <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="64dp" - * android:width="64dp" - * android:viewportHeight="600" - * android:viewportWidth="600"/> - * </aapt:attr> - * </animated-vector> - * - * The <vector> will be extracted into its own XML file and <animated-vector> - * will - * gain an attribute 'android:drawable' set to a reference to the extracted - * <vector> resource. - */ +// Extracts Inline XML definitions into their own xml::XmlResource objects. +// +// Inline XML looks like: +// +// <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="64dp" +// android:width="64dp" +// android:viewportHeight="600" +// android:viewportWidth="600"/> +// </aapt:attr> +// </animated-vector> +// +// The <vector> will be extracted into its own XML file and <animated-vector> will +// gain an attribute 'android:drawable' set to a reference to the extracted <vector> resource. class InlineXmlFormatParser : public IXmlResourceConsumer { public: explicit InlineXmlFormatParser() = default; bool Consume(IAaptContext* context, xml::XmlResource* doc) override; - std::vector<std::unique_ptr<xml::XmlResource>>& - GetExtractedInlineXmlDocuments() { + std::vector<std::unique_ptr<xml::XmlResource>>& GetExtractedInlineXmlDocuments() { return queue_; } diff --git a/tools/aapt2/compile/InlineXmlFormatParser_test.cpp b/tools/aapt2/compile/InlineXmlFormatParser_test.cpp index 348796c98c22..de7739ada407 100644 --- a/tools/aapt2/compile/InlineXmlFormatParser_test.cpp +++ b/tools/aapt2/compile/InlineXmlFormatParser_test.cpp @@ -18,25 +18,32 @@ #include "test/Test.h" +using ::testing::Eq; +using ::testing::IsNull; +using ::testing::Not; +using ::testing::NotNull; +using ::testing::SizeIs; +using ::testing::StrEq; + namespace aapt { TEST(InlineXmlFormatParserTest, PassThrough) { std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); - std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"EOF( + std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"( <View xmlns:android="http://schemas.android.com/apk/res/android"> <View android:text="hey"> <View android:id="hi" /> </View> - </View>)EOF"); + </View>)"); InlineXmlFormatParser parser; ASSERT_TRUE(parser.Consume(context.get(), doc.get())); - EXPECT_EQ(0u, parser.GetExtractedInlineXmlDocuments().size()); + EXPECT_THAT(parser.GetExtractedInlineXmlDocuments(), SizeIs(0u)); } TEST(InlineXmlFormatParserTest, ExtractOneXmlResource) { std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); - std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"EOF( + std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"( <View1 xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"> <aapt:attr name="android:text"> @@ -44,7 +51,7 @@ TEST(InlineXmlFormatParserTest, ExtractOneXmlResource) { <View3 android:id="hi" /> </View2> </aapt:attr> - </View1>)EOF"); + </View1>)"); doc->file.name = test::ParseNameOrDie("layout/main"); @@ -52,42 +59,38 @@ TEST(InlineXmlFormatParserTest, ExtractOneXmlResource) { ASSERT_TRUE(parser.Consume(context.get(), doc.get())); // One XML resource should have been extracted. - EXPECT_EQ(1u, parser.GetExtractedInlineXmlDocuments().size()); - - xml::Element* el = xml::FindRootElement(doc.get()); - ASSERT_NE(nullptr, el); + EXPECT_THAT(parser.GetExtractedInlineXmlDocuments(), SizeIs(1u)); - EXPECT_EQ("View1", el->name); + xml::Element* el = doc->root.get(); + ASSERT_THAT(el, NotNull()); + EXPECT_THAT(el->name, StrEq("View1")); // The <aapt:attr> tag should be extracted. - EXPECT_EQ(nullptr, el->FindChild(xml::kSchemaAapt, "attr")); + EXPECT_THAT(el->FindChild(xml::kSchemaAapt, "attr"), IsNull()); // The 'android:text' attribute should be set with a reference. xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "text"); - ASSERT_NE(nullptr, attr); + ASSERT_THAT(attr, NotNull()); ResourceNameRef name_ref; ASSERT_TRUE(ResourceUtils::ParseReference(attr->value, &name_ref)); - xml::XmlResource* extracted_doc = - parser.GetExtractedInlineXmlDocuments()[0].get(); - ASSERT_NE(nullptr, extracted_doc); + xml::XmlResource* extracted_doc = parser.GetExtractedInlineXmlDocuments()[0].get(); + ASSERT_THAT(extracted_doc, NotNull()); // Make sure the generated reference is correct. - EXPECT_EQ(name_ref.package, extracted_doc->file.name.package); - EXPECT_EQ(name_ref.type, extracted_doc->file.name.type); - EXPECT_EQ(name_ref.entry, extracted_doc->file.name.entry); + EXPECT_THAT(extracted_doc->file.name, Eq(name_ref)); // Verify the structure of the extracted XML. - el = xml::FindRootElement(extracted_doc); - ASSERT_NE(nullptr, el); - EXPECT_EQ("View2", el->name); - EXPECT_NE(nullptr, el->FindChild({}, "View3")); + el = extracted_doc->root.get(); + ASSERT_THAT(el, NotNull()); + EXPECT_THAT(el->name, StrEq("View2")); + EXPECT_THAT(el->FindChild({}, "View3"), NotNull()); } TEST(InlineXmlFormatParserTest, ExtractTwoXmlResources) { std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); - std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"EOF( + std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"( <View1 xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"> <aapt:attr name="android:text"> @@ -99,45 +102,39 @@ TEST(InlineXmlFormatParserTest, ExtractTwoXmlResources) { <aapt:attr name="android:drawable"> <vector /> </aapt:attr> - </View1>)EOF"); + </View1>)"); doc->file.name = test::ParseNameOrDie("layout/main"); InlineXmlFormatParser parser; ASSERT_TRUE(parser.Consume(context.get(), doc.get())); - ASSERT_EQ(2u, parser.GetExtractedInlineXmlDocuments().size()); - - xml::Element* el = xml::FindRootElement(doc.get()); - ASSERT_NE(nullptr, el); + ASSERT_THAT(parser.GetExtractedInlineXmlDocuments(), SizeIs(2u)); - EXPECT_EQ("View1", el->name); + xml::Element* el = doc->root.get(); + ASSERT_THAT(el, NotNull()); + EXPECT_THAT(el->name, StrEq("View1")); xml::Attribute* attr_text = el->FindAttribute(xml::kSchemaAndroid, "text"); - ASSERT_NE(nullptr, attr_text); + ASSERT_THAT(attr_text, NotNull()); - xml::Attribute* attr_drawable = - el->FindAttribute(xml::kSchemaAndroid, "drawable"); - ASSERT_NE(nullptr, attr_drawable); + xml::Attribute* attr_drawable = el->FindAttribute(xml::kSchemaAndroid, "drawable"); + ASSERT_THAT(attr_drawable, NotNull()); // The two extracted resources should have different names. - EXPECT_NE(attr_text->value, attr_drawable->value); + EXPECT_THAT(attr_text->value, Not(Eq(attr_drawable->value))); // The child <aapt:attr> elements should be gone. - EXPECT_EQ(nullptr, el->FindChild(xml::kSchemaAapt, "attr")); - - xml::XmlResource* extracted_doc_text = - parser.GetExtractedInlineXmlDocuments()[0].get(); - ASSERT_NE(nullptr, extracted_doc_text); - el = xml::FindRootElement(extracted_doc_text); - ASSERT_NE(nullptr, el); - EXPECT_EQ("View2", el->name); - - xml::XmlResource* extracted_doc_drawable = - parser.GetExtractedInlineXmlDocuments()[1].get(); - ASSERT_NE(nullptr, extracted_doc_drawable); - el = xml::FindRootElement(extracted_doc_drawable); - ASSERT_NE(nullptr, el); - EXPECT_EQ("vector", el->name); + EXPECT_THAT(el->FindChild(xml::kSchemaAapt, "attr"), IsNull()); + + xml::XmlResource* extracted_doc_text = parser.GetExtractedInlineXmlDocuments()[0].get(); + ASSERT_THAT(extracted_doc_text, NotNull()); + ASSERT_THAT(extracted_doc_text->root, NotNull()); + EXPECT_THAT(extracted_doc_text->root->name, StrEq("View2")); + + xml::XmlResource* extracted_doc_drawable = parser.GetExtractedInlineXmlDocuments()[1].get(); + ASSERT_THAT(extracted_doc_drawable, NotNull()); + ASSERT_THAT(extracted_doc_drawable->root, NotNull()); + EXPECT_THAT(extracted_doc_drawable->root->name, StrEq("vector")); } } // namespace aapt diff --git a/tools/aapt2/configuration/ConfigurationParser.cpp b/tools/aapt2/configuration/ConfigurationParser.cpp index b0ed792215df..1735a504e553 100644 --- a/tools/aapt2/configuration/ConfigurationParser.cpp +++ b/tools/aapt2/configuration/ConfigurationParser.cpp @@ -30,6 +30,7 @@ #include "io/File.h" #include "io/FileSystem.h" #include "io/StringInputStream.h" +#include "util/Files.h" #include "util/Maybe.h" #include "util/Util.h" #include "xml/XmlActionExecutor.h" @@ -53,12 +54,12 @@ using ::aapt::io::RegularFile; using ::aapt::io::StringInputStream; using ::aapt::util::TrimWhitespace; using ::aapt::xml::Element; -using ::aapt::xml::FindRootElement; using ::aapt::xml::NodeCast; using ::aapt::xml::XmlActionExecutor; using ::aapt::xml::XmlActionExecutorPolicy; using ::aapt::xml::XmlNodeAction; using ::android::base::ReadFileToString; +using ::android::StringPiece; const std::unordered_map<std::string, Abi> kStringToAbiMap = { {"armeabi", Abi::kArmeV6}, {"armeabi-v7a", Abi::kArmV7a}, {"arm64-v8a", Abi::kArm64V8a}, @@ -117,9 +118,9 @@ const std::string& AbiToString(Abi abi) { * success, or false if the either the placeholder is not found in the name, or the value is not * present and the placeholder was. */ -static bool ReplacePlaceholder(const std::string& placeholder, const Maybe<std::string>& value, +static bool ReplacePlaceholder(const StringPiece& placeholder, const Maybe<StringPiece>& value, std::string* name, IDiagnostics* diag) { - size_t offset = name->find(placeholder); + size_t offset = name->find(placeholder.data()); bool found = (offset != std::string::npos); // Make sure the placeholder was present if the desired value is present. @@ -139,46 +140,119 @@ static bool ReplacePlaceholder(const std::string& placeholder, const Maybe<std:: return false; } - name->replace(offset, placeholder.length(), value.value()); + name->replace(offset, placeholder.length(), value.value().data()); // Make sure there was only one instance of the placeholder. - if (name->find(placeholder) != std::string::npos) { + if (name->find(placeholder.data()) != std::string::npos) { diag->Error(DiagMessage() << "Placeholder present multiple times: " << placeholder); return false; } return true; } -Maybe<std::string> Artifact::ToArtifactName(const std::string& format, IDiagnostics* diag) const { - std::string result = format; +/** + * Returns the common artifact base name from a template string. + */ +Maybe<std::string> ToBaseName(std::string result, const StringPiece& apk_name, IDiagnostics* diag) { + const StringPiece ext = file::GetExtension(apk_name); + size_t end_index = apk_name.to_string().rfind(ext.to_string()); + const std::string base_name = + (end_index != std::string::npos) ? std::string{apk_name.begin(), end_index} : ""; + + // Base name is optional. + if (result.find("${basename}") != std::string::npos) { + Maybe<StringPiece> maybe_base_name = + base_name.empty() ? Maybe<StringPiece>{} : Maybe<StringPiece>{base_name}; + if (!ReplacePlaceholder("${basename}", maybe_base_name, &result, diag)) { + return {}; + } + } + + // Extension is optional. + if (result.find("${ext}") != std::string::npos) { + // Make sure we disregard the '.' in the extension when replacing the placeholder. + if (!ReplacePlaceholder("${ext}", {ext.substr(1)}, &result, diag)) { + return {}; + } + } else { + // If no extension is specified, and the name template does not end in the current extension, + // add the existing extension. + if (!util::EndsWith(result, ext)) { + result.append(ext.to_string()); + } + } + + return result; +} - if (!ReplacePlaceholder("{abi}", abi_group, &result, diag)) { +Maybe<std::string> Artifact::ToArtifactName(const StringPiece& format, const StringPiece& apk_name, + IDiagnostics* diag) const { + Maybe<std::string> base = ToBaseName(format.to_string(), apk_name, diag); + if (!base) { return {}; } + std::string result = std::move(base.value()); - if (!ReplacePlaceholder("{density}", screen_density_group, &result, diag)) { + if (!ReplacePlaceholder("${abi}", abi_group, &result, diag)) { return {}; } - if (!ReplacePlaceholder("{locale}", locale_group, &result, diag)) { + if (!ReplacePlaceholder("${density}", screen_density_group, &result, diag)) { return {}; } - if (!ReplacePlaceholder("{sdk}", android_sdk_group, &result, diag)) { + if (!ReplacePlaceholder("${locale}", locale_group, &result, diag)) { return {}; } - if (!ReplacePlaceholder("{feature}", device_feature_group, &result, diag)) { + if (!ReplacePlaceholder("${sdk}", android_sdk_group, &result, diag)) { return {}; } - if (!ReplacePlaceholder("{gl}", gl_texture_group, &result, diag)) { + if (!ReplacePlaceholder("${feature}", device_feature_group, &result, diag)) { + return {}; + } + + if (!ReplacePlaceholder("${gl}", gl_texture_group, &result, diag)) { return {}; } return result; } +Maybe<std::string> Artifact::Name(const StringPiece& apk_name, IDiagnostics* diag) const { + if (!name) { + return {}; + } + + return ToBaseName(name.value(), apk_name, diag); +} + +bool PostProcessingConfiguration::AllArtifactNames(const StringPiece& apk_name, + std::vector<std::string>* artifact_names, + IDiagnostics* diag) const { + for (const auto& artifact : artifacts) { + Maybe<std::string> name; + if (artifact.name) { + name = artifact.Name(apk_name, diag); + } else { + if (!artifact_format) { + diag->Error(DiagMessage() << "No global artifact template and an artifact name is missing"); + return false; + } + name = artifact.ToArtifactName(artifact_format.value(), apk_name, diag); + } + + if (!name) { + return false; + } + + artifact_names->push_back(std::move(name.value())); + } + + return true; +} + } // namespace configuration /** Returns a ConfigurationParser for the file located at the provided path. */ @@ -197,13 +271,13 @@ ConfigurationParser::ConfigurationParser(std::string contents) Maybe<PostProcessingConfiguration> ConfigurationParser::Parse() { StringInputStream in(contents_); - auto doc = xml::Inflate(&in, diag_, Source("config.xml")); + std::unique_ptr<xml::XmlResource> doc = xml::Inflate(&in, diag_, Source("config.xml")); if (!doc) { return {}; } // Strip any namespaces from the XML as the XmlActionExecutor ignores anything with a namespace. - auto* root = FindRootElement(doc.get()); + Element* root = doc->root.get(); if (root == nullptr) { diag_->Error(DiagMessage() << "Could not find the root element in the XML document"); return {}; @@ -346,7 +420,10 @@ ConfigurationParser::ActionHandler ConfigurationParser::screen_density_group_han if ((t = NodeCast<xml::Text>(node.get())) != nullptr) { ConfigDescription config_descriptor; const android::StringPiece& text = TrimWhitespace(t->text); - if (ConfigDescription::Parse(text, &config_descriptor)) { + bool parsed = ConfigDescription::Parse(text, &config_descriptor); + if (parsed && + (config_descriptor.CopyWithoutSdkVersion().diff(ConfigDescription::DefaultConfig()) == + android::ResTable_config::CONFIG_DENSITY)) { // Copy the density with the minimum SDK version stripped out. group.push_back(config_descriptor.CopyWithoutSdkVersion()); } else { @@ -379,17 +456,25 @@ ConfigurationParser::ActionHandler ConfigurationParser::locale_group_handler_ = << child->name); valid = false; } else { - Locale entry; - for (const auto& attr : child->attributes) { - if (attr.name == "lang") { - entry.lang = {attr.value}; - } else if (attr.name == "region") { - entry.region = {attr.value}; - } else { - diag->Warn(DiagMessage() << "Unknown attribute: " << attr.name << " = " << attr.value); + for (auto& node : child->children) { + xml::Text* t; + if ((t = NodeCast<xml::Text>(node.get())) != nullptr) { + ConfigDescription config_descriptor; + const android::StringPiece& text = TrimWhitespace(t->text); + bool parsed = ConfigDescription::Parse(text, &config_descriptor); + if (parsed && + (config_descriptor.CopyWithoutSdkVersion().diff(ConfigDescription::DefaultConfig()) == + android::ResTable_config::CONFIG_LOCALE)) { + // Copy the locale with the minimum SDK version stripped out. + group.push_back(config_descriptor.CopyWithoutSdkVersion()); + } else { + diag->Error(DiagMessage() + << "Could not parse config descriptor for screen-density: " << text); + valid = false; + } + break; } } - group.push_back(entry); } } diff --git a/tools/aapt2/configuration/ConfigurationParser.h b/tools/aapt2/configuration/ConfigurationParser.h index 28c355e39643..a58685e3b8a6 100644 --- a/tools/aapt2/configuration/ConfigurationParser.h +++ b/tools/aapt2/configuration/ConfigurationParser.h @@ -36,7 +36,7 @@ using Group = std::unordered_map<std::string, std::vector<T>>; /** Output artifact configuration options. */ struct Artifact { /** Name to use for output of processing foo.apk -> foo.<name>.apk. */ - std::string name; + Maybe<std::string> name; /** If present, uses the ABI group with this name. */ Maybe<std::string> abi_group; /** If present, uses the screen density group with this name. */ @@ -51,7 +51,11 @@ struct Artifact { Maybe<std::string> gl_texture_group; /** Convert an artifact name template into a name string based on configuration contents. */ - Maybe<std::string> ToArtifactName(const std::string& format, IDiagnostics* diag) const; + Maybe<std::string> ToArtifactName(const android::StringPiece& format, + const android::StringPiece& apk_name, IDiagnostics* diag) const; + + /** Convert an artifact name template into a name string based on configuration contents. */ + Maybe<std::string> Name(const android::StringPiece& apk_name, IDiagnostics* diag) const; }; /** Enumeration of currently supported ABIs. */ @@ -129,10 +133,14 @@ struct PostProcessingConfiguration { Group<Abi> abi_groups; Group<ConfigDescription> screen_density_groups; - Group<Locale> locale_groups; + Group<ConfigDescription> locale_groups; Group<AndroidSdk> android_sdk_groups; Group<DeviceFeature> device_feature_groups; Group<GlTexture> gl_texture_groups; + + /** Helper method that generates a list of artifact names and returns true on success. */ + bool AllArtifactNames(const android::StringPiece& apk_name, + std::vector<std::string>* artifact_names, IDiagnostics* diag) const; }; } // namespace configuration diff --git a/tools/aapt2/configuration/ConfigurationParser_test.cpp b/tools/aapt2/configuration/ConfigurationParser_test.cpp index ab3b7ec2003b..d3bfd330fe9d 100644 --- a/tools/aapt2/configuration/ConfigurationParser_test.cpp +++ b/tools/aapt2/configuration/ConfigurationParser_test.cpp @@ -18,9 +18,6 @@ #include <string> -#include <gmock/gmock.h> -#include <gtest/gtest.h> - #include "androidfw/ResourceTypes.h" #include "test/Test.h" @@ -29,7 +26,7 @@ namespace aapt { namespace { -using android::ResTable_config; +using ::android::ResTable_config; using configuration::Abi; using configuration::AndroidSdk; using configuration::Artifact; @@ -38,7 +35,7 @@ using configuration::DeviceFeature; using configuration::GlTexture; using configuration::Locale; using configuration::AndroidManifest; -using testing::ElementsAre; +using ::testing::ElementsAre; using xml::Element; using xml::NodeCast; @@ -67,18 +64,15 @@ constexpr const char* kValidConfig = R"(<?xml version="1.0" encoding="utf-8" ?> <screen-density>xxxhdpi</screen-density> </screen-density-group> <locale-group label="europe"> - <locale lang="en"/> - <locale lang="es"/> - <locale lang="fr"/> - <locale lang="de"/> + <locale>en</locale> + <locale>es</locale> + <locale>fr</locale> + <locale>de</locale> </locale-group> <locale-group label="north-america"> - <locale lang="en"/> - <locale lang="es" region="MX"/> - <locale lang="fr" region="CA"/> - </locale-group> - <locale-group label="all"> - <locale/> + <locale>en</locale> + <locale>es-rMX</locale> + <locale>fr-rCA</locale> </locale-group> <android-sdk-group label="19"> <android-sdk @@ -156,10 +150,9 @@ TEST_F(ConfigurationParserTest, ValidateFile) { EXPECT_EQ(3ul, value.screen_density_groups["large"].size()); EXPECT_EQ(6ul, value.screen_density_groups["alldpi"].size()); - EXPECT_EQ(3ul, value.locale_groups.size()); + EXPECT_EQ(2ul, value.locale_groups.size()); EXPECT_EQ(4ul, value.locale_groups["europe"].size()); EXPECT_EQ(3ul, value.locale_groups["north-america"].size()); - EXPECT_EQ(1ul, value.locale_groups["all"].size()); EXPECT_EQ(1ul, value.android_sdk_groups.size()); EXPECT_EQ(1ul, value.android_sdk_groups["19"].size()); @@ -192,13 +185,13 @@ TEST_F(ConfigurationParserTest, ArtifactAction) { auto doc = test::BuildXmlDom(xml); PostProcessingConfiguration config; - bool ok = artifact_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); + bool ok = artifact_handler_(&config, NodeCast<Element>(doc->root.get()), &diag_); ASSERT_TRUE(ok); EXPECT_EQ(1ul, config.artifacts.size()); auto& artifact = config.artifacts.front(); - EXPECT_EQ("", artifact.name); // TODO: make this fail. + EXPECT_FALSE(artifact.name); // TODO: make this fail. EXPECT_EQ("arm", artifact.abi_group.value()); EXPECT_EQ("large", artifact.screen_density_group.value()); EXPECT_EQ("europe", artifact.locale_group.value()); @@ -298,10 +291,10 @@ TEST_F(ConfigurationParserTest, ScreenDensityGroupAction) { TEST_F(ConfigurationParserTest, LocaleGroupAction) { static constexpr const char* xml = R"xml( <locale-group label="europe"> - <locale lang="en"/> - <locale lang="es"/> - <locale lang="fr"/> - <locale lang="de"/> + <locale>en</locale> + <locale>es</locale> + <locale>fr</locale> + <locale>de</locale> </locale-group>)xml"; auto doc = test::BuildXmlDom(xml); @@ -313,16 +306,12 @@ TEST_F(ConfigurationParserTest, LocaleGroupAction) { ASSERT_EQ(1ul, config.locale_groups.size()); ASSERT_EQ(1u, config.locale_groups.count("europe")); - auto& out = config.locale_groups["europe"]; + const auto& out = config.locale_groups["europe"]; - Locale en; - en.lang = std::string("en"); - Locale es; - es.lang = std::string("es"); - Locale fr; - fr.lang = std::string("fr"); - Locale de; - de.lang = std::string("de"); + ConfigDescription en = test::ParseConfigOrDie("en"); + ConfigDescription es = test::ParseConfigOrDie("es"); + ConfigDescription fr = test::ParseConfigOrDie("fr"); + ConfigDescription de = test::ParseConfigOrDie("de"); ASSERT_THAT(out, ElementsAre(en, es, fr, de)); } @@ -425,16 +414,36 @@ TEST(ArtifactTest, Simple) { Artifact x86; x86.abi_group = {"x86"}; - auto x86_result = x86.ToArtifactName("something.{abi}.apk", &diag); + auto x86_result = x86.ToArtifactName("something.${abi}.apk", "", &diag); ASSERT_TRUE(x86_result); EXPECT_EQ(x86_result.value(), "something.x86.apk"); Artifact arm; arm.abi_group = {"armeabi-v7a"}; - auto arm_result = arm.ToArtifactName("app.{abi}.apk", &diag); - ASSERT_TRUE(arm_result); - EXPECT_EQ(arm_result.value(), "app.armeabi-v7a.apk"); + { + auto arm_result = arm.ToArtifactName("app.${abi}.apk", "", &diag); + ASSERT_TRUE(arm_result); + EXPECT_EQ(arm_result.value(), "app.armeabi-v7a.apk"); + } + + { + auto arm_result = arm.ToArtifactName("app.${abi}.apk", "different_name.apk", &diag); + ASSERT_TRUE(arm_result); + EXPECT_EQ(arm_result.value(), "app.armeabi-v7a.apk"); + } + + { + auto arm_result = arm.ToArtifactName("${basename}.${abi}.apk", "app.apk", &diag); + ASSERT_TRUE(arm_result); + EXPECT_EQ(arm_result.value(), "app.armeabi-v7a.apk"); + } + + { + auto arm_result = arm.ToArtifactName("app.${abi}.${ext}", "app.apk", &diag); + ASSERT_TRUE(arm_result); + EXPECT_EQ(arm_result.value(), "app.armeabi-v7a.apk"); + } } TEST(ArtifactTest, Complex) { @@ -447,10 +456,40 @@ TEST(ArtifactTest, Complex) { artifact.locale_group = {"en-AU"}; artifact.android_sdk_group = {"26"}; - auto result = - artifact.ToArtifactName("app.{density}_{locale}_{feature}_{gl}.sdk{sdk}.{abi}.apk", &diag); - ASSERT_TRUE(result); - EXPECT_EQ(result.value(), "app.ldpi_en-AU_df1_glx1.sdk26.mips64.apk"); + { + auto result = artifact.ToArtifactName( + "app.${density}_${locale}_${feature}_${gl}.sdk${sdk}.${abi}.apk", "", &diag); + ASSERT_TRUE(result); + EXPECT_EQ(result.value(), "app.ldpi_en-AU_df1_glx1.sdk26.mips64.apk"); + } + + { + auto result = artifact.ToArtifactName( + "app.${density}_${locale}_${feature}_${gl}.sdk${sdk}.${abi}.apk", "app.apk", &diag); + ASSERT_TRUE(result); + EXPECT_EQ(result.value(), "app.ldpi_en-AU_df1_glx1.sdk26.mips64.apk"); + } + + { + auto result = artifact.ToArtifactName( + "${basename}.${density}_${locale}_${feature}_${gl}.sdk${sdk}.${abi}.apk", "app.apk", &diag); + ASSERT_TRUE(result); + EXPECT_EQ(result.value(), "app.ldpi_en-AU_df1_glx1.sdk26.mips64.apk"); + } + + { + auto result = artifact.ToArtifactName( + "app.${density}_${locale}_${feature}_${gl}.sdk${sdk}.${abi}.${ext}", "app.apk", &diag); + ASSERT_TRUE(result); + EXPECT_EQ(result.value(), "app.ldpi_en-AU_df1_glx1.sdk26.mips64.apk"); + } + + { + auto result = artifact.ToArtifactName( + "${basename}.${density}_${locale}_${feature}_${gl}.sdk${sdk}.${abi}", "app.apk", &diag); + ASSERT_TRUE(result); + EXPECT_EQ(result.value(), "app.ldpi_en-AU_df1_glx1.sdk26.mips64.apk"); + } } TEST(ArtifactTest, Missing) { @@ -458,16 +497,20 @@ TEST(ArtifactTest, Missing) { Artifact x86; x86.abi_group = {"x86"}; - EXPECT_FALSE(x86.ToArtifactName("something.{density}.apk", &diag)); - EXPECT_FALSE(x86.ToArtifactName("something.apk", &diag)); + EXPECT_FALSE(x86.ToArtifactName("something.${density}.apk", "", &diag)); + EXPECT_FALSE(x86.ToArtifactName("something.apk", "", &diag)); + EXPECT_FALSE(x86.ToArtifactName("something.${density}.apk", "something.apk", &diag)); + EXPECT_FALSE(x86.ToArtifactName("something.apk", "something.apk", &diag)); } TEST(ArtifactTest, Empty) { StdErrDiagnostics diag; Artifact artifact; - EXPECT_FALSE(artifact.ToArtifactName("something.{density}.apk", &diag)); - EXPECT_TRUE(artifact.ToArtifactName("something.apk", &diag)); + EXPECT_FALSE(artifact.ToArtifactName("something.${density}.apk", "", &diag)); + EXPECT_TRUE(artifact.ToArtifactName("something.apk", "", &diag)); + EXPECT_FALSE(artifact.ToArtifactName("something.${density}.apk", "something.apk", &diag)); + EXPECT_TRUE(artifact.ToArtifactName("something.apk", "something.apk", &diag)); } TEST(ArtifactTest, Repeated) { @@ -475,8 +518,9 @@ TEST(ArtifactTest, Repeated) { Artifact artifact; artifact.screen_density_group = {"mdpi"}; - EXPECT_TRUE(artifact.ToArtifactName("something.{density}.apk", &diag)); - EXPECT_FALSE(artifact.ToArtifactName("something.{density}.{density}.apk", &diag)); + ASSERT_TRUE(artifact.ToArtifactName("something.${density}.apk", "", &diag)); + EXPECT_FALSE(artifact.ToArtifactName("something.${density}.${density}.apk", "", &diag)); + ASSERT_TRUE(artifact.ToArtifactName("something.${density}.apk", "something.apk", &diag)); } TEST(ArtifactTest, Nesting) { @@ -484,36 +528,36 @@ TEST(ArtifactTest, Nesting) { Artifact x86; x86.abi_group = {"x86"}; - EXPECT_FALSE(x86.ToArtifactName("something.{abi{density}}.apk", &diag)); + EXPECT_FALSE(x86.ToArtifactName("something.${abi${density}}.apk", "", &diag)); - const Maybe<std::string>& name = x86.ToArtifactName("something.{abi{abi}}.apk", &diag); - EXPECT_TRUE(name); - EXPECT_EQ(name.value(), "something.{abix86}.apk"); + const Maybe<std::string>& name = x86.ToArtifactName("something.${abi${abi}}.apk", "", &diag); + ASSERT_TRUE(name); + EXPECT_EQ(name.value(), "something.${abix86}.apk"); } TEST(ArtifactTest, Recursive) { StdErrDiagnostics diag; Artifact artifact; - artifact.device_feature_group = {"{gl}"}; + artifact.device_feature_group = {"${gl}"}; artifact.gl_texture_group = {"glx1"}; - EXPECT_FALSE(artifact.ToArtifactName("app.{feature}.{gl}.apk", &diag)); + EXPECT_FALSE(artifact.ToArtifactName("app.${feature}.${gl}.apk", "", &diag)); artifact.device_feature_group = {"df1"}; - artifact.gl_texture_group = {"{feature}"}; + artifact.gl_texture_group = {"${feature}"}; { - const auto& result = artifact.ToArtifactName("app.{feature}.{gl}.apk", &diag); - EXPECT_TRUE(result); - EXPECT_EQ(result.value(), "app.df1.{feature}.apk"); + const auto& result = artifact.ToArtifactName("app.${feature}.${gl}.apk", "", &diag); + ASSERT_TRUE(result); + EXPECT_EQ(result.value(), "app.df1.${feature}.apk"); } // This is an invalid case, but should be the only possible case due to the ordering of // replacement. - artifact.device_feature_group = {"{gl}"}; + artifact.device_feature_group = {"${gl}"}; artifact.gl_texture_group = {"glx1"}; { - const auto& result = artifact.ToArtifactName("app.{feature}.apk", &diag); - EXPECT_TRUE(result); + const auto& result = artifact.ToArtifactName("app.${feature}.apk", "", &diag); + ASSERT_TRUE(result); EXPECT_EQ(result.value(), "app.glx1.apk"); } } diff --git a/tools/aapt2/filter/ConfigFilter.h b/tools/aapt2/filter/ConfigFilter.h index 3f1341684912..ebb81519dceb 100644 --- a/tools/aapt2/filter/ConfigFilter.h +++ b/tools/aapt2/filter/ConfigFilter.h @@ -38,13 +38,9 @@ class IConfigFilter { }; /** - * Implements config axis matching. An axis is one component of a configuration, - * like screen - * density or locale. If an axis is specified in the filter, and the axis is - * specified in - * the configuration to match, they must be compatible. Otherwise the - * configuration to match is - * accepted. + * Implements config axis matching. An axis is one component of a configuration, like screen density + * or locale. If an axis is specified in the filter, and the axis is specified in the configuration + * to match, they must be compatible. Otherwise the configuration to match is accepted. * * Used when handling "-c" options. */ diff --git a/tools/aapt2/filter/Filter_test.cpp b/tools/aapt2/filter/Filter_test.cpp index fb75a4b4d7c1..db2e69fc90d3 100644 --- a/tools/aapt2/filter/Filter_test.cpp +++ b/tools/aapt2/filter/Filter_test.cpp @@ -25,22 +25,16 @@ namespace aapt { namespace { -TEST(FilterChainTest, EmptyChain) { +TEST(FilterTest, FilterChain) { FilterChain chain; ASSERT_TRUE(chain.Keep("some/random/path")); -} -TEST(FilterChainTest, SingleFilter) { - FilterChain chain; chain.AddFilter(util::make_unique<PrefixFilter>("keep/")); ASSERT_FALSE(chain.Keep("removed/path")); ASSERT_TRUE(chain.Keep("keep/path/1")); ASSERT_TRUE(chain.Keep("keep/path/2")); -} -TEST(FilterChainTest, MultipleFilters) { - FilterChain chain; chain.AddFilter(util::make_unique<PrefixFilter>("keep/")); chain.AddFilter(util::make_unique<PrefixFilter>("keep/really/")); diff --git a/tools/aapt2/flatten/TableFlattener.cpp b/tools/aapt2/flatten/TableFlattener.cpp index e5993a65366d..14b776b1bd99 100644 --- a/tools/aapt2/flatten/TableFlattener.cpp +++ b/tools/aapt2/flatten/TableFlattener.cpp @@ -133,7 +133,7 @@ class MapFlattenVisitor : public RawValueVisitor { } void Visit(Array* array) override { - for (auto& item : array->items) { + for (auto& item : array->elements) { ResTable_map* out_entry = buffer_->NextBlock<ResTable_map>(); FlattenValue(item.get(), out_entry); out_entry->value.size = util::HostToDevice16(sizeof(out_entry->value)); diff --git a/tools/aapt2/flatten/XmlFlattener.cpp b/tools/aapt2/flatten/XmlFlattener.cpp index 331ef784a7da..b3b308a29fc5 100644 --- a/tools/aapt2/flatten/XmlFlattener.cpp +++ b/tools/aapt2/flatten/XmlFlattener.cpp @@ -38,12 +38,10 @@ namespace { constexpr uint32_t kLowPriority = 0xffffffffu; -static bool cmp_xml_attribute_by_id(const xml::Attribute* a, - const xml::Attribute* b) { +static bool cmp_xml_attribute_by_id(const xml::Attribute* a, const xml::Attribute* b) { if (a->compiled_attribute && a->compiled_attribute.value().id) { if (b->compiled_attribute && b->compiled_attribute.value().id) { - return a->compiled_attribute.value().id.value() < - b->compiled_attribute.value().id.value(); + return a->compiled_attribute.value().id.value() < b->compiled_attribute.value().id.value(); } return true; } else if (!b->compiled_attribute) { @@ -75,17 +73,6 @@ class XmlFlattenerVisitor : public xml::Visitor { XmlFlattenerVisitor(BigBuffer* buffer, XmlFlattenerOptions options) : buffer_(buffer), options_(options) {} - void Visit(xml::Namespace* node) override { - if (node->namespace_uri == xml::kSchemaTools) { - // Skip dedicated tools namespace. - xml::Visitor::Visit(node); - } else { - WriteNamespace(node, android::RES_XML_START_NAMESPACE_TYPE); - xml::Visitor::Visit(node); - WriteNamespace(node, android::RES_XML_END_NAMESPACE_TYPE); - } - } - void Visit(xml::Text* node) override { if (util::TrimWhitespace(node->text).empty()) { // Skip whitespace only text nodes. @@ -93,8 +80,7 @@ class XmlFlattenerVisitor : public xml::Visitor { } ChunkWriter writer(buffer_); - ResXMLTree_node* flat_node = - writer.StartChunk<ResXMLTree_node>(RES_XML_CDATA_TYPE); + ResXMLTree_node* flat_node = writer.StartChunk<ResXMLTree_node>(RES_XML_CDATA_TYPE); flat_node->lineNumber = util::HostToDevice32(node->line_number); flat_node->comment.index = util::HostToDevice32(-1); @@ -109,6 +95,13 @@ class XmlFlattenerVisitor : public xml::Visitor { } void Visit(xml::Element* node) override { + for (const xml::NamespaceDecl& decl : node->namespace_decls) { + // Skip dedicated tools namespace. + if (decl.uri != xml::kSchemaTools) { + WriteNamespace(decl, android::RES_XML_START_NAMESPACE_TYPE); + } + } + { ChunkWriter start_writer(buffer_); ResXMLTree_node* flat_node = @@ -116,19 +109,15 @@ class XmlFlattenerVisitor : public xml::Visitor { flat_node->lineNumber = util::HostToDevice32(node->line_number); flat_node->comment.index = util::HostToDevice32(-1); - ResXMLTree_attrExt* flat_elem = - start_writer.NextBlock<ResXMLTree_attrExt>(); + ResXMLTree_attrExt* flat_elem = start_writer.NextBlock<ResXMLTree_attrExt>(); - // A missing namespace must be null, not an empty string. Otherwise the - // runtime complains. + // A missing namespace must be null, not an empty string. Otherwise the runtime complains. AddString(node->namespace_uri, kLowPriority, &flat_elem->ns, true /* treat_empty_string_as_null */); - AddString(node->name, kLowPriority, &flat_elem->name, - true /* treat_empty_string_as_null */); + AddString(node->name, kLowPriority, &flat_elem->name, true /* treat_empty_string_as_null */); flat_elem->attributeStart = util::HostToDevice16(sizeof(*flat_elem)); - flat_elem->attributeSize = - util::HostToDevice16(sizeof(ResXMLTree_attribute)); + flat_elem->attributeSize = util::HostToDevice16(sizeof(ResXMLTree_attribute)); WriteAttributes(node, flat_elem, &start_writer); @@ -144,14 +133,20 @@ class XmlFlattenerVisitor : public xml::Visitor { flat_end_node->lineNumber = util::HostToDevice32(node->line_number); flat_end_node->comment.index = util::HostToDevice32(-1); - ResXMLTree_endElementExt* flat_end_elem = - end_writer.NextBlock<ResXMLTree_endElementExt>(); + ResXMLTree_endElementExt* flat_end_elem = end_writer.NextBlock<ResXMLTree_endElementExt>(); AddString(node->namespace_uri, kLowPriority, &flat_end_elem->ns, true /* treat_empty_string_as_null */); AddString(node->name, kLowPriority, &flat_end_elem->name); end_writer.Finish(); } + + for (auto iter = node->namespace_decls.rbegin(); iter != node->namespace_decls.rend(); ++iter) { + // Skip dedicated tools namespace. + if (iter->uri != xml::kSchemaTools) { + WriteNamespace(*iter, android::RES_XML_END_NAMESPACE_TYPE); + } + } } private: @@ -173,16 +168,16 @@ class XmlFlattenerVisitor : public xml::Visitor { string_refs.push_back(StringFlattenDest{ref, dest}); } - void WriteNamespace(xml::Namespace* node, uint16_t type) { + void WriteNamespace(const xml::NamespaceDecl& decl, uint16_t type) { ChunkWriter writer(buffer_); ResXMLTree_node* flatNode = writer.StartChunk<ResXMLTree_node>(type); - flatNode->lineNumber = util::HostToDevice32(node->line_number); + flatNode->lineNumber = util::HostToDevice32(decl.line_number); flatNode->comment.index = util::HostToDevice32(-1); ResXMLTree_namespaceExt* flat_ns = writer.NextBlock<ResXMLTree_namespaceExt>(); - AddString(node->namespace_prefix, kLowPriority, &flat_ns->prefix); - AddString(node->namespace_uri, kLowPriority, &flat_ns->uri); + AddString(decl.prefix, kLowPriority, &flat_ns->prefix); + AddString(decl.uri, kLowPriority, &flat_ns->uri); writer.Finish(); } diff --git a/tools/aapt2/integration-tests/NamespaceTest/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/Android.mk new file mode 100644 index 000000000000..6361f9b8ae7d --- /dev/null +++ b/tools/aapt2/integration-tests/NamespaceTest/Android.mk @@ -0,0 +1,2 @@ +LOCAL_PATH := $(call my-dir) +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/tools/aapt2/integration-tests/NamespaceTest/App/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/App/Android.mk new file mode 100644 index 000000000000..6ed07b0c5c73 --- /dev/null +++ b/tools/aapt2/integration-tests/NamespaceTest/App/Android.mk @@ -0,0 +1,29 @@ +# +# Copyright (C) 2017 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_USE_AAPT2 := true +LOCAL_AAPT_NAMESPACES := true +LOCAL_PACKAGE_NAME := AaptTestNamespace_App +LOCAL_MODULE_TAGS := tests +LOCAL_SRC_FILES := $(call all-java-files-under,src) +LOCAL_STATIC_ANDROID_LIBRARIES := \ + AaptTestNamespace_LibOne \ + AaptTestNamespace_LibTwo +LOCAL_AAPT_FLAGS := -v +include $(BUILD_PACKAGE) diff --git a/tools/aapt2/integration-tests/NamespaceTest/App/AndroidManifest.xml b/tools/aapt2/integration-tests/NamespaceTest/App/AndroidManifest.xml new file mode 100644 index 000000000000..6398a83ea1d2 --- /dev/null +++ b/tools/aapt2/integration-tests/NamespaceTest/App/AndroidManifest.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.aapt.namespace.app"> + + <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="26"/> + + <application android:theme="@style/AppTheme" android:label="@string/app_name"> + <activity android:name=".MainActivity"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> +</manifest> diff --git a/tools/aapt2/integration-tests/NamespaceTest/App/res/layout/activity_main.xml b/tools/aapt2/integration-tests/NamespaceTest/App/res/layout/activity_main.xml new file mode 100644 index 000000000000..19bfd942a5bd --- /dev/null +++ b/tools/aapt2/integration-tests/NamespaceTest/App/res/layout/activity_main.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:libone="http://schemas.android.com/apk/res/com.android.aapt.namespace.libone" + xmlns:libtwo="http://schemas.android.com/apk/res/com.android.aapt.namespace.libtwo" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <com.android.aapt.namespace.libtwo.TextView + android:id="@+id/textview" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerInParent="@bool/always_true" + android:text="@libone:string/textview_text" + libtwo:textview_attr="?libone:theme_attr" /> +</RelativeLayout>
\ No newline at end of file diff --git a/tools/aapt2/integration-tests/NamespaceTest/App/res/values/values.xml b/tools/aapt2/integration-tests/NamespaceTest/App/res/values/values.xml new file mode 100644 index 000000000000..1b80d9542881 --- /dev/null +++ b/tools/aapt2/integration-tests/NamespaceTest/App/res/values/values.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<resources> + <string name="app_name">Namespace App</string> + <bool name="always_true">true</bool> + + <style name="AppTheme" parent="com.android.aapt.namespace.libone:style/Theme"> + <item name="android:colorPrimary">#3F51B5</item> + <item name="android:colorPrimaryDark">#303F9F</item> + <item name="android:colorAccent">#FF4081</item> + <item name="com.android.aapt.namespace.libone:theme_attr"> + @com.android.aapt.namespace.libtwo:string/public_string + </item> + </style> +</resources>
\ No newline at end of file diff --git a/tools/aapt2/integration-tests/NamespaceTest/App/src/com/android/aapt/namespace/app/MainActivity.java b/tools/aapt2/integration-tests/NamespaceTest/App/src/com/android/aapt/namespace/app/MainActivity.java new file mode 100644 index 000000000000..fcb4c3c12f81 --- /dev/null +++ b/tools/aapt2/integration-tests/NamespaceTest/App/src/com/android/aapt/namespace/app/MainActivity.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.aapt.namespace.app; + +import android.app.Activity; +import android.os.Bundle; +import android.widget.Toast; + +public class MainActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + com.android.aapt.namespace.libtwo.TextView tv = findViewById(R.id.textview); + + + + Toast.makeText(this, tv.getTextViewAttr(), Toast.LENGTH_LONG).show(); + } +} diff --git a/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk new file mode 100644 index 000000000000..b1cac68dae7a --- /dev/null +++ b/tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk @@ -0,0 +1,28 @@ +# +# Copyright (C) 2017 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_USE_AAPT2 := true +LOCAL_AAPT_NAMESPACES := true +LOCAL_MODULE := AaptTestNamespace_LibOne +LOCAL_MODULE_TAGS := tests +LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res + +# We need this to retain the R.java generated for this library. +LOCAL_JAR_EXCLUDE_FILES := none +include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/packages/SystemUI/res/drawable/car_qs_background_primary.xml b/tools/aapt2/integration-tests/NamespaceTest/LibOne/AndroidManifest.xml index 0f77987bb7ce..70b4b226624b 100644 --- a/packages/SystemUI/res/drawable/car_qs_background_primary.xml +++ b/tools/aapt2/integration-tests/NamespaceTest/LibOne/AndroidManifest.xml @@ -13,8 +13,9 @@ See the License for the specific language governing permissions and limitations under the License. --> -<inset xmlns:android="http://schemas.android.com/apk/res/android"> - <shape> - <solid android:color="?android:attr/colorPrimaryDark"/> - </shape> -</inset> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.aapt.namespace.libone"> + + <uses-sdk android:minSdkVersion="21" /> +</manifest> diff --git a/tools/aapt2/integration-tests/NamespaceTest/LibOne/res/values/values.xml b/tools/aapt2/integration-tests/NamespaceTest/LibOne/res/values/values.xml new file mode 100644 index 000000000000..d2dcea0c0b1e --- /dev/null +++ b/tools/aapt2/integration-tests/NamespaceTest/LibOne/res/values/values.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<resources> + <public type="string" name="textview_text" /> + <string name="textview_text">LibOne\'s textview_text string!</string> + + <public type="attr" name="theme_attr" /> + <attr name="theme_attr" format="string" /> + + <public type="style" name="Theme" /> + <style name="Theme" parent="android:Theme.Material.Light.DarkActionBar"> + <item name="theme_attr">[Please override with your own value]</item> + </style> +</resources>
\ No newline at end of file diff --git a/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk b/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk new file mode 100644 index 000000000000..dc16d1bbb420 --- /dev/null +++ b/tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk @@ -0,0 +1,29 @@ +# +# Copyright (C) 2017 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_USE_AAPT2 := true +LOCAL_AAPT_NAMESPACES := true +LOCAL_MODULE := AaptTestNamespace_LibTwo +LOCAL_MODULE_TAGS := tests +LOCAL_SRC_FILES := $(call all-java-files-under,src) +LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res + +# We need this to retain the R.java generated for this library. +LOCAL_JAR_EXCLUDE_FILES := none +include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/packages/SystemUI/res/layout/car_qs_detail.xml b/tools/aapt2/integration-tests/NamespaceTest/LibTwo/AndroidManifest.xml index 5703f7ee5a4e..32944a9b8f0b 100644 --- a/packages/SystemUI/res/layout/car_qs_detail.xml +++ b/tools/aapt2/integration-tests/NamespaceTest/LibTwo/AndroidManifest.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2017 The Android Open Source Project +<!-- Copyright (C) 2017 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,13 +13,9 @@ See the License for the specific language governing permissions and limitations under the License. --> -<!-- Extends FrameLayout --> -<com.android.systemui.qs.car.CarQSDetail - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:background="@drawable/qs_detail_background" - android:paddingBottom="8dp" - android:visibility="gone"> -</com.android.systemui.qs.car.CarQSDetail> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.aapt.namespace.libtwo"> + + <uses-sdk android:minSdkVersion="21" /> +</manifest> diff --git a/tools/aapt2/integration-tests/NamespaceTest/LibTwo/res/values/values.xml b/tools/aapt2/integration-tests/NamespaceTest/LibTwo/res/values/values.xml new file mode 100644 index 000000000000..0c5f5d8d55e0 --- /dev/null +++ b/tools/aapt2/integration-tests/NamespaceTest/LibTwo/res/values/values.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<resources> + <public type="string" name="public_string" /> + <string name="public_string">LibTwo\'s public string!</string> + + <public type="attr" name="textview_attr" /> + <attr name="textview_attr" format="string" /> + + <declare-styleable name="TextView"> + <attr name="textview_attr" /> + </declare-styleable> +</resources>
\ No newline at end of file diff --git a/tools/aapt2/integration-tests/NamespaceTest/LibTwo/src/com/android/aapt/namespace/libtwo/TextView.java b/tools/aapt2/integration-tests/NamespaceTest/LibTwo/src/com/android/aapt/namespace/libtwo/TextView.java new file mode 100644 index 000000000000..0f8024e58797 --- /dev/null +++ b/tools/aapt2/integration-tests/NamespaceTest/LibTwo/src/com/android/aapt/namespace/libtwo/TextView.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.aapt.namespace.libtwo; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; + +public class TextView extends android.widget.TextView { + + private String mTextViewAttr; + + public TextView(Context context) { + this(context, null); + } + + public TextView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public TextView(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + + public TextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + + final TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.TextView, + 0, 0); + try { + mTextViewAttr = ta.getString(R.styleable.TextView_textview_attr); + } finally { + ta.recycle(); + } + } + + public String getTextViewAttr() { + return mTextViewAttr; + } +} diff --git a/tools/aapt2/integration-tests/StaticLibTest/Android.mk b/tools/aapt2/integration-tests/StaticLibTest/Android.mk new file mode 100644 index 000000000000..6361f9b8ae7d --- /dev/null +++ b/tools/aapt2/integration-tests/StaticLibTest/Android.mk @@ -0,0 +1,2 @@ +LOCAL_PATH := $(call my-dir) +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/tools/aapt2/integration-tests/AppOne/Android.mk b/tools/aapt2/integration-tests/StaticLibTest/App/Android.mk index 38bd5b5e3275..4d0c01d565a5 100644 --- a/tools/aapt2/integration-tests/AppOne/Android.mk +++ b/tools/aapt2/integration-tests/StaticLibTest/App/Android.mk @@ -18,12 +18,12 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_USE_AAPT2 := true -LOCAL_PACKAGE_NAME := AaptTestAppOne +LOCAL_PACKAGE_NAME := AaptTestStaticLib_App LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := $(call all-java-files-under,src) LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets $(LOCAL_PATH)/assets2 LOCAL_STATIC_ANDROID_LIBRARIES := \ - AaptTestStaticLibOne \ - AaptTestStaticLibTwo + AaptTestStaticLib_LibOne \ + AaptTestStaticLib_LibTwo LOCAL_AAPT_FLAGS := --no-version-vectors --no-version-transitions include $(BUILD_PACKAGE) diff --git a/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml b/tools/aapt2/integration-tests/StaticLibTest/App/AndroidManifest.xml index a5f202dd22fc..a5f202dd22fc 100644 --- a/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml +++ b/tools/aapt2/integration-tests/StaticLibTest/App/AndroidManifest.xml diff --git a/tools/aapt2/integration-tests/AppOne/assets/subdir/subsubdir/test.txt b/tools/aapt2/integration-tests/StaticLibTest/App/assets/subdir/subsubdir/test.txt index 125194943ec8..125194943ec8 100644 --- a/tools/aapt2/integration-tests/AppOne/assets/subdir/subsubdir/test.txt +++ b/tools/aapt2/integration-tests/StaticLibTest/App/assets/subdir/subsubdir/test.txt diff --git a/tools/aapt2/integration-tests/AppOne/assets/test.txt b/tools/aapt2/integration-tests/StaticLibTest/App/assets/test.txt index 88266de2b4d4..88266de2b4d4 100644 --- a/tools/aapt2/integration-tests/AppOne/assets/test.txt +++ b/tools/aapt2/integration-tests/StaticLibTest/App/assets/test.txt diff --git a/tools/aapt2/integration-tests/AppOne/assets2/new.txt b/tools/aapt2/integration-tests/StaticLibTest/App/assets2/new.txt index f4963a95503a..f4963a95503a 100644 --- a/tools/aapt2/integration-tests/AppOne/assets2/new.txt +++ b/tools/aapt2/integration-tests/StaticLibTest/App/assets2/new.txt diff --git a/tools/aapt2/integration-tests/AppOne/assets2/test.txt b/tools/aapt2/integration-tests/StaticLibTest/App/assets2/test.txt index 5d8b36c0d52d..5d8b36c0d52d 100644 --- a/tools/aapt2/integration-tests/AppOne/assets2/test.txt +++ b/tools/aapt2/integration-tests/StaticLibTest/App/assets2/test.txt diff --git a/tools/aapt2/integration-tests/AppOne/res/drawable/cheap_transparency.png b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/cheap_transparency.png Binary files differindex 0522a9979db9..0522a9979db9 100644 --- a/tools/aapt2/integration-tests/AppOne/res/drawable/cheap_transparency.png +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/cheap_transparency.png diff --git a/tools/aapt2/integration-tests/AppOne/res/drawable/complex.9.png b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/complex.9.png Binary files differindex baf9fff13ab5..baf9fff13ab5 100644 --- a/tools/aapt2/integration-tests/AppOne/res/drawable/complex.9.png +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/complex.9.png diff --git a/tools/aapt2/integration-tests/AppOne/res/drawable/icon.png b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/icon.png Binary files differindex 4bff9b900643..4bff9b900643 100644 --- a/tools/aapt2/integration-tests/AppOne/res/drawable/icon.png +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/icon.png diff --git a/tools/aapt2/integration-tests/AppOne/res/drawable/image.xml b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/image.xml index 6132a75d85d0..6132a75d85d0 100644 --- a/tools/aapt2/integration-tests/AppOne/res/drawable/image.xml +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/image.xml diff --git a/tools/aapt2/integration-tests/AppOne/res/drawable/outline_8x8.9.png b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/outline_8x8.9.png Binary files differindex 7b331e16fcbd..7b331e16fcbd 100644 --- a/tools/aapt2/integration-tests/AppOne/res/drawable/outline_8x8.9.png +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/outline_8x8.9.png diff --git a/tools/aapt2/integration-tests/AppOne/res/drawable/round_rect_off_center_outline_32x16.9.png b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/round_rect_off_center_outline_32x16.9.png Binary files differindex 0ec6c70a2b9f..0ec6c70a2b9f 100644 --- a/tools/aapt2/integration-tests/AppOne/res/drawable/round_rect_off_center_outline_32x16.9.png +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/round_rect_off_center_outline_32x16.9.png diff --git a/tools/aapt2/integration-tests/AppOne/res/drawable/round_rect_outline_32x16.9.png b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/round_rect_outline_32x16.9.png Binary files differindex e05708a089a3..e05708a089a3 100644 --- a/tools/aapt2/integration-tests/AppOne/res/drawable/round_rect_outline_32x16.9.png +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/round_rect_outline_32x16.9.png diff --git a/tools/aapt2/integration-tests/AppOne/res/drawable/test.9.png b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/test.9.png Binary files differindex 33daa117ea9d..33daa117ea9d 100644 --- a/tools/aapt2/integration-tests/AppOne/res/drawable/test.9.png +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/test.9.png diff --git a/tools/aapt2/integration-tests/AppOne/res/drawable/transparent_3x3.9.png b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/transparent_3x3.9.png Binary files differindex a11377a0d670..a11377a0d670 100644 --- a/tools/aapt2/integration-tests/AppOne/res/drawable/transparent_3x3.9.png +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/transparent_3x3.9.png diff --git a/tools/aapt2/integration-tests/AppOne/res/drawable/transparent_optical_bounds_3x3.9.png b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/transparent_optical_bounds_3x3.9.png Binary files differindex 6803e4243484..6803e4243484 100644 --- a/tools/aapt2/integration-tests/AppOne/res/drawable/transparent_optical_bounds_3x3.9.png +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/transparent_optical_bounds_3x3.9.png diff --git a/tools/aapt2/integration-tests/AppOne/res/drawable/white_3x3.9.png b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/white_3x3.9.png Binary files differindex 1a3731bbc8b8..1a3731bbc8b8 100644 --- a/tools/aapt2/integration-tests/AppOne/res/drawable/white_3x3.9.png +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/white_3x3.9.png diff --git a/tools/aapt2/integration-tests/AppOne/res/drawable/white_optical_bounds_3x3.9.png b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/white_optical_bounds_3x3.9.png Binary files differindex 489ace292e1f..489ace292e1f 100644 --- a/tools/aapt2/integration-tests/AppOne/res/drawable/white_optical_bounds_3x3.9.png +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/drawable/white_optical_bounds_3x3.9.png diff --git a/tools/aapt2/integration-tests/AppOne/res/font/myfont-italic.ttf b/tools/aapt2/integration-tests/StaticLibTest/App/res/font/myfont-italic.ttf index e69de29bb2d1..e69de29bb2d1 100644 --- a/tools/aapt2/integration-tests/AppOne/res/font/myfont-italic.ttf +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/font/myfont-italic.ttf diff --git a/tools/aapt2/integration-tests/AppOne/res/font/myfont-normal.ttf b/tools/aapt2/integration-tests/StaticLibTest/App/res/font/myfont-normal.ttf index e69de29bb2d1..e69de29bb2d1 100644 --- a/tools/aapt2/integration-tests/AppOne/res/font/myfont-normal.ttf +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/font/myfont-normal.ttf diff --git a/tools/aapt2/integration-tests/AppOne/res/font/myfont.xml b/tools/aapt2/integration-tests/StaticLibTest/App/res/font/myfont.xml index 1fb67914894e..1fb67914894e 100644 --- a/tools/aapt2/integration-tests/AppOne/res/font/myfont.xml +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/font/myfont.xml diff --git a/tools/aapt2/integration-tests/AppOne/res/layout-v21/main.xml b/tools/aapt2/integration-tests/StaticLibTest/App/res/layout-v21/main.xml index 9f5a4a85cbcf..724bfe4a9536 100644 --- a/tools/aapt2/integration-tests/AppOne/res/layout-v21/main.xml +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/layout-v21/main.xml @@ -15,7 +15,6 @@ --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:support="http://schemas.android.com/apk/res/android.appcompat" android:id="@+id/view" android:layout_width="match_parent" android:layout_height="wrap_content"> diff --git a/tools/aapt2/integration-tests/AppOne/res/layout/main.xml b/tools/aapt2/integration-tests/StaticLibTest/App/res/layout/main.xml index ab1a251a7d56..aaa884bf7084 100644 --- a/tools/aapt2/integration-tests/AppOne/res/layout/main.xml +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/layout/main.xml @@ -15,7 +15,6 @@ --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:support="http://schemas.android.com/apk/res/android.appcompat" android:id="@+id/view" android:layout_width="match_parent" android:layout_height="wrap_content"> diff --git a/tools/aapt2/integration-tests/AppOne/res/layout/special.xml b/tools/aapt2/integration-tests/StaticLibTest/App/res/layout/special.xml index 28c85ca92019..28c85ca92019 100644 --- a/tools/aapt2/integration-tests/AppOne/res/layout/special.xml +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/layout/special.xml diff --git a/tools/aapt2/integration-tests/AppOne/res/navigation/home.xml b/tools/aapt2/integration-tests/StaticLibTest/App/res/navigation/home.xml index ade271d60ab6..ade271d60ab6 100644 --- a/tools/aapt2/integration-tests/AppOne/res/navigation/home.xml +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/navigation/home.xml diff --git a/tools/aapt2/integration-tests/AppOne/res/raw/test.txt b/tools/aapt2/integration-tests/StaticLibTest/App/res/raw/test.txt index b14df6442ea5..b14df6442ea5 100644 --- a/tools/aapt2/integration-tests/AppOne/res/raw/test.txt +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/raw/test.txt diff --git a/tools/aapt2/integration-tests/AppOne/res/transition/transition_set.xml b/tools/aapt2/integration-tests/StaticLibTest/App/res/transition/transition_set.xml index e10e6c2f53da..e10e6c2f53da 100644 --- a/tools/aapt2/integration-tests/AppOne/res/transition/transition_set.xml +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/transition/transition_set.xml diff --git a/tools/aapt2/integration-tests/AppOne/res/values-v4/styles.xml b/tools/aapt2/integration-tests/StaticLibTest/App/res/values-v4/styles.xml index d8c11e210eda..d8c11e210eda 100644 --- a/tools/aapt2/integration-tests/AppOne/res/values-v4/styles.xml +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/values-v4/styles.xml diff --git a/tools/aapt2/integration-tests/AppOne/res/values/colors.xml b/tools/aapt2/integration-tests/StaticLibTest/App/res/values/colors.xml index 4df5077051d2..4df5077051d2 100644 --- a/tools/aapt2/integration-tests/AppOne/res/values/colors.xml +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/values/colors.xml diff --git a/tools/aapt2/integration-tests/AppOne/res/values/styles.xml b/tools/aapt2/integration-tests/StaticLibTest/App/res/values/styles.xml index 19d96c0809db..a088e5d0e1a2 100644 --- a/tools/aapt2/integration-tests/AppOne/res/values/styles.xml +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/values/styles.xml @@ -14,7 +14,7 @@ limitations under the License. --> -<resources xmlns:lib="http://schemas.android.com/apk/res/android.appcompat"> +<resources> <style name="App"> <item name="android:background">@color/primary</item> <item name="android:colorPrimary">@color/primary</item> diff --git a/tools/aapt2/integration-tests/AppOne/res/values/test.xml b/tools/aapt2/integration-tests/StaticLibTest/App/res/values/test.xml index 2c9e8b877565..2c9e8b877565 100644 --- a/tools/aapt2/integration-tests/AppOne/res/values/test.xml +++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/values/test.xml diff --git a/tools/aapt2/integration-tests/AppOne/src/com/android/aapt/app/one/AppOne.java b/tools/aapt2/integration-tests/StaticLibTest/App/src/com/android/aapt/app/one/AppOne.java index 472b35a781fe..472b35a781fe 100644 --- a/tools/aapt2/integration-tests/AppOne/src/com/android/aapt/app/one/AppOne.java +++ b/tools/aapt2/integration-tests/StaticLibTest/App/src/com/android/aapt/app/one/AppOne.java diff --git a/tools/aapt2/integration-tests/StaticLibOne/Android.mk b/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.mk index 0b7129aa0d38..0c828b80b3b3 100644 --- a/tools/aapt2/integration-tests/StaticLibOne/Android.mk +++ b/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.mk @@ -18,11 +18,11 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_USE_AAPT2 := true -LOCAL_MODULE := AaptTestStaticLibOne +LOCAL_MODULE := AaptTestStaticLib_LibOne LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := $(call all-java-files-under,src) LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res -# We need this to compile the Java sources of AaptTestStaticLibTwo using javac. +# We need this to compile the Java sources of AaptTestStaticLib_LibTwo using javac. LOCAL_JAR_EXCLUDE_FILES := none include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/tools/aapt2/integration-tests/StaticLibOne/AndroidManifest.xml b/tools/aapt2/integration-tests/StaticLibTest/LibOne/AndroidManifest.xml index 705047e71300..705047e71300 100644 --- a/tools/aapt2/integration-tests/StaticLibOne/AndroidManifest.xml +++ b/tools/aapt2/integration-tests/StaticLibTest/LibOne/AndroidManifest.xml diff --git a/tools/aapt2/integration-tests/StaticLibOne/res/layout/layout.xml b/tools/aapt2/integration-tests/StaticLibTest/LibOne/res/layout/layout.xml index 683c91cd9cf5..683c91cd9cf5 100644 --- a/tools/aapt2/integration-tests/StaticLibOne/res/layout/layout.xml +++ b/tools/aapt2/integration-tests/StaticLibTest/LibOne/res/layout/layout.xml diff --git a/tools/aapt2/integration-tests/StaticLibOne/res/values/values.xml b/tools/aapt2/integration-tests/StaticLibTest/LibOne/res/values/values.xml index b4dc90b3e640..b4dc90b3e640 100644 --- a/tools/aapt2/integration-tests/StaticLibOne/res/values/values.xml +++ b/tools/aapt2/integration-tests/StaticLibTest/LibOne/res/values/values.xml diff --git a/tools/aapt2/integration-tests/StaticLibOne/src/com/android/aapt/staticlib/one/StaticLibOne.java b/tools/aapt2/integration-tests/StaticLibTest/LibOne/src/com/android/aapt/staticlib/one/StaticLibOne.java index cf48f67056cf..cf48f67056cf 100644 --- a/tools/aapt2/integration-tests/StaticLibOne/src/com/android/aapt/staticlib/one/StaticLibOne.java +++ b/tools/aapt2/integration-tests/StaticLibTest/LibOne/src/com/android/aapt/staticlib/one/StaticLibOne.java diff --git a/tools/aapt2/integration-tests/StaticLibTwo/Android.mk b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.mk index 8b6eb41b08cd..538d5251b203 100644 --- a/tools/aapt2/integration-tests/StaticLibTwo/Android.mk +++ b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.mk @@ -18,10 +18,10 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_USE_AAPT2 := true -LOCAL_MODULE := AaptTestStaticLibTwo +LOCAL_MODULE := AaptTestStaticLib_LibTwo LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := $(call all-java-files-under,src) LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res -LOCAL_SHARED_ANDROID_LIBRARIES := AaptTestStaticLibOne +LOCAL_SHARED_ANDROID_LIBRARIES := AaptTestStaticLib_LibOne include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/tools/aapt2/integration-tests/StaticLibTwo/AndroidManifest.xml b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/AndroidManifest.xml index 28f069932452..28f069932452 100644 --- a/tools/aapt2/integration-tests/StaticLibTwo/AndroidManifest.xml +++ b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/AndroidManifest.xml diff --git a/tools/aapt2/integration-tests/StaticLibTwo/res/drawable/vector.xml b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/res/drawable/vector.xml index dd5979f7e838..dd5979f7e838 100644 --- a/tools/aapt2/integration-tests/StaticLibTwo/res/drawable/vector.xml +++ b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/res/drawable/vector.xml diff --git a/tools/aapt2/integration-tests/StaticLibTwo/res/layout/layout_two.xml b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/res/layout/layout_two.xml index ba9830708eb0..ba9830708eb0 100644 --- a/tools/aapt2/integration-tests/StaticLibTwo/res/layout/layout_two.xml +++ b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/res/layout/layout_two.xml diff --git a/tools/aapt2/integration-tests/StaticLibTwo/res/values/values.xml b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/res/values/values.xml index 97bb2a53d9f6..97bb2a53d9f6 100644 --- a/tools/aapt2/integration-tests/StaticLibTwo/res/values/values.xml +++ b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/res/values/values.xml diff --git a/tools/aapt2/integration-tests/StaticLibTwo/src/com/android/aapt/staticlib/two/StaticLibTwo.java b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/src/com/android/aapt/staticlib/two/StaticLibTwo.java index 7110dcdd017a..7110dcdd017a 100644 --- a/tools/aapt2/integration-tests/StaticLibTwo/src/com/android/aapt/staticlib/two/StaticLibTwo.java +++ b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/src/com/android/aapt/staticlib/two/StaticLibTwo.java diff --git a/tools/aapt2/java/ClassDefinition.cpp b/tools/aapt2/java/ClassDefinition.cpp index 45130a4d7681..6ad0dd68cb6a 100644 --- a/tools/aapt2/java/ClassDefinition.cpp +++ b/tools/aapt2/java/ClassDefinition.cpp @@ -39,6 +39,17 @@ void MethodDefinition::WriteToStream(const StringPiece& prefix, bool final, *out << prefix << "}"; } +ClassDefinition::Result ClassDefinition::AddMember(std::unique_ptr<ClassMember> member) { + Result result = Result::kAdded; + auto iter = members_.find(member); + if (iter != members_.end()) { + members_.erase(iter); + result = Result::kOverridden; + } + members_.insert(std::move(member)); + return result; +} + bool ClassDefinition::empty() const { for (const std::unique_ptr<ClassMember>& member : members_) { if (!member->empty()) { diff --git a/tools/aapt2/java/ClassDefinition.h b/tools/aapt2/java/ClassDefinition.h index ca76421390d6..6c4bcad83d2a 100644 --- a/tools/aapt2/java/ClassDefinition.h +++ b/tools/aapt2/java/ClassDefinition.h @@ -18,6 +18,7 @@ #define AAPT_JAVA_CLASSDEFINITION_H #include <ostream> +#include <set> #include <string> #include "android-base/macros.h" @@ -37,10 +38,14 @@ class ClassMember { public: virtual ~ClassMember() = default; - AnnotationProcessor* GetCommentBuilder() { return &processor_; } + AnnotationProcessor* GetCommentBuilder() { + return &processor_; + } virtual bool empty() const = 0; + virtual const std::string& GetName() const = 0; + // Writes the class member to the out stream. Subclasses should derive this method // to write their own data. Call this base method from the subclass to write out // this member's comments/annotations. @@ -57,7 +62,13 @@ class PrimitiveMember : public ClassMember { PrimitiveMember(const android::StringPiece& name, const T& val) : name_(name.to_string()), val_(val) {} - bool empty() const override { return false; } + bool empty() const override { + return false; + } + + const std::string& GetName() const override { + return name_; + } void WriteToStream(const android::StringPiece& prefix, bool final, std::ostream* out) const override { @@ -83,7 +94,13 @@ class PrimitiveMember<std::string> : public ClassMember { PrimitiveMember(const android::StringPiece& name, const std::string& val) : name_(name.to_string()), val_(val) {} - bool empty() const override { return false; } + bool empty() const override { + return false; + } + + const std::string& GetName() const override { + return name_; + } void WriteToStream(const android::StringPiece& prefix, bool final, std::ostream* out) const override { @@ -109,9 +126,17 @@ class PrimitiveArrayMember : public ClassMember { public: explicit PrimitiveArrayMember(const android::StringPiece& name) : name_(name.to_string()) {} - void AddElement(const T& val) { elements_.push_back(val); } + void AddElement(const T& val) { + elements_.push_back(val); + } - bool empty() const override { return false; } + bool empty() const override { + return false; + } + + const std::string& GetName() const override { + return name_; + } void WriteToStream(const android::StringPiece& prefix, bool final, std::ostream* out) const override { @@ -154,6 +179,11 @@ class MethodDefinition : public ClassMember { // formatting may be broken. void AppendStatement(const android::StringPiece& statement); + // Not quite the same as a name, but good enough. + const std::string& GetName() const override { + return signature_; + } + // Even if the method is empty, we always want to write the method signature. bool empty() const override { return false; } @@ -175,19 +205,34 @@ class ClassDefinition : public ClassMember { ClassDefinition(const android::StringPiece& name, ClassQualifier qualifier, bool createIfEmpty) : name_(name.to_string()), qualifier_(qualifier), create_if_empty_(createIfEmpty) {} - void AddMember(std::unique_ptr<ClassMember> member) { - members_.push_back(std::move(member)); - } + enum class Result { + kAdded, + kOverridden, + }; + + Result AddMember(std::unique_ptr<ClassMember> member); bool empty() const override; + + const std::string& GetName() const override { + return name_; + } + void WriteToStream(const android::StringPiece& prefix, bool final, std::ostream* out) const override; private: + struct ClassMemberCompare { + using T = std::unique_ptr<ClassMember>; + bool operator()(const T& a, const T& b) const { + return a->GetName() < b->GetName(); + } + }; + std::string name_; ClassQualifier qualifier_; bool create_if_empty_; - std::vector<std::unique_ptr<ClassMember>> members_; + std::set<std::unique_ptr<ClassMember>, ClassMemberCompare> members_; DISALLOW_COPY_AND_ASSIGN(ClassDefinition); }; diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp index 44fa0f19a0e5..8da9106aa8d7 100644 --- a/tools/aapt2/java/JavaClassGenerator.cpp +++ b/tools/aapt2/java/JavaClassGenerator.cpp @@ -480,7 +480,7 @@ Maybe<std::string> JavaClassGenerator::UnmangleResource(const StringPiece& packa if (NameMangler::Unmangle(&unmangled_name, &unmangled_package)) { // The entry name was mangled, and we successfully unmangled it. // Check that we want to emit this symbol. - if (package_name != unmangled_package) { + if (package_name_to_generate != unmangled_package) { // Skip the entry if it doesn't belong to the package we're writing. return {}; } @@ -579,8 +579,7 @@ bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, continue; } - // Stay consistent with AAPT and generate an empty type class if the R class - // is public. + // Stay consistent with AAPT and generate an empty type class if the R class is public. const bool force_creation_if_empty = (options_.types == JavaClassGeneratorOptions::SymbolTypes::kPublic); diff --git a/tools/aapt2/java/ManifestClassGenerator.cpp b/tools/aapt2/java/ManifestClassGenerator.cpp index 4ef32c92dd84..c4b36176aa71 100644 --- a/tools/aapt2/java/ManifestClassGenerator.cpp +++ b/tools/aapt2/java/ManifestClassGenerator.cpp @@ -68,7 +68,10 @@ static bool WriteSymbol(const Source& source, IDiagnostics* diag, xml::Element* util::make_unique<StringMember>(result.value(), attr->value); string_member->GetCommentBuilder()->AppendComment(el->comment); - class_def->AddMember(std::move(string_member)); + if (class_def->AddMember(std::move(string_member)) == ClassDefinition::Result::kOverridden) { + diag->Warn(DiagMessage(source.WithLine(el->line_number)) + << "duplicate definitions of '" << result.value() << "', overriding previous"); + } return true; } diff --git a/tools/aapt2/java/ManifestClassGenerator_test.cpp b/tools/aapt2/java/ManifestClassGenerator_test.cpp index c744e9bd4fc9..ada563409d19 100644 --- a/tools/aapt2/java/ManifestClassGenerator_test.cpp +++ b/tools/aapt2/java/ManifestClassGenerator_test.cpp @@ -121,6 +121,21 @@ TEST(ManifestClassGeneratorTest, CommentsAndAnnotationsArePresent) { EXPECT_THAT(actual, HasSubstr(expected_test)); } +// This is bad but part of public API behaviour so we need to preserve it. +TEST(ManifestClassGeneratorTest, LastSeenPermissionWithSameLeafNameTakesPrecedence) { + std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); + std::unique_ptr<xml::XmlResource> manifest = test::BuildXmlDom(R"( + <manifest xmlns:android="http://schemas.android.com/apk/res/android"> + <permission android:name="android.permission.ACCESS_INTERNET" /> + <permission android:name="com.android.aapt.test.ACCESS_INTERNET" /> + </manifest>)"); + + std::string actual; + ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), &actual)); + EXPECT_THAT(actual, HasSubstr("ACCESS_INTERNET=\"com.android.aapt.test.ACCESS_INTERNET\";")); + EXPECT_THAT(actual, Not(HasSubstr("ACCESS_INTERNET=\"android.permission.ACCESS_INTERNET\";"))); +} + static ::testing::AssertionResult GetManifestClassText(IAaptContext* context, xml::XmlResource* res, std::string* out_str) { std::unique_ptr<ClassDefinition> manifest_class = diff --git a/tools/aapt2/java/ProguardRules.cpp b/tools/aapt2/java/ProguardRules.cpp index 5f61faeeebe7..10c46101123c 100644 --- a/tools/aapt2/java/ProguardRules.cpp +++ b/tools/aapt2/java/ProguardRules.cpp @@ -29,18 +29,12 @@ namespace proguard { class BaseVisitor : public xml::Visitor { public: - BaseVisitor(const Source& source, KeepSet* keep_set) - : source_(source), keep_set_(keep_set) {} + using xml::Visitor::Visit; - virtual void Visit(xml::Text*) override{}; - - virtual void Visit(xml::Namespace* node) override { - for (const auto& child : node->children) { - child->Accept(this); - } + BaseVisitor(const Source& source, KeepSet* keep_set) : source_(source), keep_set_(keep_set) { } - virtual void Visit(xml::Element* node) override { + void Visit(xml::Element* node) override { if (!node->namespace_uri.empty()) { Maybe<xml::ExtractedPackage> maybe_package = xml::ExtractPackageFromNamespace(node->namespace_uri); @@ -78,10 +72,10 @@ class BaseVisitor : public xml::Visitor { class LayoutVisitor : public BaseVisitor { public: - LayoutVisitor(const Source& source, KeepSet* keep_set) - : BaseVisitor(source, keep_set) {} + LayoutVisitor(const Source& source, KeepSet* keep_set) : BaseVisitor(source, keep_set) { + } - virtual void Visit(xml::Element* node) override { + void Visit(xml::Element* node) override { bool check_class = false; bool check_name = false; if (node->namespace_uri.empty()) { @@ -119,7 +113,7 @@ class MenuVisitor : public BaseVisitor { MenuVisitor(const Source& source, KeepSet* keep_set) : BaseVisitor(source, keep_set) { } - virtual void Visit(xml::Element* node) override { + void Visit(xml::Element* node) override { if (node->namespace_uri.empty() && node->name == "item") { for (const auto& attr : node->attributes) { if (attr.namespace_uri == xml::kSchemaAndroid) { @@ -142,10 +136,10 @@ class MenuVisitor : public BaseVisitor { class XmlResourceVisitor : public BaseVisitor { public: - XmlResourceVisitor(const Source& source, KeepSet* keep_set) - : BaseVisitor(source, keep_set) {} + XmlResourceVisitor(const Source& source, KeepSet* keep_set) : BaseVisitor(source, keep_set) { + } - virtual void Visit(xml::Element* node) override { + void Visit(xml::Element* node) override { bool check_fragment = false; if (node->namespace_uri.empty()) { check_fragment = @@ -169,13 +163,12 @@ class XmlResourceVisitor : public BaseVisitor { class TransitionVisitor : public BaseVisitor { public: - TransitionVisitor(const Source& source, KeepSet* keep_set) - : BaseVisitor(source, keep_set) {} + TransitionVisitor(const Source& source, KeepSet* keep_set) : BaseVisitor(source, keep_set) { + } - virtual void Visit(xml::Element* node) override { + void Visit(xml::Element* node) override { bool check_class = - node->namespace_uri.empty() && - (node->name == "transition" || node->name == "pathMotion"); + node->namespace_uri.empty() && (node->name == "transition" || node->name == "pathMotion"); if (check_class) { xml::Attribute* attr = node->FindAttribute({}, "class"); if (attr && util::IsJavaClassName(attr->value)) { @@ -195,7 +188,7 @@ class ManifestVisitor : public BaseVisitor { ManifestVisitor(const Source& source, KeepSet* keep_set, bool main_dex_only) : BaseVisitor(source, keep_set), main_dex_only_(main_dex_only) {} - virtual void Visit(xml::Element* node) override { + void Visit(xml::Element* node) override { if (node->namespace_uri.empty()) { bool get_name = false; if (node->name == "manifest") { @@ -205,18 +198,15 @@ class ManifestVisitor : public BaseVisitor { } } else if (node->name == "application") { get_name = true; - xml::Attribute* attr = - node->FindAttribute(xml::kSchemaAndroid, "backupAgent"); + xml::Attribute* attr = node->FindAttribute(xml::kSchemaAndroid, "backupAgent"); if (attr) { - Maybe<std::string> result = - util::GetFullyQualifiedClassName(package_, attr->value); + Maybe<std::string> result = util::GetFullyQualifiedClassName(package_, attr->value); if (result) { AddClass(node->line_number, result.value()); } } if (main_dex_only_) { - xml::Attribute* default_process = - node->FindAttribute(xml::kSchemaAndroid, "process"); + xml::Attribute* default_process = node->FindAttribute(xml::kSchemaAndroid, "process"); if (default_process) { default_process_ = default_process->value; } @@ -226,8 +216,7 @@ class ManifestVisitor : public BaseVisitor { get_name = true; if (main_dex_only_) { - xml::Attribute* component_process = - node->FindAttribute(xml::kSchemaAndroid, "process"); + xml::Attribute* component_process = node->FindAttribute(xml::kSchemaAndroid, "process"); const std::string& process = component_process ? component_process->value : default_process_; @@ -242,8 +231,7 @@ class ManifestVisitor : public BaseVisitor { get_name = attr != nullptr; if (get_name) { - Maybe<std::string> result = - util::GetFullyQualifiedClassName(package_, attr->value); + Maybe<std::string> result = util::GetFullyQualifiedClassName(package_, attr->value); if (result) { AddClass(node->line_number, result.value()); } @@ -261,8 +249,7 @@ class ManifestVisitor : public BaseVisitor { std::string default_process_; }; -bool CollectProguardRulesForManifest(const Source& source, - xml::XmlResource* res, KeepSet* keep_set, +bool CollectProguardRulesForManifest(const Source& source, xml::XmlResource* res, KeepSet* keep_set, bool main_dex_only) { ManifestVisitor visitor(source, keep_set, main_dex_only); if (res->root) { @@ -272,8 +259,7 @@ bool CollectProguardRulesForManifest(const Source& source, return false; } -bool CollectProguardRules(const Source& source, xml::XmlResource* res, - KeepSet* keep_set) { +bool CollectProguardRules(const Source& source, xml::XmlResource* res, KeepSet* keep_set) { if (!res->root) { return false; } @@ -321,8 +307,7 @@ bool WriteKeepSet(std::ostream* out, const KeepSet& keep_set) { for (const Source& source : entry.second) { *out << "# Referenced at " << source << "\n"; } - *out << "-keepclassmembers class * { *** " << entry.first << "(...); }\n" - << std::endl; + *out << "-keepclassmembers class * { *** " << entry.first << "(...); }\n" << std::endl; } return true; } diff --git a/tools/aapt2/link/Linkers.h b/tools/aapt2/link/Linkers.h index 5527f9092c87..3c9c4767b3d1 100644 --- a/tools/aapt2/link/Linkers.h +++ b/tools/aapt2/link/Linkers.h @@ -21,6 +21,7 @@ #include <unordered_set> #include "android-base/macros.h" +#include "androidfw/StringPiece.h" #include "Resource.h" #include "SdkConstants.h" @@ -33,18 +34,15 @@ class ResourceTable; class ResourceEntry; struct ConfigDescription; -/** - * Defines the location in which a value exists. This determines visibility of - * other package's private symbols. - */ +// Defines the context in which a resource value is defined. Most resources are defined with the +// implicit package name of their compilation context. Understanding the package name of a resource +// allows to determine visibility of other symbols which may or may not have their packages defined. struct CallSite { - ResourceNameRef resource; + std::string package; }; -/** - * Determines whether a versioned resource should be created. If a versioned - * resource already exists, it takes precedence. - */ +// Determines whether a versioned resource should be created. If a versioned resource already +// exists, it takes precedence. bool ShouldGenerateVersionedResource(const ResourceEntry* entry, const ConfigDescription& config, const ApiVersion sdk_version_to_generate); @@ -62,39 +60,26 @@ class AutoVersioner : public IResourceTableConsumer { DISALLOW_COPY_AND_ASSIGN(AutoVersioner); }; -/** - * If any attribute resource values are defined as public, this consumer will - * move all private - * attribute resource values to a private ^private-attr type, avoiding backwards - * compatibility - * issues with new apps running on old platforms. - * - * The Android platform ignores resource attributes it doesn't recognize, so an - * app developer can - * use new attributes in their layout XML files without worrying about - * versioning. This assumption - * actually breaks on older platforms. OEMs may add private attributes that are - * used internally. - * AAPT originally assigned all private attributes IDs immediately proceeding - * the public attributes' - * IDs. - * - * This means that on a newer Android platform, an ID previously assigned to a - * private attribute - * may end up assigned to a public attribute. - * - * App developers assume using the newer attribute is safe on older platforms - * because it will - * be ignored. Instead, the platform thinks the new attribute is an older, - * private attribute and - * will interpret it as such. This leads to unintended styling and exceptions - * thrown due to - * unexpected types. - * - * By moving the private attributes to a completely different type, this ID - * conflict will never - * occur. - */ +// If any attribute resource values are defined as public, this consumer will move all private +// attribute resource values to a private ^private-attr type, avoiding backwards compatibility +// issues with new apps running on old platforms. +// +// The Android platform ignores resource attributes it doesn't recognize, so an app developer can +// use new attributes in their layout XML files without worrying about versioning. This assumption +// actually breaks on older platforms. OEMs may add private attributes that are used internally. +// AAPT originally assigned all private attributes IDs immediately proceeding the public attributes' +// IDs. +// +// This means that on a newer Android platform, an ID previously assigned to a private attribute +// may end up assigned to a public attribute. +// +// App developers assume using the newer attribute is safe on older platforms because it will +// be ignored. Instead, the platform thinks the new attribute is an older, private attribute and +// will interpret it as such. This leads to unintended styling and exceptions thrown due to +// unexpected types. +// +// By moving the private attributes to a completely different type, this ID conflict will never +// occur. class PrivateAttributeMover : public IResourceTableConsumer { public: PrivateAttributeMover() = default; @@ -126,14 +111,10 @@ class ProductFilter : public IResourceTableConsumer { std::unordered_set<std::string> products_; }; -/** - * Removes namespace nodes and URI information from the XmlResource. - * - * Once an XmlResource is processed by this consumer, it is no longer able to - * have its attributes - * parsed. As such, this XmlResource must have already been processed by - * XmlReferenceLinker. - */ +// Removes namespace nodes and URI information from the XmlResource. +// +// Once an XmlResource is processed by this consumer, it is no longer able to have its attributes +// parsed. As such, this XmlResource must have already been processed by XmlReferenceLinker. class XmlNamespaceRemover : public IXmlResourceConsumer { public: explicit XmlNamespaceRemover(bool keep_uris = false) : keep_uris_(keep_uris){}; @@ -146,11 +127,8 @@ class XmlNamespaceRemover : public IXmlResourceConsumer { bool keep_uris_; }; -/** - * Resolves attributes in the XmlResource and compiles string values to resource - * values. - * Once an XmlResource is processed by this linker, it is ready to be flattened. - */ +// Resolves attributes in the XmlResource and compiles string values to resource values. +// Once an XmlResource is processed by this linker, it is ready to be flattened. class XmlReferenceLinker : public IXmlResourceConsumer { public: XmlReferenceLinker() = default; diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp index a0ffefad1e1c..6fb1793d90ed 100644 --- a/tools/aapt2/link/ManifestFixer.cpp +++ b/tools/aapt2/link/ManifestFixer.cpp @@ -293,6 +293,7 @@ bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor, manifest_action["instrumentation"]["meta-data"] = meta_data_action; manifest_action["original-package"]; + manifest_action["overlay"]; manifest_action["protected-broadcast"]; manifest_action["uses-permission"]; manifest_action["uses-permission-sdk-23"]; diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp index 80edb352f42c..da7f410b8b08 100644 --- a/tools/aapt2/link/ManifestFixer_test.cpp +++ b/tools/aapt2/link/ManifestFixer_test.cpp @@ -122,7 +122,7 @@ TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) { xml::Element* el; xml::Attribute* attr; - el = xml::FindRootElement(doc.get()); + el = doc->root.get(); ASSERT_NE(nullptr, el); el = el->FindChild({}, "uses-sdk"); ASSERT_NE(nullptr, el); @@ -141,7 +141,7 @@ TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) { options); ASSERT_NE(nullptr, doc); - el = xml::FindRootElement(doc.get()); + el = doc->root.get(); ASSERT_NE(nullptr, el); el = el->FindChild({}, "uses-sdk"); ASSERT_NE(nullptr, el); @@ -160,7 +160,7 @@ TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) { options); ASSERT_NE(nullptr, doc); - el = xml::FindRootElement(doc.get()); + el = doc->root.get(); ASSERT_NE(nullptr, el); el = el->FindChild({}, "uses-sdk"); ASSERT_NE(nullptr, el); @@ -177,7 +177,7 @@ TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) { options); ASSERT_NE(nullptr, doc); - el = xml::FindRootElement(doc.get()); + el = doc->root.get(); ASSERT_NE(nullptr, el); el = el->FindChild({}, "uses-sdk"); ASSERT_NE(nullptr, el); @@ -199,7 +199,7 @@ TEST_F(ManifestFixerTest, UsesSdkMustComeBeforeApplication) { options); ASSERT_NE(nullptr, doc); - xml::Element* manifest_el = xml::FindRootElement(doc.get()); + xml::Element* manifest_el = doc->root.get(); ASSERT_NE(nullptr, manifest_el); ASSERT_EQ("manifest", manifest_el->name); @@ -248,7 +248,7 @@ TEST_F(ManifestFixerTest, RenameManifestPackageAndFullyQualifyClasses) { options); ASSERT_NE(nullptr, doc); - xml::Element* manifestEl = xml::FindRootElement(doc.get()); + xml::Element* manifestEl = doc->root.get(); ASSERT_NE(nullptr, manifestEl); xml::Attribute* attr = nullptr; @@ -297,7 +297,7 @@ TEST_F(ManifestFixerTest, options); ASSERT_NE(nullptr, doc); - xml::Element* manifest_el = xml::FindRootElement(doc.get()); + xml::Element* manifest_el = doc->root.get(); ASSERT_NE(nullptr, manifest_el); xml::Element* instrumentation_el = @@ -321,7 +321,7 @@ TEST_F(ManifestFixerTest, UseDefaultVersionNameAndCode) { options); ASSERT_NE(nullptr, doc); - xml::Element* manifest_el = xml::FindRootElement(doc.get()); + xml::Element* manifest_el = doc->root.get(); ASSERT_NE(nullptr, manifest_el); xml::Attribute* attr = @@ -344,7 +344,7 @@ TEST_F(ManifestFixerTest, EnsureManifestAttributesAreTyped) { Verify("<manifest package=\"android\" coreApp=\"true\" />"); ASSERT_NE(nullptr, doc); - xml::Element* el = xml::FindRootElement(doc.get()); + xml::Element* el = doc->root.get(); ASSERT_NE(nullptr, el); EXPECT_EQ("manifest", el->name); diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp index 414e56eb5dcc..71e828b039e1 100644 --- a/tools/aapt2/link/ReferenceLinker.cpp +++ b/tools/aapt2/link/ReferenceLinker.cpp @@ -30,23 +30,18 @@ #include "util/Util.h" #include "xml/XmlUtil.h" -using android::StringPiece; +using ::android::StringPiece; namespace aapt { namespace { -/** - * The ReferenceLinkerVisitor will follow all references and make sure they - * point - * to resources that actually exist, either in the local resource table, or as - * external - * symbols. Once the target resource has been found, the ID of the resource will - * be assigned - * to the reference object. - * - * NOTE: All of the entries in the ResourceTable must be assigned IDs. - */ +// The ReferenceLinkerVisitor will follow all references and make sure they point +// to resources that actually exist, either in the local resource table, or as external +// symbols. Once the target resource has been found, the ID of the resource will be assigned +// to the reference object. +// +// NOTE: All of the entries in the ResourceTable must be assigned IDs. class ReferenceLinkerVisitor : public ValueVisitor { public: using ValueVisitor::Visit; @@ -65,14 +60,9 @@ class ReferenceLinkerVisitor : public ValueVisitor { } } - /** - * We visit the Style specially because during this phase, values of - * attributes are - * all RawString values. Now that we are expected to resolve all symbols, we - * can - * lookup the attributes to find out which types are allowed for the - * attributes' values. - */ + // We visit the Style specially because during this phase, values of attributes are + // all RawString values. Now that we are expected to resolve all symbols, we can + // lookup the attributes to find out which types are allowed for the attributes' values. void Visit(Style* style) override { if (style->parent) { Visit(&style->parent.value()); @@ -81,28 +71,21 @@ class ReferenceLinkerVisitor : public ValueVisitor { for (Style::Entry& entry : style->entries) { std::string err_str; - // Transform the attribute reference so that it is using the fully - // qualified package - // name. This will also mark the reference as being able to see private - // resources if - // there was a '*' in the reference or if the package came from the - // private namespace. + // Transform the attribute reference so that it is using the fully qualified package + // name. This will also mark the reference as being able to see private resources if + // there was a '*' in the reference or if the package came from the private namespace. Reference transformed_reference = entry.key; - TransformReferenceFromNamespace(package_decls_, - context_->GetCompilationPackage(), - &transformed_reference); + ResolvePackage(package_decls_, &transformed_reference); - // Find the attribute in the symbol table and check if it is visible from - // this callsite. + // Find the attribute in the symbol table and check if it is visible from this callsite. const SymbolTable::Symbol* symbol = ReferenceLinker::ResolveAttributeCheckVisibility( transformed_reference, callsite_, symbols_, &err_str); if (symbol) { - // Assign our style key the correct ID. - // The ID may not exist. + // Assign our style key the correct ID. The ID may not exist. entry.key.id = symbol->id; - // Try to convert the value to a more specific, typed value based on the - // attribute it is set to. + // Try to convert the value to a more specific, typed value based on the attribute it is + // set to. entry.value = ParseValueWithAttribute(std::move(entry.value), symbol->attribute.get()); // Link/resolve the final value (mostly if it's a reference). @@ -115,8 +98,8 @@ class ReferenceLinkerVisitor : public ValueVisitor { // The actual type of this item is incompatible with the attribute. DiagMessage msg(entry.key.GetSource()); - // Call the matches method again, this time with a DiagMessage so we - // fill in the actual error message. + // Call the matches method again, this time with a DiagMessage so we fill in the actual + // error message. symbol->attribute->Matches(*entry.value, &msg); context_->GetDiagnostics()->Error(msg); error_ = true; @@ -125,7 +108,7 @@ class ReferenceLinkerVisitor : public ValueVisitor { } else { DiagMessage msg(entry.key.GetSource()); msg << "style attribute '"; - ReferenceLinker::WriteResourceName(&msg, entry.key, transformed_reference); + ReferenceLinker::WriteResourceName(entry.key, callsite_, package_decls_, &msg); msg << "' " << err_str; context_->GetDiagnostics()->Error(msg); error_ = true; @@ -133,17 +116,15 @@ class ReferenceLinkerVisitor : public ValueVisitor { } } - bool HasError() { return error_; } + bool HasError() { + return error_; + } private: DISALLOW_COPY_AND_ASSIGN(ReferenceLinkerVisitor); - /** - * Transform a RawString value into a more specific, appropriate value, based - * on the - * Attribute. If a non RawString value is passed in, this is an identity - * transform. - */ + // Transform a RawString value into a more specific, appropriate value, based on the + // Attribute. If a non RawString value is passed in, this is an identity transform. std::unique_ptr<Item> ParseValueWithAttribute(std::unique_ptr<Item> value, const Attribute* attr) { if (RawString* raw_string = ValueCast<RawString>(value.get())) { @@ -178,11 +159,9 @@ class EmptyDeclStack : public xml::IPackageDeclStack { public: EmptyDeclStack() = default; - Maybe<xml::ExtractedPackage> TransformPackageAlias( - const StringPiece& alias, - const StringPiece& local_package) const override { + Maybe<xml::ExtractedPackage> TransformPackageAlias(const StringPiece& alias) const override { if (alias.empty()) { - return xml::ExtractedPackage{local_package.to_string(), true /* private */}; + return xml::ExtractedPackage{{}, true /*private*/}; } return {}; } @@ -191,32 +170,44 @@ class EmptyDeclStack : public xml::IPackageDeclStack { DISALLOW_COPY_AND_ASSIGN(EmptyDeclStack); }; -} // namespace +// The symbol is visible if it is public, or if the reference to it is requesting private access +// or if the callsite comes from the same package. +bool IsSymbolVisible(const SymbolTable::Symbol& symbol, const Reference& ref, + const CallSite& callsite) { + if (symbol.is_public || ref.private_reference) { + return true; + } -/** - * The symbol is visible if it is public, or if the reference to it is - * requesting private access - * or if the callsite comes from the same package. - */ -bool ReferenceLinker::IsSymbolVisible(const SymbolTable::Symbol& symbol, - const Reference& ref, - const CallSite& callsite) { - if (!symbol.is_public && !ref.private_reference) { - if (ref.name) { - return callsite.resource.package == ref.name.value().package; - } else if (ref.id && symbol.id) { - return ref.id.value().package_id() == symbol.id.value().package_id(); - } else { - return false; + if (ref.name) { + const ResourceName& name = ref.name.value(); + if (name.package.empty()) { + // If the symbol was found, and the package is empty, that means it was found in the local + // scope, which is always visible (private local). + return true; } + + // The symbol is visible if the reference is local to the same package it is defined in. + return callsite.package == name.package; } - return true; + + if (ref.id && symbol.id) { + return ref.id.value().package_id() == symbol.id.value().package_id(); + } + return false; } +} // namespace + const SymbolTable::Symbol* ReferenceLinker::ResolveSymbol(const Reference& reference, + const CallSite& callsite, SymbolTable* symbols) { if (reference.name) { - return symbols->FindByName(reference.name.value()); + const ResourceName& name = reference.name.value(); + if (name.package.empty()) { + // Use the callsite's package name if no package name was defined. + return symbols->FindByName(ResourceName(callsite.package, name.type, name.entry)); + } + return symbols->FindByName(name); } else if (reference.id) { return symbols->FindById(reference.id.value()); } else { @@ -228,7 +219,7 @@ const SymbolTable::Symbol* ReferenceLinker::ResolveSymbolCheckVisibility(const R const CallSite& callsite, SymbolTable* symbols, std::string* out_error) { - const SymbolTable::Symbol* symbol = ResolveSymbol(reference, symbols); + const SymbolTable::Symbol* symbol = ResolveSymbol(reference, callsite, symbols); if (!symbol) { if (out_error) *out_error = "not found"; return nullptr; @@ -274,24 +265,62 @@ Maybe<xml::AaptAttribute> ReferenceLinker::CompileXmlAttribute(const Reference& return xml::AaptAttribute(*symbol->attribute, symbol->id); } -void ReferenceLinker::WriteResourceName(DiagMessage* out_msg, - const Reference& orig, - const Reference& transformed) { +void ReferenceLinker::WriteResourceName(const Reference& ref, const CallSite& callsite, + const xml::IPackageDeclStack* decls, DiagMessage* out_msg) { CHECK(out_msg != nullptr); + if (!ref.name) { + *out_msg << ref.id.value(); + return; + } - if (orig.name) { - *out_msg << orig.name.value(); - if (transformed.name.value() != orig.name.value()) { - *out_msg << " (aka " << transformed.name.value() << ")"; - } - } else { - *out_msg << orig.id.value(); + *out_msg << ref.name.value(); + + Reference fully_qualified = ref; + xml::ResolvePackage(decls, &fully_qualified); + + ResourceName& full_name = fully_qualified.name.value(); + if (full_name.package.empty()) { + full_name.package = callsite.package; + } + + if (full_name != ref.name.value()) { + *out_msg << " (aka " << full_name << ")"; + } +} + +void ReferenceLinker::WriteAttributeName(const Reference& ref, const CallSite& callsite, + const xml::IPackageDeclStack* decls, + DiagMessage* out_msg) { + CHECK(out_msg != nullptr); + if (!ref.name) { + *out_msg << ref.id.value(); + return; + } + + const ResourceName& ref_name = ref.name.value(); + CHECK_EQ(ref_name.type, ResourceType::kAttr); + + if (!ref_name.package.empty()) { + *out_msg << ref_name.package << ":"; + } + *out_msg << ref_name.entry; + + Reference fully_qualified = ref; + xml::ResolvePackage(decls, &fully_qualified); + + ResourceName& full_name = fully_qualified.name.value(); + if (full_name.package.empty()) { + full_name.package = callsite.package; + } + + if (full_name != ref.name.value()) { + *out_msg << " (aka " << full_name.package << ":" << full_name.entry << ")"; } } bool ReferenceLinker::LinkReference(const CallSite& callsite, Reference* reference, IAaptContext* context, SymbolTable* symbols, - xml::IPackageDeclStack* decls) { + const xml::IPackageDeclStack* decls) { CHECK(reference != nullptr); if (!reference->name && !reference->id) { // This is @null. @@ -299,7 +328,7 @@ bool ReferenceLinker::LinkReference(const CallSite& callsite, Reference* referen } Reference transformed_reference = *reference; - TransformReferenceFromNamespace(decls, context->GetCompilationPackage(), &transformed_reference); + xml::ResolvePackage(decls, &transformed_reference); std::string err_str; const SymbolTable::Symbol* s = @@ -314,7 +343,7 @@ bool ReferenceLinker::LinkReference(const CallSite& callsite, Reference* referen DiagMessage error_msg(reference->GetSource()); error_msg << "resource "; - WriteResourceName(&error_msg, *reference, transformed_reference); + WriteResourceName(*reference, callsite, decls, &error_msg); error_msg << " " << err_str; context->GetDiagnostics()->Error(error_msg); return false; @@ -324,21 +353,24 @@ bool ReferenceLinker::Consume(IAaptContext* context, ResourceTable* table) { EmptyDeclStack decl_stack; bool error = false; for (auto& package : table->packages) { + // Since we're linking, each package must have a name. + CHECK(!package->name.empty()) << "all packages being linked must have a name"; + for (auto& type : package->types) { for (auto& entry : type->entries) { - // Symbol state information may be lost if there is no value for the - // resource. - if (entry->symbol_status.state != SymbolState::kUndefined && - entry->values.empty()) { - context->GetDiagnostics()->Error( - DiagMessage(entry->symbol_status.source) - << "no definition for declared symbol '" - << ResourceNameRef(package->name, type->type, entry->name) - << "'"); + // First, unmangle the name if necessary. + ResourceName name(package->name, type->type, entry->name); + NameMangler::Unmangle(&name.entry, &name.package); + + // Symbol state information may be lost if there is no value for the resource. + if (entry->symbol_status.state != SymbolState::kUndefined && entry->values.empty()) { + context->GetDiagnostics()->Error(DiagMessage(entry->symbol_status.source) + << "no definition for declared symbol '" << name << "'"); error = true; } - CallSite callsite = {ResourceNameRef(package->name, type->type, entry->name)}; + // The context of this resource is the package in which it is defined. + const CallSite callsite{name.package}; ReferenceLinkerVisitor visitor(callsite, context, context->GetExternalSymbols(), &table->string_pool, &decl_stack); diff --git a/tools/aapt2/link/ReferenceLinker.h b/tools/aapt2/link/ReferenceLinker.h index b3d0196d9e7c..3b11bee0acc9 100644 --- a/tools/aapt2/link/ReferenceLinker.h +++ b/tools/aapt2/link/ReferenceLinker.h @@ -29,83 +29,58 @@ namespace aapt { -/** - * Resolves all references to resources in the ResourceTable and assigns them - * IDs. - * The ResourceTable must already have IDs assigned to each resource. - * Once the ResourceTable is processed by this linker, it is ready to be - * flattened. - */ +// Resolves all references to resources in the ResourceTable and assigns them IDs. +// The ResourceTable must already have IDs assigned to each resource. +// Once the ResourceTable is processed by this linker, it is ready to be flattened. class ReferenceLinker : public IResourceTableConsumer { public: ReferenceLinker() = default; - /** - * Returns true if the symbol is visible by the reference and from the - * callsite. - */ - static bool IsSymbolVisible(const SymbolTable::Symbol& symbol, - const Reference& ref, const CallSite& callsite); - - /** - * Performs name mangling and looks up the resource in the symbol table. - * Returns nullptr if the symbol was not found. - */ - static const SymbolTable::Symbol* ResolveSymbol(const Reference& reference, SymbolTable* symbols); - - /** - * Performs name mangling and looks up the resource in the symbol table. If - * the symbol is not visible by the reference at the callsite, nullptr is - * returned. out_error holds the error message. - */ + // Performs name mangling and looks up the resource in the symbol table. Uses the callsite's + // package if the reference has no package name defined (implicit). + // Returns nullptr if the symbol was not found. + static const SymbolTable::Symbol* ResolveSymbol(const Reference& reference, + const CallSite& callsite, SymbolTable* symbols); + + // Performs name mangling and looks up the resource in the symbol table. If the symbol is not + // visible by the reference at the callsite, nullptr is returned. + // `out_error` holds the error message. static const SymbolTable::Symbol* ResolveSymbolCheckVisibility(const Reference& reference, const CallSite& callsite, SymbolTable* symbols, std::string* out_error); - /** - * Same as resolveSymbolCheckVisibility(), but also makes sure the symbol is - * an attribute. - * That is, the return value will have a non-null value for - * ISymbolTable::Symbol::attribute. - */ + // Same as ResolveSymbolCheckVisibility(), but also makes sure the symbol is an attribute. + // That is, the return value will have a non-null value for ISymbolTable::Symbol::attribute. static const SymbolTable::Symbol* ResolveAttributeCheckVisibility(const Reference& reference, const CallSite& callsite, SymbolTable* symbols, std::string* out_error); - /** - * Resolves the attribute reference and returns an xml::AaptAttribute if - * successful. - * If resolution fails, outError holds the error message. - */ + // Resolves the attribute reference and returns an xml::AaptAttribute if successful. + // If resolution fails, outError holds the error message. static Maybe<xml::AaptAttribute> CompileXmlAttribute(const Reference& reference, const CallSite& callsite, SymbolTable* symbols, std::string* out_error); - /** - * Writes the resource name to the DiagMessage, using the - * "orig_name (aka <transformed_name>)" syntax. - */ - static void WriteResourceName(DiagMessage* out_msg, const Reference& orig, - const Reference& transformed); - - /** - * Transforms the package name of the reference to the fully qualified package - * name using - * the xml::IPackageDeclStack, then mangles and looks up the symbol. If the - * symbol is visible - * to the reference at the callsite, the reference is updated with an ID. - * Returns false on failure, and an error message is logged to the - * IDiagnostics in the context. - */ + // Writes the resource name to the DiagMessage, using the + // "orig_name (aka <transformed_name>)" syntax. + static void WriteResourceName(const Reference& orig, const CallSite& callsite, + const xml::IPackageDeclStack* decls, DiagMessage* out_msg); + + // Same as WriteResourceName but omits the 'attr' part. + static void WriteAttributeName(const Reference& ref, const CallSite& callsite, + const xml::IPackageDeclStack* decls, DiagMessage* out_msg); + + // Transforms the package name of the reference to the fully qualified package name using + // the xml::IPackageDeclStack, then mangles and looks up the symbol. If the symbol is visible + // to the reference at the callsite, the reference is updated with an ID. + // Returns false on failure, and an error message is logged to the IDiagnostics in the context. static bool LinkReference(const CallSite& callsite, Reference* reference, IAaptContext* context, - SymbolTable* symbols, xml::IPackageDeclStack* decls); + SymbolTable* symbols, const xml::IPackageDeclStack* decls); - /** - * Links all references in the ResourceTable. - */ + // Links all references in the ResourceTable. bool Consume(IAaptContext* context, ResourceTable* table) override; private: diff --git a/tools/aapt2/link/ReferenceLinker_test.cpp b/tools/aapt2/link/ReferenceLinker_test.cpp index 72a91689e392..be38b967c986 100644 --- a/tools/aapt2/link/ReferenceLinker_test.cpp +++ b/tools/aapt2/link/ReferenceLinker_test.cpp @@ -18,7 +18,9 @@ #include "test/Test.h" -using android::ResTable_map; +using ::android::ResTable_map; +using ::testing::Eq; +using ::testing::IsNull; using ::testing::NotNull; namespace aapt { @@ -263,7 +265,7 @@ TEST(ReferenceLinkerTest, AppsWithSamePackageButDifferentIdAreVisibleNonPublic) .Build()); std::string error; - const CallSite call_site{ResourceNameRef("com.app.test", ResourceType::kString, "foo")}; + const CallSite call_site{"com.app.test"}; const SymbolTable::Symbol* symbol = ReferenceLinker::ResolveSymbolCheckVisibility( *test::BuildReference("com.app.test:string/foo"), call_site, &table, &error); ASSERT_THAT(symbol, NotNull()); @@ -281,7 +283,7 @@ TEST(ReferenceLinkerTest, AppsWithDifferentPackageCanNotUseEachOthersAttribute) .Build()); std::string error; - const CallSite call_site{ResourceNameRef("com.app.ext", ResourceType::kLayout, "foo")}; + const CallSite call_site{"com.app.ext"}; EXPECT_FALSE(ReferenceLinker::CompileXmlAttribute( *test::BuildReference("com.app.test:attr/foo"), call_site, &table, &error)); @@ -293,4 +295,27 @@ TEST(ReferenceLinkerTest, AppsWithDifferentPackageCanNotUseEachOthersAttribute) EXPECT_TRUE(error.empty()); } +TEST(ReferenceLinkerTest, ReferenceWithNoPackageUsesCallSitePackage) { + NameMangler mangler(NameManglerPolicy{"com.app.test"}); + SymbolTable table(&mangler); + table.AppendSource(test::StaticSymbolSourceBuilder() + .AddSymbol("com.app.test:string/foo", ResourceId(0x7f010000)) + .AddSymbol("com.app.lib:string/foo", ResourceId(0x7f010001)) + .Build()); + + const SymbolTable::Symbol* s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/foo"), + CallSite{"com.app.test"}, &table); + ASSERT_THAT(s, NotNull()); + EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010000))); + + s = ReferenceLinker::ResolveSymbol(*test::BuildReference("string/foo"), CallSite{"com.app.lib"}, + &table); + ASSERT_THAT(s, NotNull()); + EXPECT_THAT(s->id, Eq(make_value<ResourceId>(0x7f010001))); + + EXPECT_THAT(ReferenceLinker::ResolveSymbol(*test::BuildReference("string/foo"), + CallSite{"com.app.bad"}, &table), + IsNull()); +} + } // namespace aapt diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp index 10e837c725e5..93c904f1a743 100644 --- a/tools/aapt2/link/TableMerger.cpp +++ b/tools/aapt2/link/TableMerger.cpp @@ -24,7 +24,7 @@ #include "ValueVisitor.h" #include "util/Util.h" -using android::StringPiece; +using ::android::StringPiece; namespace aapt { @@ -32,27 +32,23 @@ TableMerger::TableMerger(IAaptContext* context, ResourceTable* out_table, const TableMergerOptions& options) : context_(context), master_table_(out_table), options_(options) { // Create the desired package that all tables will be merged into. - master_package_ = master_table_->CreatePackage( - context_->GetCompilationPackage(), context_->GetPackageId()); + master_package_ = + master_table_->CreatePackage(context_->GetCompilationPackage(), context_->GetPackageId()); CHECK(master_package_ != nullptr) << "package name or ID already taken"; } -bool TableMerger::Merge(const Source& src, ResourceTable* table, - io::IFileCollection* collection) { - return MergeImpl(src, table, collection, false /* overlay */, true /* allow new */); +bool TableMerger::Merge(const Source& src, ResourceTable* table, io::IFileCollection* collection) { + return MergeImpl(src, table, collection, false /*overlay*/, true /*allow_new*/); } bool TableMerger::MergeOverlay(const Source& src, ResourceTable* table, io::IFileCollection* collection) { - return MergeImpl(src, table, collection, true /* overlay */, options_.auto_add_overlay); + return MergeImpl(src, table, collection, true /*overlay*/, options_.auto_add_overlay); } -/** - * This will merge packages with the same package name (or no package name). - */ +// This will merge packages with the same package name (or no package name). bool TableMerger::MergeImpl(const Source& src, ResourceTable* table, - io::IFileCollection* collection, bool overlay, - bool allow_new) { + io::IFileCollection* collection, bool overlay, bool allow_new) { bool error = false; for (auto& package : table->packages) { // Only merge an empty package or the package we're building. @@ -62,9 +58,8 @@ bool TableMerger::MergeImpl(const Source& src, ResourceTable* table, if (package->name.empty() || context_->GetCompilationPackage() == package->name) { FileMergeCallback callback; if (collection) { - callback = [&](const ResourceNameRef& name, - const ConfigDescription& config, FileReference* new_file, - FileReference* old_file) -> bool { + callback = [&](const ResourceNameRef& name, const ConfigDescription& config, + FileReference* new_file, FileReference* old_file) -> bool { // The old file's path points inside the APK, so we can use it as is. io::IFile* f = collection->FindFile(*old_file->path); if (!f) { @@ -78,45 +73,38 @@ bool TableMerger::MergeImpl(const Source& src, ResourceTable* table, }; } - // Merge here. Once the entries are merged and mangled, any references to - // them are still valid. This is because un-mangled references are - // mangled, then looked up at resolution time. - // Also, when linking, we convert references with no package name to use - // the compilation package name. - error |= !DoMerge(src, table, package.get(), false /* mangle */, overlay, - allow_new, callback); + // Merge here. Once the entries are merged and mangled, any references to them are still + // valid. This is because un-mangled references are mangled, then looked up at resolution + // time. Also, when linking, we convert references with no package name to use the compilation + // package name. + error |= + !DoMerge(src, table, package.get(), false /* mangle */, overlay, allow_new, callback); } } return !error; } -/** - * This will merge and mangle resources from a static library. - */ -bool TableMerger::MergeAndMangle(const Source& src, - const StringPiece& package_name, - ResourceTable* table, - io::IFileCollection* collection) { +// This will merge and mangle resources from a static library. +bool TableMerger::MergeAndMangle(const Source& src, const StringPiece& package_name, + ResourceTable* table, io::IFileCollection* collection) { bool error = false; for (auto& package : table->packages) { // Warn of packages with an unrelated ID. if (package_name != package->name) { - context_->GetDiagnostics()->Warn(DiagMessage(src) << "ignoring package " - << package->name); + context_->GetDiagnostics()->Warn(DiagMessage(src) << "ignoring package " << package->name); continue; } bool mangle = package_name != context_->GetCompilationPackage(); merged_packages_.insert(package->name); - auto callback = [&]( - const ResourceNameRef& name, const ConfigDescription& config, - FileReference* new_file, FileReference* old_file) -> bool { + auto callback = [&](const ResourceNameRef& name, const ConfigDescription& config, + FileReference* new_file, FileReference* old_file) -> bool { // The old file's path points inside the APK, so we can use it as is. io::IFile* f = collection->FindFile(*old_file->path); if (!f) { - context_->GetDiagnostics()->Error( - DiagMessage(src) << "file '" << *old_file->path << "' not found"); + context_->GetDiagnostics()->Error(DiagMessage(src) + << "file '" << *old_file->path << "' not found"); return false; } @@ -124,21 +112,18 @@ bool TableMerger::MergeAndMangle(const Source& src, return true; }; - error |= !DoMerge(src, table, package.get(), mangle, false /* overlay */, - true /* allow new */, callback); + error |= !DoMerge(src, table, package.get(), mangle, false /*overlay*/, true /*allow_new*/, + callback); } return !error; } -static bool MergeType(IAaptContext* context, const Source& src, - ResourceTableType* dst_type, +static bool MergeType(IAaptContext* context, const Source& src, ResourceTableType* dst_type, ResourceTableType* src_type) { if (dst_type->symbol_status.state < src_type->symbol_status.state) { - // The incoming type's visibility is stronger, so we should override - // the visibility. + // The incoming type's visibility is stronger, so we should override the visibility. if (src_type->symbol_status.state == SymbolState::kPublic) { - // Only copy the ID if the source is public, or else the ID is - // meaningless. + // Only copy the ID if the source is public, or else the ID is meaningless. dst_type->id = src_type->id; } dst_type->symbol_status = std::move(src_type->symbol_status); @@ -155,14 +140,12 @@ static bool MergeType(IAaptContext* context, const Source& src, return true; } -static bool MergeEntry(IAaptContext* context, const Source& src, - ResourceEntry* dst_entry, ResourceEntry* src_entry) { +static bool MergeEntry(IAaptContext* context, const Source& src, ResourceEntry* dst_entry, + ResourceEntry* src_entry) { if (dst_entry->symbol_status.state < src_entry->symbol_status.state) { - // The incoming type's visibility is stronger, so we should override - // the visibility. + // The incoming type's visibility is stronger, so we should override the visibility. if (src_entry->symbol_status.state == SymbolState::kPublic) { - // Only copy the ID if the source is public, or else the ID is - // meaningless. + // Only copy the ID if the source is public, or else the ID is meaningless. dst_entry->id = src_entry->id; } dst_entry->symbol_status = std::move(src_entry->symbol_status); @@ -171,9 +154,8 @@ static bool MergeEntry(IAaptContext* context, const Source& src, dst_entry->id && src_entry->id && dst_entry->id.value() != src_entry->id.value()) { // Both entries are public and have different IDs. - context->GetDiagnostics()->Error( - DiagMessage(src) << "cannot merge entry '" << src_entry->name - << "': conflicting public IDs"); + context->GetDiagnostics()->Error(DiagMessage(src) << "cannot merge entry '" << src_entry->name + << "': conflicting public IDs"); return false; } return true; @@ -181,12 +163,10 @@ static bool MergeEntry(IAaptContext* context, const Source& src, // Modified CollisionResolver which will merge Styleables and Styles. Used with overlays. // -// Styleables are not actual resources, but they are treated as such during the -// compilation phase. +// Styleables are not actual resources, but they are treated as such during the compilation phase. // -// Styleables and Styles don't simply overlay each other, their definitions merge -// and accumulate. If both values are Styleables/Styles, we just merge them into the -// existing value. +// Styleables and Styles don't simply overlay each other, their definitions merge and accumulate. +// If both values are Styleables/Styles, we just merge them into the existing value. static ResourceTable::CollisionResult ResolveMergeCollision(Value* existing, Value* incoming, StringPool* pool) { if (Styleable* existing_styleable = ValueCast<Styleable>(existing)) { diff --git a/tools/aapt2/link/TableMerger.h b/tools/aapt2/link/TableMerger.h index c96b1b0b4dfb..81518ffb2441 100644 --- a/tools/aapt2/link/TableMerger.h +++ b/tools/aapt2/link/TableMerger.h @@ -33,81 +33,49 @@ namespace aapt { struct TableMergerOptions { - /** - * If true, resources in overlays can be added without previously having - * existed. - */ + // If true, resources in overlays can be added without previously having existed. bool auto_add_overlay = false; }; -/** - * TableMerger takes resource tables and merges all packages within the tables - * that have the same - * package ID. - * - * If a package has a different name, all the entries in that table have their - * names mangled - * to include the package name. This way there are no collisions. In order to do - * this correctly, - * the TableMerger needs to also mangle any FileReference paths. Once these are - * mangled, - * the original source path of the file, along with the new destination path is - * recorded in the - * queue returned from getFileMergeQueue(). - * - * Once the merging is complete, a separate process can go collect the files - * from the various - * source APKs and either copy or process their XML and put them in the correct - * location in - * the final APK. - */ +// TableMerger takes resource tables and merges all packages within the tables that have the same +// package ID. +// +// If a package has a different name, all the entries in that table have their names mangled +// to include the package name. This way there are no collisions. In order to do this correctly, +// the TableMerger needs to also mangle any FileReference paths. Once these are mangled, the +// `IFile` pointer in `FileReference` will point to the original file. +// +// Once the merging is complete, a separate phase can go collect the files from the various +// source APKs and either copy or process their XML and put them in the correct location in the +// final APK. class TableMerger { public: - /** - * Note: The out_table ResourceTable must live longer than this TableMerger. - * References are made to this ResourceTable for efficiency reasons. - */ - TableMerger(IAaptContext* context, ResourceTable* out_table, - const TableMergerOptions& options); - - const std::set<std::string>& merged_packages() const { + // Note: The out_table ResourceTable must live longer than this TableMerger. + // References are made to this ResourceTable for efficiency reasons. + TableMerger(IAaptContext* context, ResourceTable* out_table, const TableMergerOptions& options); + + inline const std::set<std::string>& merged_packages() const { return merged_packages_; } - /** - * Merges resources from the same or empty package. This is for local sources. - * An io::IFileCollection is optional and used to find the referenced Files - * and process them. - */ - bool Merge(const Source& src, ResourceTable* table, - io::IFileCollection* collection = nullptr); - - /** - * Merges resources from an overlay ResourceTable. - * An io::IFileCollection is optional and used to find the referenced Files - * and process them. - */ + // Merges resources from the same or empty package. This is for local sources. + // An io::IFileCollection is optional and used to find the referenced Files and process them. + bool Merge(const Source& src, ResourceTable* table, io::IFileCollection* collection = nullptr); + + // Merges resources from an overlay ResourceTable. + // An io::IFileCollection is optional and used to find the referenced Files and process them. bool MergeOverlay(const Source& src, ResourceTable* table, io::IFileCollection* collection = nullptr); - /** - * Merges resources from the given package, mangling the name. This is for - * static libraries. - * An io::IFileCollection is needed in order to find the referenced Files and - * process them. - */ + // Merges resources from the given package, mangling the name. This is for static libraries. + // An io::IFileCollection is needed in order to find the referenced Files and process them. bool MergeAndMangle(const Source& src, const android::StringPiece& package, ResourceTable* table, io::IFileCollection* collection); - /** - * Merges a compiled file that belongs to this same or empty package. This is - * for local sources. - */ + // Merges a compiled file that belongs to this same or empty package. This is for local sources. bool MergeFile(const ResourceFile& fileDesc, io::IFile* file); - /** - * Merges a compiled file from an overlay, overriding an existing definition. - */ + // Merges a compiled file from an overlay, overriding an existing definition. bool MergeFileOverlay(const ResourceFile& fileDesc, io::IFile* file); private: diff --git a/tools/aapt2/link/XmlCompatVersioner.cpp b/tools/aapt2/link/XmlCompatVersioner.cpp index f1f4e3b7f05f..20ebdc696814 100644 --- a/tools/aapt2/link/XmlCompatVersioner.cpp +++ b/tools/aapt2/link/XmlCompatVersioner.cpp @@ -107,7 +107,7 @@ std::unique_ptr<xml::XmlResource> XmlCompatVersioner::ProcessDoc( std::unique_ptr<xml::XmlResource> cloned_doc = util::make_unique<xml::XmlResource>(doc->file); cloned_doc->file.config.sdkVersion = static_cast<uint16_t>(target_api); - cloned_doc->root = doc->root->Clone([&](const xml::Element& el, xml::Element* out_el) { + cloned_doc->root = doc->root->CloneElement([&](const xml::Element& el, xml::Element* out_el) { for (const auto& attr : el.attributes) { if (!attr.compiled_attribute) { // Just copy if this isn't a compiled attribute. diff --git a/tools/aapt2/link/XmlCompatVersioner_test.cpp b/tools/aapt2/link/XmlCompatVersioner_test.cpp index ce6605c6ad97..29ad25f79ab9 100644 --- a/tools/aapt2/link/XmlCompatVersioner_test.cpp +++ b/tools/aapt2/link/XmlCompatVersioner_test.cpp @@ -19,6 +19,12 @@ #include "Linkers.h" #include "test/Test.h" +using ::aapt::test::ValueEq; +using ::testing::Eq; +using ::testing::IsNull; +using ::testing::NotNull; +using ::testing::SizeIs; + namespace aapt { constexpr auto TYPE_DIMENSION = android::ResTable_map::TYPE_DIMENSION; @@ -68,12 +74,12 @@ class XmlCompatVersionerTest : public ::testing::Test { }; TEST_F(XmlCompatVersionerTest, NoRulesOnlyStripsAndCopies) { - auto doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF( + auto doc = test::BuildXmlDomForPackageName(context_.get(), R"( <View xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:paddingHorizontal="24dp" app:foo="16dp" - foo="bar"/>)EOF"); + foo="bar"/>)"); XmlReferenceLinker linker; ASSERT_TRUE(linker.Consume(context_.get(), doc.get())); @@ -84,35 +90,35 @@ TEST_F(XmlCompatVersionerTest, NoRulesOnlyStripsAndCopies) { XmlCompatVersioner versioner(&rules); std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs = versioner.Process(context_.get(), doc.get(), api_range); - ASSERT_EQ(2u, versioned_docs.size()); + ASSERT_THAT(versioned_docs, SizeIs(2u)); xml::Element* el; // Source XML file's sdkVersion == 0, so the first one must also have the same sdkVersion. - EXPECT_EQ(static_cast<uint16_t>(0), versioned_docs[0]->file.config.sdkVersion); - el = xml::FindRootElement(versioned_docs[0].get()); - ASSERT_NE(nullptr, el); - EXPECT_EQ(2u, el->attributes.size()); - EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal")); - EXPECT_NE(nullptr, el->FindAttribute(xml::kSchemaAuto, "foo")); - EXPECT_NE(nullptr, el->FindAttribute({}, "foo")); - - EXPECT_EQ(static_cast<uint16_t>(SDK_LOLLIPOP_MR1), versioned_docs[1]->file.config.sdkVersion); - el = xml::FindRootElement(versioned_docs[1].get()); - ASSERT_NE(nullptr, el); - EXPECT_EQ(3u, el->attributes.size()); - EXPECT_NE(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal")); - EXPECT_NE(nullptr, el->FindAttribute(xml::kSchemaAuto, "foo")); - EXPECT_NE(nullptr, el->FindAttribute({}, "foo")); + EXPECT_THAT(versioned_docs[0]->file.config.sdkVersion, Eq(0u)); + el = versioned_docs[0]->root.get(); + ASSERT_THAT(el, NotNull()); + EXPECT_THAT(el->attributes, SizeIs(2u)); + EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), IsNull()); + EXPECT_THAT(el->FindAttribute(xml::kSchemaAuto, "foo"), NotNull()); + EXPECT_THAT(el->FindAttribute({}, "foo"), NotNull()); + + EXPECT_THAT(versioned_docs[1]->file.config.sdkVersion, Eq(SDK_LOLLIPOP_MR1)); + el = versioned_docs[1]->root.get(); + ASSERT_THAT(el, NotNull()); + EXPECT_THAT(el->attributes, SizeIs(3u)); + EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), NotNull()); + EXPECT_THAT(el->FindAttribute(xml::kSchemaAuto, "foo"), NotNull()); + EXPECT_THAT(el->FindAttribute({}, "foo"), NotNull()); } TEST_F(XmlCompatVersionerTest, SingleRule) { - auto doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF( + auto doc = test::BuildXmlDomForPackageName(context_.get(), R"( <View xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:paddingHorizontal="24dp" app:foo="16dp" - foo="bar"/>)EOF"); + foo="bar"/>)"); XmlReferenceLinker linker; ASSERT_TRUE(linker.Consume(context_.get(), doc.get())); @@ -129,51 +135,51 @@ TEST_F(XmlCompatVersionerTest, SingleRule) { XmlCompatVersioner versioner(&rules); std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs = versioner.Process(context_.get(), doc.get(), api_range); - ASSERT_EQ(2u, versioned_docs.size()); + ASSERT_THAT(versioned_docs, SizeIs(2u)); xml::Element* el; - EXPECT_EQ(static_cast<uint16_t>(0), versioned_docs[0]->file.config.sdkVersion); - el = xml::FindRootElement(versioned_docs[0].get()); - ASSERT_NE(nullptr, el); - EXPECT_EQ(4u, el->attributes.size()); - EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal")); - EXPECT_NE(nullptr, el->FindAttribute(xml::kSchemaAuto, "foo")); - EXPECT_NE(nullptr, el->FindAttribute({}, "foo")); + EXPECT_THAT(versioned_docs[0]->file.config.sdkVersion, Eq(0u)); + el = versioned_docs[0]->root.get(); + ASSERT_THAT(el, NotNull()); + EXPECT_THAT(el->attributes, SizeIs(4u)); + EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), IsNull()); + EXPECT_THAT(el->FindAttribute(xml::kSchemaAuto, "foo"), NotNull()); + EXPECT_THAT(el->FindAttribute({}, "foo"), NotNull()); xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft"); - ASSERT_NE(nullptr, attr); - ASSERT_NE(nullptr, attr->compiled_value); + ASSERT_THAT(attr, NotNull()); + ASSERT_THAT(attr->compiled_value, NotNull()); ASSERT_TRUE(attr->compiled_attribute); attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight"); - ASSERT_NE(nullptr, attr); - ASSERT_NE(nullptr, attr->compiled_value); + ASSERT_THAT(attr, NotNull()); + ASSERT_THAT(attr->compiled_value, NotNull()); ASSERT_TRUE(attr->compiled_attribute); - EXPECT_EQ(static_cast<uint16_t>(SDK_LOLLIPOP_MR1), versioned_docs[1]->file.config.sdkVersion); - el = xml::FindRootElement(versioned_docs[1].get()); - ASSERT_NE(nullptr, el); - EXPECT_EQ(5u, el->attributes.size()); - EXPECT_NE(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal")); - EXPECT_NE(nullptr, el->FindAttribute(xml::kSchemaAuto, "foo")); - EXPECT_NE(nullptr, el->FindAttribute({}, "foo")); + EXPECT_THAT(versioned_docs[1]->file.config.sdkVersion, Eq(SDK_LOLLIPOP_MR1)); + el = versioned_docs[1]->root.get(); + ASSERT_THAT(el, NotNull()); + EXPECT_THAT(el->attributes, SizeIs(5u)); + EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), NotNull()); + EXPECT_THAT(el->FindAttribute(xml::kSchemaAuto, "foo"), NotNull()); + EXPECT_THAT(el->FindAttribute({}, "foo"), NotNull()); attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft"); - ASSERT_NE(nullptr, attr); - ASSERT_NE(nullptr, attr->compiled_value); + ASSERT_THAT(attr, NotNull()); + ASSERT_THAT(attr->compiled_value, NotNull()); ASSERT_TRUE(attr->compiled_attribute); attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight"); - ASSERT_NE(nullptr, attr); - ASSERT_NE(nullptr, attr->compiled_value); + ASSERT_THAT(attr, NotNull()); + ASSERT_THAT(attr->compiled_value, NotNull()); ASSERT_TRUE(attr->compiled_attribute); } TEST_F(XmlCompatVersionerTest, ChainedRule) { - auto doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF( + auto doc = test::BuildXmlDomForPackageName(context_.get(), R"( <View xmlns:android="http://schemas.android.com/apk/res/android" - android:paddingHorizontal="24dp" />)EOF"); + android:paddingHorizontal="24dp" />)"); XmlReferenceLinker linker; ASSERT_TRUE(linker.Consume(context_.get(), doc.get())); @@ -193,71 +199,70 @@ TEST_F(XmlCompatVersionerTest, ChainedRule) { XmlCompatVersioner versioner(&rules); std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs = versioner.Process(context_.get(), doc.get(), api_range); - ASSERT_EQ(3u, versioned_docs.size()); + ASSERT_THAT(versioned_docs, SizeIs(3u)); xml::Element* el; - EXPECT_EQ(static_cast<uint16_t>(0), versioned_docs[0]->file.config.sdkVersion); - el = xml::FindRootElement(versioned_docs[0].get()); - ASSERT_NE(nullptr, el); - EXPECT_EQ(2u, el->attributes.size()); - EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal")); + EXPECT_THAT(versioned_docs[0]->file.config.sdkVersion, Eq(0u)); + el = versioned_docs[0]->root.get(); + ASSERT_THAT(el, NotNull()); + EXPECT_THAT(el->attributes, SizeIs(2u)); + EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), IsNull()); xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft"); - ASSERT_NE(nullptr, attr); - ASSERT_NE(nullptr, attr->compiled_value); + ASSERT_THAT(attr, NotNull()); + ASSERT_THAT(attr->compiled_value, NotNull()); ASSERT_TRUE(attr->compiled_attribute); attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight"); - ASSERT_NE(nullptr, attr); - ASSERT_NE(nullptr, attr->compiled_value); + ASSERT_THAT(attr, NotNull()); + ASSERT_THAT(attr->compiled_value, NotNull()); ASSERT_TRUE(attr->compiled_attribute); - EXPECT_EQ(static_cast<uint16_t>(SDK_HONEYCOMB), versioned_docs[1]->file.config.sdkVersion); - el = xml::FindRootElement(versioned_docs[1].get()); - ASSERT_NE(nullptr, el); - EXPECT_EQ(1u, el->attributes.size()); - EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal")); - EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingLeft")); - EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingRight")); + EXPECT_THAT(versioned_docs[1]->file.config.sdkVersion, Eq(SDK_HONEYCOMB)); + el = versioned_docs[1]->root.get(); + ASSERT_THAT(el, NotNull()); + EXPECT_THAT(el->attributes, SizeIs(1u)); + EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), IsNull()); + EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingLeft"), IsNull()); + EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingRight"), IsNull()); attr = el->FindAttribute(xml::kSchemaAndroid, "progressBarPadding"); - ASSERT_NE(nullptr, attr); - ASSERT_NE(nullptr, attr->compiled_value); + ASSERT_THAT(attr, NotNull()); + ASSERT_THAT(attr->compiled_value, NotNull()); ASSERT_TRUE(attr->compiled_attribute); - EXPECT_EQ(static_cast<uint16_t>(SDK_LOLLIPOP_MR1), versioned_docs[2]->file.config.sdkVersion); - el = xml::FindRootElement(versioned_docs[2].get()); - ASSERT_NE(nullptr, el); - EXPECT_EQ(2u, el->attributes.size()); - EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingLeft")); - EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingRight")); + EXPECT_THAT(versioned_docs[2]->file.config.sdkVersion, Eq(SDK_LOLLIPOP_MR1)); + el = versioned_docs[2]->root.get(); + ASSERT_THAT(el, NotNull()); + EXPECT_THAT(el->attributes, SizeIs(2u)); + EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingLeft"), IsNull()); + EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingRight"), IsNull()); attr = el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"); - ASSERT_NE(nullptr, attr); - ASSERT_NE(nullptr, attr->compiled_value); + ASSERT_THAT(attr, NotNull()); + ASSERT_THAT(attr->compiled_value, NotNull()); ASSERT_TRUE(attr->compiled_attribute); attr = el->FindAttribute(xml::kSchemaAndroid, "progressBarPadding"); - ASSERT_NE(nullptr, attr); - ASSERT_NE(nullptr, attr->compiled_value); + ASSERT_THAT(attr, NotNull()); + ASSERT_THAT(attr->compiled_value, NotNull()); ASSERT_TRUE(attr->compiled_attribute); } TEST_F(XmlCompatVersionerTest, DegradeRuleOverridesExistingAttribute) { - auto doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF( + auto doc = test::BuildXmlDomForPackageName(context_.get(), R"( <View xmlns:android="http://schemas.android.com/apk/res/android" android:paddingHorizontal="24dp" android:paddingLeft="16dp" - android:paddingRight="16dp"/>)EOF"); + android:paddingRight="16dp"/>)"); XmlReferenceLinker linker; ASSERT_TRUE(linker.Consume(context_.get(), doc.get())); - Item* padding_horizontal_value = xml::FindRootElement(doc.get()) - ->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal") - ->compiled_value.get(); - ASSERT_NE(nullptr, padding_horizontal_value); + Item* padding_horizontal_value = + doc->root->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal")->compiled_value.get(); + ASSERT_THAT(padding_horizontal_value, NotNull()); XmlCompatVersioner::Rules rules; rules[R::attr::paddingHorizontal] = @@ -271,50 +276,50 @@ TEST_F(XmlCompatVersionerTest, DegradeRuleOverridesExistingAttribute) { XmlCompatVersioner versioner(&rules); std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs = versioner.Process(context_.get(), doc.get(), api_range); - ASSERT_EQ(2u, versioned_docs.size()); + ASSERT_THAT(versioned_docs, SizeIs(2u)); xml::Element* el; - EXPECT_EQ(static_cast<uint16_t>(0), versioned_docs[0]->file.config.sdkVersion); - el = xml::FindRootElement(versioned_docs[0].get()); - ASSERT_NE(nullptr, el); - EXPECT_EQ(2u, el->attributes.size()); - EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal")); + EXPECT_THAT(versioned_docs[0]->file.config.sdkVersion, Eq(0u)); + el = versioned_docs[0]->root.get(); + ASSERT_THAT(el, NotNull()); + EXPECT_THAT(el->attributes, SizeIs(2u)); + EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), IsNull()); xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft"); - ASSERT_NE(nullptr, attr); - ASSERT_NE(nullptr, attr->compiled_value); - ASSERT_TRUE(padding_horizontal_value->Equals(attr->compiled_value.get())); + ASSERT_THAT(attr, NotNull()); + ASSERT_THAT(attr->compiled_value, NotNull()); ASSERT_TRUE(attr->compiled_attribute); + ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value)); attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight"); - ASSERT_NE(nullptr, attr); - ASSERT_NE(nullptr, attr->compiled_value); - ASSERT_TRUE(padding_horizontal_value->Equals(attr->compiled_value.get())); + ASSERT_THAT(attr, NotNull()); + ASSERT_THAT(attr->compiled_value, NotNull()); ASSERT_TRUE(attr->compiled_attribute); + ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value)); - EXPECT_EQ(static_cast<uint16_t>(SDK_LOLLIPOP_MR1), versioned_docs[1]->file.config.sdkVersion); - el = xml::FindRootElement(versioned_docs[1].get()); - ASSERT_NE(nullptr, el); - EXPECT_EQ(3u, el->attributes.size()); + EXPECT_THAT(versioned_docs[1]->file.config.sdkVersion, Eq(SDK_LOLLIPOP_MR1)); + el = versioned_docs[1]->root.get(); + ASSERT_THAT(el, NotNull()); + EXPECT_THAT(el->attributes, SizeIs(3u)); attr = el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"); - ASSERT_NE(nullptr, attr); - ASSERT_NE(nullptr, attr->compiled_value); - ASSERT_TRUE(padding_horizontal_value->Equals(attr->compiled_value.get())); + ASSERT_THAT(attr, NotNull()); + ASSERT_THAT(attr->compiled_value, NotNull()); ASSERT_TRUE(attr->compiled_attribute); + ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value)); attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft"); - ASSERT_NE(nullptr, attr); - ASSERT_NE(nullptr, attr->compiled_value); - ASSERT_TRUE(padding_horizontal_value->Equals(attr->compiled_value.get())); + ASSERT_THAT(attr, NotNull()); + ASSERT_THAT(attr->compiled_value, NotNull()); ASSERT_TRUE(attr->compiled_attribute); + ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value)); attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight"); - ASSERT_NE(nullptr, attr); - ASSERT_NE(nullptr, attr->compiled_value); - ASSERT_TRUE(padding_horizontal_value->Equals(attr->compiled_value.get())); + ASSERT_THAT(attr, NotNull()); + ASSERT_THAT(attr->compiled_value, NotNull()); ASSERT_TRUE(attr->compiled_attribute); + ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value)); } } // namespace aapt diff --git a/tools/aapt2/link/XmlNamespaceRemover.cpp b/tools/aapt2/link/XmlNamespaceRemover.cpp index 24aa5660ae30..b5e2423d58dc 100644 --- a/tools/aapt2/link/XmlNamespaceRemover.cpp +++ b/tools/aapt2/link/XmlNamespaceRemover.cpp @@ -24,37 +24,19 @@ namespace aapt { namespace { -/** - * Visits each xml Node, removing URI references and nested namespaces. - */ +// Visits each xml Node, removing URI references and nested namespaces. class XmlVisitor : public xml::Visitor { public: explicit XmlVisitor(bool keep_uris) : keep_uris_(keep_uris) {} void Visit(xml::Element* el) override { - // Strip namespaces - for (auto& child : el->children) { - while (child && xml::NodeCast<xml::Namespace>(child.get())) { - if (child->children.empty()) { - child = {}; - } else { - child = std::move(child->children.front()); - child->parent = el; - } - } - } - el->children.erase( - std::remove_if(el->children.begin(), el->children.end(), - [](const std::unique_ptr<xml::Node>& child) -> bool { - return child == nullptr; - }), - el->children.end()); + el->namespace_decls.clear(); if (!keep_uris_) { for (xml::Attribute& attr : el->attributes) { - attr.namespace_uri = std::string(); + attr.namespace_uri.clear(); } - el->namespace_uri = std::string(); + el->namespace_uri.clear(); } xml::Visitor::Visit(el); } @@ -67,19 +49,11 @@ class XmlVisitor : public xml::Visitor { } // namespace -bool XmlNamespaceRemover::Consume(IAaptContext* context, - xml::XmlResource* resource) { +bool XmlNamespaceRemover::Consume(IAaptContext* context, xml::XmlResource* resource) { if (!resource->root) { return false; } - // Replace any root namespaces until the root is a non-namespace node - while (xml::NodeCast<xml::Namespace>(resource->root.get())) { - if (resource->root->children.empty()) { - break; - } - resource->root = std::move(resource->root->children.front()); - resource->root->parent = nullptr; - } + XmlVisitor visitor(keep_uris_); resource->root->Accept(&visitor); return true; diff --git a/tools/aapt2/link/XmlNamespaceRemover_test.cpp b/tools/aapt2/link/XmlNamespaceRemover_test.cpp index a176c03a6432..df4920fde37f 100644 --- a/tools/aapt2/link/XmlNamespaceRemover_test.cpp +++ b/tools/aapt2/link/XmlNamespaceRemover_test.cpp @@ -18,6 +18,10 @@ #include "test/Test.h" +using ::testing::NotNull; +using ::testing::SizeIs; +using ::testing::StrEq; + namespace aapt { class XmlUriTestVisitor : public xml::Visitor { @@ -25,16 +29,14 @@ class XmlUriTestVisitor : public xml::Visitor { XmlUriTestVisitor() = default; void Visit(xml::Element* el) override { + EXPECT_THAT(el->namespace_decls, SizeIs(0u)); + for (const auto& attr : el->attributes) { - EXPECT_EQ(std::string(), attr.namespace_uri); + EXPECT_THAT(attr.namespace_uri, StrEq("")); } - EXPECT_EQ(std::string(), el->namespace_uri); - xml::Visitor::Visit(el); - } + EXPECT_THAT(el->namespace_uri, StrEq("")); - void Visit(xml::Namespace* ns) override { - EXPECT_EQ(std::string(), ns->namespace_uri); - xml::Visitor::Visit(ns); + xml::Visitor::Visit(el); } private: @@ -45,10 +47,9 @@ class XmlNamespaceTestVisitor : public xml::Visitor { public: XmlNamespaceTestVisitor() = default; - void Visit(xml::Namespace* ns) override { - ADD_FAILURE() << "Detected namespace: " << ns->namespace_prefix << "=\"" - << ns->namespace_uri << "\""; - xml::Visitor::Visit(ns); + void Visit(xml::Element* el) override { + EXPECT_THAT(el->namespace_decls, SizeIs(0u)); + xml::Visitor::Visit(el); } private: @@ -58,8 +59,7 @@ class XmlNamespaceTestVisitor : public xml::Visitor { class XmlNamespaceRemoverTest : public ::testing::Test { public: void SetUp() override { - context_ = - test::ContextBuilder().SetCompilationPackage("com.app.test").Build(); + context_ = test::ContextBuilder().SetCompilationPackage("com.app.test").Build(); } protected: @@ -75,8 +75,8 @@ TEST_F(XmlNamespaceRemoverTest, RemoveUris) { XmlNamespaceRemover remover; ASSERT_TRUE(remover.Consume(context_.get(), doc.get())); - xml::Node* root = doc.get()->root.get(); - ASSERT_NE(root, nullptr); + xml::Node* root = doc->root.get(); + ASSERT_THAT(root, NotNull()); XmlUriTestVisitor visitor; root->Accept(&visitor); @@ -93,8 +93,8 @@ TEST_F(XmlNamespaceRemoverTest, RemoveNamespaces) { XmlNamespaceRemover remover; ASSERT_TRUE(remover.Consume(context_.get(), doc.get())); - xml::Node* root = doc.get()->root.get(); - ASSERT_NE(root, nullptr); + xml::Node* root = doc->root.get(); + ASSERT_THAT(root, NotNull()); XmlNamespaceTestVisitor visitor; root->Accept(&visitor); @@ -112,8 +112,8 @@ TEST_F(XmlNamespaceRemoverTest, RemoveNestedNamespaces) { XmlNamespaceRemover remover; ASSERT_TRUE(remover.Consume(context_.get(), doc.get())); - xml::Node* root = doc.get()->root.get(); - ASSERT_NE(root, nullptr); + xml::Node* root = doc->root.get(); + ASSERT_THAT(root, NotNull()); XmlNamespaceTestVisitor visitor; root->Accept(&visitor); diff --git a/tools/aapt2/link/XmlReferenceLinker.cpp b/tools/aapt2/link/XmlReferenceLinker.cpp index 721fc26399bc..6ebb80f4be8f 100644 --- a/tools/aapt2/link/XmlReferenceLinker.cpp +++ b/tools/aapt2/link/XmlReferenceLinker.cpp @@ -31,13 +31,9 @@ namespace aapt { namespace { -/** - * Visits all references (including parents of styles, references in styles, - * arrays, etc) and - * links their symbolic name to their Resource ID, performing mangling and - * package aliasing - * as needed. - */ +// Visits all references (including parents of styles, references in styles, arrays, etc) and +// links their symbolic name to their Resource ID, performing mangling and package aliasing +// as needed. class ReferenceVisitor : public ValueVisitor { public: using ValueVisitor::Visit; @@ -52,7 +48,9 @@ class ReferenceVisitor : public ValueVisitor { } } - bool HasError() const { return error_; } + bool HasError() const { + return error_; + } private: DISALLOW_COPY_AND_ASSIGN(ReferenceVisitor); @@ -64,9 +62,7 @@ class ReferenceVisitor : public ValueVisitor { bool error_; }; -/** - * Visits each xml Element and compiles the attributes within. - */ +// Visits each xml Element and compiles the attributes within. class XmlVisitor : public xml::PackageAwareVisitor { public: using xml::PackageAwareVisitor::Visit; @@ -92,18 +88,12 @@ class XmlVisitor : public xml::PackageAwareVisitor { // they were assigned to the default Attribute. const Attribute* attribute = &kDefaultAttribute; - std::string attribute_package; if (Maybe<xml::ExtractedPackage> maybe_package = xml::ExtractPackageFromNamespace(attr.namespace_uri)) { // There is a valid package name for this attribute. We will look this up. - attribute_package = maybe_package.value().package; - if (attribute_package.empty()) { - // Empty package means the 'current' or 'local' package. - attribute_package = context_->GetCompilationPackage(); - } - - Reference attr_ref(ResourceNameRef(attribute_package, ResourceType::kAttr, attr.name)); + Reference attr_ref( + ResourceNameRef(maybe_package.value().package, ResourceType::kAttr, attr.name)); attr_ref.private_reference = maybe_package.value().private_namespace; std::string err_str; @@ -111,9 +101,11 @@ class XmlVisitor : public xml::PackageAwareVisitor { ReferenceLinker::CompileXmlAttribute(attr_ref, callsite_, symbols_, &err_str); if (!attr.compiled_attribute) { - context_->GetDiagnostics()->Error(DiagMessage(source) << "attribute '" - << attribute_package << ":" - << attr.name << "' " << err_str); + DiagMessage error_msg(source); + error_msg << "attribute "; + ReferenceLinker::WriteAttributeName(attr_ref, callsite_, this, &error_msg); + error_msg << " " << err_str; + context_->GetDiagnostics()->Error(error_msg); error_ = true; continue; } @@ -129,12 +121,8 @@ class XmlVisitor : public xml::PackageAwareVisitor { } else if ((attribute->type_mask & android::ResTable_map::TYPE_STRING) == 0) { // We won't be able to encode this as a string. DiagMessage msg(source); - msg << "'" << attr.value << "' " - << "is incompatible with attribute "; - if (!attribute_package.empty()) { - msg << attribute_package << ":"; - } - msg << attr.name << " " << *attribute; + msg << "'" << attr.value << "' is incompatible with attribute " << attr.name << " " + << *attribute; context_->GetDiagnostics()->Error(msg); error_ = true; } @@ -144,7 +132,9 @@ class XmlVisitor : public xml::PackageAwareVisitor { xml::PackageAwareVisitor::Visit(el); } - bool HasError() { return error_ || reference_visitor_.HasError(); } + bool HasError() { + return error_ || reference_visitor_.HasError(); + } private: DISALLOW_COPY_AND_ASSIGN(XmlVisitor); @@ -161,7 +151,17 @@ class XmlVisitor : public xml::PackageAwareVisitor { } // namespace bool XmlReferenceLinker::Consume(IAaptContext* context, xml::XmlResource* resource) { - const CallSite callsite = {resource->file.name}; + CallSite callsite{resource->file.name.package}; + + std::string out_name = resource->file.name.entry; + NameMangler::Unmangle(&out_name, &callsite.package); + + if (callsite.package.empty()) { + // Assume an empty package means that the XML file is local. This is true of AndroidManifest.xml + // for example. + callsite.package = context->GetCompilationPackage(); + } + XmlVisitor visitor(resource->file.source, callsite, context, context->GetExternalSymbols()); if (resource->root) { resource->root->Accept(&visitor); diff --git a/tools/aapt2/link/XmlReferenceLinker_test.cpp b/tools/aapt2/link/XmlReferenceLinker_test.cpp index 228cfb9e3d66..ef99355e5b5f 100644 --- a/tools/aapt2/link/XmlReferenceLinker_test.cpp +++ b/tools/aapt2/link/XmlReferenceLinker_test.cpp @@ -79,20 +79,20 @@ class XmlReferenceLinkerTest : public ::testing::Test { }; TEST_F(XmlReferenceLinkerTest, LinkBasicAttributes) { - std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF( - <View xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:background="@color/green" - android:text="hello" - android:attr="\?hello" - nonAaptAttr="1" - nonAaptAttrRef="@id/id" - class="hello" />)EOF"); + std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"( + <View xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:background="@color/green" + android:text="hello" + android:attr="\?hello" + nonAaptAttr="1" + nonAaptAttrRef="@id/id" + class="hello" />)"); XmlReferenceLinker linker; ASSERT_TRUE(linker.Consume(context_.get(), doc.get())); - xml::Element* view_el = xml::FindRootElement(doc.get()); + xml::Element* view_el = doc->root.get(); ASSERT_THAT(view_el, NotNull()); xml::Attribute* xml_attr = view_el->FindAttribute(xml::kSchemaAndroid, "layout_width"); @@ -138,32 +138,32 @@ TEST_F(XmlReferenceLinkerTest, LinkBasicAttributes) { } TEST_F(XmlReferenceLinkerTest, PrivateSymbolsAreNotLinked) { - std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF( - <View xmlns:android="http://schemas.android.com/apk/res/android" - android:colorAccent="@android:color/hidden" />)EOF"); + std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"( + <View xmlns:android="http://schemas.android.com/apk/res/android" + android:colorAccent="@android:color/hidden" />)"); XmlReferenceLinker linker; ASSERT_FALSE(linker.Consume(context_.get(), doc.get())); } TEST_F(XmlReferenceLinkerTest, PrivateSymbolsAreLinkedWhenReferenceHasStarPrefix) { - std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF( + std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"( <View xmlns:android="http://schemas.android.com/apk/res/android" - android:colorAccent="@*android:color/hidden" />)EOF"); + android:colorAccent="@*android:color/hidden" />)"); XmlReferenceLinker linker; ASSERT_TRUE(linker.Consume(context_.get(), doc.get())); } TEST_F(XmlReferenceLinkerTest, LinkMangledAttributes) { - std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF( - <View xmlns:support="http://schemas.android.com/apk/res/com.android.support" - support:colorAccent="#ff0000" />)EOF"); + std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"( + <View xmlns:support="http://schemas.android.com/apk/res/com.android.support" + support:colorAccent="#ff0000" />)"); XmlReferenceLinker linker; ASSERT_TRUE(linker.Consume(context_.get(), doc.get())); - xml::Element* view_el = xml::FindRootElement(doc.get()); + xml::Element* view_el = doc->root.get(); ASSERT_THAT(view_el, NotNull()); xml::Attribute* xml_attr = @@ -175,14 +175,14 @@ TEST_F(XmlReferenceLinkerTest, LinkMangledAttributes) { } TEST_F(XmlReferenceLinkerTest, LinkAutoResReference) { - std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF( - <View xmlns:app="http://schemas.android.com/apk/res-auto" - app:colorAccent="@app:color/red" />)EOF"); + std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"( + <View xmlns:app="http://schemas.android.com/apk/res-auto" + app:colorAccent="@app:color/red" />)"); XmlReferenceLinker linker; ASSERT_TRUE(linker.Consume(context_.get(), doc.get())); - xml::Element* view_el = xml::FindRootElement(doc.get()); + xml::Element* view_el = doc->root.get(); ASSERT_THAT(view_el, NotNull()); xml::Attribute* xml_attr = view_el->FindAttribute(xml::kSchemaAuto, "colorAccent"); @@ -196,17 +196,15 @@ TEST_F(XmlReferenceLinkerTest, LinkAutoResReference) { } TEST_F(XmlReferenceLinkerTest, LinkViewWithShadowedPackageAlias) { - std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF( - <View xmlns:app="http://schemas.android.com/apk/res/android" - app:attr="@app:id/id"> - <View xmlns:app="http://schemas.android.com/apk/res/com.app.test" - app:attr="@app:id/id"/> - </View>)EOF"); + std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"( + <View xmlns:app="http://schemas.android.com/apk/res/android" app:attr="@app:id/id"> + <View xmlns:app="http://schemas.android.com/apk/res/com.app.test" app:attr="@app:id/id"/> + </View>)"); XmlReferenceLinker linker; ASSERT_TRUE(linker.Consume(context_.get(), doc.get())); - xml::Element* view_el = xml::FindRootElement(doc.get()); + xml::Element* view_el = doc->root.get(); ASSERT_THAT(view_el, NotNull()); // All attributes and references in this element should be referring to @@ -235,14 +233,14 @@ TEST_F(XmlReferenceLinkerTest, LinkViewWithShadowedPackageAlias) { } TEST_F(XmlReferenceLinkerTest, LinkViewWithLocalPackageAndAliasOfTheSameName) { - std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF( - <View xmlns:android="http://schemas.android.com/apk/res/com.app.test" - android:attr="@id/id"/>)EOF"); + std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"( + <View xmlns:android="http://schemas.android.com/apk/res/com.app.test" + android:attr="@id/id"/>)"); XmlReferenceLinker linker; ASSERT_TRUE(linker.Consume(context_.get(), doc.get())); - xml::Element* view_el = xml::FindRootElement(doc.get()); + xml::Element* view_el = doc->root.get(); ASSERT_THAT(view_el, NotNull()); // All attributes and references in this element should be referring to diff --git a/tools/aapt2/optimize/MultiApkGenerator.cpp b/tools/aapt2/optimize/MultiApkGenerator.cpp new file mode 100644 index 000000000000..e7a4f8578529 --- /dev/null +++ b/tools/aapt2/optimize/MultiApkGenerator.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MultiApkGenerator.h" + +#include <algorithm> +#include <string> + +#include "androidfw/StringPiece.h" + +#include "LoadedApk.h" +#include "configuration/ConfigurationParser.h" +#include "filter/AbiFilter.h" +#include "filter/Filter.h" +#include "flatten/Archive.h" +#include "process/IResourceTableConsumer.h" +#include "split/TableSplitter.h" +#include "util/Files.h" + +namespace aapt { + +using ::aapt::configuration::Artifact; +using ::aapt::configuration::PostProcessingConfiguration; +using ::android::StringPiece; + +MultiApkGenerator::MultiApkGenerator(LoadedApk* apk, IAaptContext* context) + : apk_(apk), context_(context) { +} + +bool MultiApkGenerator::FromBaseApk(const std::string& out_dir, + const PostProcessingConfiguration& config, + const TableFlattenerOptions& table_flattener_options) { + // TODO(safarmer): Handle APK version codes for the generated APKs. + IDiagnostics* diag = context_->GetDiagnostics(); + + const std::string& apk_name = file::GetFilename(apk_->GetSource().path).to_string(); + const StringPiece ext = file::GetExtension(apk_name); + const std::string base_name = apk_name.substr(0, apk_name.rfind(ext.to_string())); + + // For now, just write out the stripped APK since ABI splitting doesn't modify anything else. + for (const Artifact& artifact : config.artifacts) { + FilterChain filters; + TableSplitterOptions splits; + AxisConfigFilter axis_filter; + + if (!artifact.name && !config.artifact_format) { + diag->Error( + DiagMessage() << "Artifact does not have a name and no global name template defined"); + return false; + } + + Maybe<std::string> artifact_name = + (artifact.name) ? artifact.Name(apk_name, diag) + : artifact.ToArtifactName(config.artifact_format.value(), apk_name, diag); + + if (!artifact_name) { + diag->Error(DiagMessage() << "Could not determine split APK artifact name"); + return false; + } + + if (artifact.abi_group) { + const std::string& group_name = artifact.abi_group.value(); + + auto group = config.abi_groups.find(group_name); + // TODO: Remove validation when configuration parser ensures referential integrity. + if (group == config.abi_groups.end()) { + diag->Error(DiagMessage() << "could not find referenced ABI group '" << group_name << "'"); + return false; + } + filters.AddFilter(AbiFilter::FromAbiList(group->second)); + } + + if (artifact.screen_density_group) { + const std::string& group_name = artifact.screen_density_group.value(); + + auto group = config.screen_density_groups.find(group_name); + // TODO: Remove validation when configuration parser ensures referential integrity. + if (group == config.screen_density_groups.end()) { + diag->Error(DiagMessage() << "could not find referenced group '" << group_name << "'"); + return false; + } + + const std::vector<ConfigDescription>& densities = group->second; + std::for_each(densities.begin(), densities.end(), [&](const ConfigDescription& c) { + splits.preferred_densities.push_back(c.density); + }); + } + + if (artifact.locale_group) { + const std::string& group_name = artifact.locale_group.value(); + auto group = config.locale_groups.find(group_name); + // TODO: Remove validation when configuration parser ensures referential integrity. + if (group == config.locale_groups.end()) { + diag->Error(DiagMessage() << "could not find referenced group '" << group_name << "'"); + return false; + } + + const std::vector<ConfigDescription>& locales = group->second; + std::for_each(locales.begin(), locales.end(), + [&](const ConfigDescription& c) { axis_filter.AddConfig(c); }); + splits.config_filter = &axis_filter; + } + + std::unique_ptr<ResourceTable> table = apk_->GetResourceTable()->Clone(); + + + TableSplitter splitter{{}, splits}; + splitter.SplitTable(table.get()); + + std::string out = out_dir; + if (!file::mkdirs(out)) { + context_->GetDiagnostics()->Warn(DiagMessage() << "could not create out dir: " << out); + } + file::AppendPath(&out, artifact_name.value()); + + std::unique_ptr<IArchiveWriter> writer = CreateZipFileArchiveWriter(diag, out); + + if (context_->IsVerbose()) { + diag->Note(DiagMessage() << "Writing output: " << out); + } + + if (!apk_->WriteToArchive(context_, table.get(), table_flattener_options, &filters, + writer.get())) { + return false; + } + } + + return true; +} + +} // namespace aapt diff --git a/tools/aapt2/optimize/MultiApkGenerator.h b/tools/aapt2/optimize/MultiApkGenerator.h new file mode 100644 index 000000000000..f325d83053f4 --- /dev/null +++ b/tools/aapt2/optimize/MultiApkGenerator.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AAPT2_APKSPLITTER_H +#define AAPT2_APKSPLITTER_H + +#include "Diagnostics.h" +#include "LoadedApk.h" +#include "configuration/ConfigurationParser.h" + +namespace aapt { + +/** + * Generates a set of APKs that are a subset of the original base APKs. Each of the new APKs contain + * only the resources and assets for an artifact in the configuration file. + */ +class MultiApkGenerator { + public: + MultiApkGenerator(LoadedApk* apk, IAaptContext* context); + + /** + * Writes a set of APKs to the provided output directory. Each APK is a subset fo the base APK and + * represents an artifact in the post processing configuration. + */ + bool FromBaseApk(const std::string& out_dir, + const configuration::PostProcessingConfiguration& config, + const TableFlattenerOptions& table_flattener_options); + + private: + IDiagnostics* GetDiagnostics() { + return context_->GetDiagnostics(); + } + + LoadedApk* apk_; + IAaptContext* context_; +}; + +} // namespace aapt + +#endif // AAPT2_APKSPLITTER_H diff --git a/tools/aapt2/optimize/MultiApkGenerator_test.cpp b/tools/aapt2/optimize/MultiApkGenerator_test.cpp new file mode 100644 index 000000000000..6c928d94e879 --- /dev/null +++ b/tools/aapt2/optimize/MultiApkGenerator_test.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "optimize/MultiApkGenerator.h" + +#include <string> + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include "LoadedApk.h" +#include "ResourceTable.h" +#include "configuration/ConfigurationParser.h" +#include "filter/Filter.h" +#include "flatten/Archive.h" +#include "flatten/TableFlattener.h" +#include "process/IResourceTableConsumer.h" +#include "test/Context.h" +#include "test/Test.h" + +namespace aapt { +namespace { + +using ::aapt::configuration::Abi; +using ::aapt::configuration::Artifact; +using ::aapt::configuration::PostProcessingConfiguration; + +using ::testing::Eq; +using ::testing::Return; +using ::testing::_; + +class MockApk : public LoadedApk { + public: + MockApk(std::unique_ptr<ResourceTable> table) : LoadedApk({"test.apk"}, {}, std::move(table)){}; + MOCK_METHOD5(WriteToArchive, bool(IAaptContext*, ResourceTable*, const TableFlattenerOptions&, + FilterChain*, IArchiveWriter*)); +}; + +TEST(MultiApkGeneratorTest, FromBaseApk) { + std::unique_ptr<ResourceTable> table = + test::ResourceTableBuilder() + .AddFileReference("android:drawable/icon", "res/drawable-mdpi/icon.png", + test::ParseConfigOrDie("mdpi")) + .AddFileReference("android:drawable/icon", "res/drawable-hdpi/icon.png", + test::ParseConfigOrDie("hdpi")) + .AddFileReference("android:drawable/icon", "res/drawable-xhdpi/icon.png", + test::ParseConfigOrDie("xhdpi")) + .AddFileReference("android:drawable/icon", "res/drawable-xxhdpi/icon.png", + test::ParseConfigOrDie("xxhdpi")) + .AddSimple("android:string/one") + .Build(); + + MockApk apk{std::move(table)}; + + EXPECT_CALL(apk, WriteToArchive(_, _, _, _, _)).Times(0); + + test::Context ctx; + PostProcessingConfiguration empty_config; + TableFlattenerOptions table_flattener_options; + + MultiApkGenerator generator{&apk, &ctx}; + EXPECT_TRUE(generator.FromBaseApk("out", empty_config, table_flattener_options)); + + Artifact x64 = test::ArtifactBuilder() + .SetName("${basename}.x64.apk") + .SetAbiGroup("x64") + .SetLocaleGroup("en") + .SetDensityGroup("xhdpi") + .Build(); + + Artifact intel = test::ArtifactBuilder() + .SetName("${basename}.intel.apk") + .SetAbiGroup("intel") + .SetLocaleGroup("europe") + .SetDensityGroup("large") + .Build(); + + auto config = test::PostProcessingConfigurationBuilder() + .SetLocaleGroup("en", {"en"}) + .SetLocaleGroup("europe", {"en", "fr", "de", "es"}) + .SetAbiGroup("x64", {Abi::kX86_64}) + .SetAbiGroup("intel", {Abi::kX86_64, Abi::kX86}) + .SetDensityGroup("xhdpi", {"xhdpi"}) + .SetDensityGroup("large", {"xhdpi", "xxhdpi", "xxxhdpi"}) + .AddArtifact(x64) + .AddArtifact(intel) + .Build(); + + // Called once for each artifact. + EXPECT_CALL(apk, WriteToArchive(Eq(&ctx), _, _, _, _)).Times(2).WillRepeatedly(Return(true)); + EXPECT_TRUE(generator.FromBaseApk("out", config, table_flattener_options)); +} + +} // namespace +} // namespace aapt diff --git a/tools/aapt2/proto/ProtoHelpers.cpp b/tools/aapt2/proto/ProtoHelpers.cpp index 6b21364b5eb2..aa99c982f6ae 100644 --- a/tools/aapt2/proto/ProtoHelpers.cpp +++ b/tools/aapt2/proto/ProtoHelpers.cpp @@ -36,7 +36,7 @@ void SerializeSourceToPb(const Source& source, StringPool* src_pool, pb::Source* StringPool::Ref ref = src_pool->MakeRef(source.path); out_pb_source->set_path_idx(static_cast<uint32_t>(ref.index())); if (source.line) { - out_pb_source->set_line_no(static_cast<uint32_t>(source.line.value())); + out_pb_source->mutable_position()->set_line_number(static_cast<uint32_t>(source.line.value())); } } @@ -46,29 +46,28 @@ void DeserializeSourceFromPb(const pb::Source& pb_source, const android::ResStri out_source->path = util::GetString(src_pool, pb_source.path_idx()); } - if (pb_source.has_line_no()) { - out_source->line = static_cast<size_t>(pb_source.line_no()); + if (pb_source.has_position()) { + out_source->line = static_cast<size_t>(pb_source.position().line_number()); } } pb::SymbolStatus_Visibility SerializeVisibilityToPb(SymbolState state) { switch (state) { case SymbolState::kPrivate: - return pb::SymbolStatus_Visibility_Private; + return pb::SymbolStatus_Visibility_PRIVATE; case SymbolState::kPublic: - return pb::SymbolStatus_Visibility_Public; + return pb::SymbolStatus_Visibility_PUBLIC; default: break; } - return pb::SymbolStatus_Visibility_Unknown; + return pb::SymbolStatus_Visibility_UNKNOWN; } -SymbolState DeserializeVisibilityFromPb( - pb::SymbolStatus_Visibility pb_visibility) { +SymbolState DeserializeVisibilityFromPb(pb::SymbolStatus_Visibility pb_visibility) { switch (pb_visibility) { - case pb::SymbolStatus_Visibility_Private: + case pb::SymbolStatus_Visibility_PRIVATE: return SymbolState::kPrivate; - case pb::SymbolStatus_Visibility_Public: + case pb::SymbolStatus_Visibility_PUBLIC: return SymbolState::kPublic; default: break; @@ -102,20 +101,20 @@ bool DeserializeConfigDescriptionFromPb(const pb::ConfigDescription& pb_config, pb::Reference_Type SerializeReferenceTypeToPb(Reference::Type type) { switch (type) { case Reference::Type::kResource: - return pb::Reference_Type_Ref; + return pb::Reference_Type_REFERENCE; case Reference::Type::kAttribute: - return pb::Reference_Type_Attr; + return pb::Reference_Type_ATTRIBUTE; default: break; } - return pb::Reference_Type_Ref; + return pb::Reference_Type_REFERENCE; } Reference::Type DeserializeReferenceTypeFromPb(pb::Reference_Type pb_type) { switch (pb_type) { - case pb::Reference_Type_Ref: + case pb::Reference_Type_REFERENCE: return Reference::Type::kResource; - case pb::Reference_Type_Attr: + case pb::Reference_Type_ATTRIBUTE: return Reference::Type::kAttribute; default: break; @@ -126,32 +125,32 @@ Reference::Type DeserializeReferenceTypeFromPb(pb::Reference_Type pb_type) { pb::Plural_Arity SerializePluralEnumToPb(size_t plural_idx) { switch (plural_idx) { case Plural::Zero: - return pb::Plural_Arity_Zero; + return pb::Plural_Arity_ZERO; case Plural::One: - return pb::Plural_Arity_One; + return pb::Plural_Arity_ONE; case Plural::Two: - return pb::Plural_Arity_Two; + return pb::Plural_Arity_TWO; case Plural::Few: - return pb::Plural_Arity_Few; + return pb::Plural_Arity_FEW; case Plural::Many: - return pb::Plural_Arity_Many; + return pb::Plural_Arity_MANY; default: break; } - return pb::Plural_Arity_Other; + return pb::Plural_Arity_OTHER; } size_t DeserializePluralEnumFromPb(pb::Plural_Arity arity) { switch (arity) { - case pb::Plural_Arity_Zero: + case pb::Plural_Arity_ZERO: return Plural::Zero; - case pb::Plural_Arity_One: + case pb::Plural_Arity_ONE: return Plural::One; - case pb::Plural_Arity_Two: + case pb::Plural_Arity_TWO: return Plural::Two; - case pb::Plural_Arity_Few: + case pb::Plural_Arity_FEW: return Plural::Few; - case pb::Plural_Arity_Many: + case pb::Plural_Arity_MANY: return Plural::Many; default: break; diff --git a/tools/aapt2/proto/ProtoHelpers.h b/tools/aapt2/proto/ProtoHelpers.h index 344e9477ea71..2f268f44752c 100644 --- a/tools/aapt2/proto/ProtoHelpers.h +++ b/tools/aapt2/proto/ProtoHelpers.h @@ -23,27 +23,23 @@ #include "ResourceTable.h" #include "Source.h" #include "StringPool.h" -#include "Format.pb.h" +#include "Resources.pb.h" +#include "ResourcesInternal.pb.h" namespace aapt { -void SerializeStringPoolToPb(const StringPool& pool, - pb::StringPool* out_pb_pool); +void SerializeStringPoolToPb(const StringPool& pool, pb::StringPool* out_pb_pool); -void SerializeSourceToPb(const Source& source, StringPool* src_pool, - pb::Source* out_pb_source); +void SerializeSourceToPb(const Source& source, StringPool* src_pool, pb::Source* out_pb_source); -void DeserializeSourceFromPb(const pb::Source& pb_source, - const android::ResStringPool& src_pool, +void DeserializeSourceFromPb(const pb::Source& pb_source, const android::ResStringPool& src_pool, Source* out_source); pb::SymbolStatus_Visibility SerializeVisibilityToPb(SymbolState state); -SymbolState DeserializeVisibilityFromPb( - pb::SymbolStatus_Visibility pb_visibility); +SymbolState DeserializeVisibilityFromPb(pb::SymbolStatus_Visibility pb_visibility); -void SerializeConfig(const ConfigDescription& config, - pb::ConfigDescription* out_pb_config); +void SerializeConfig(const ConfigDescription& config, pb::ConfigDescription* out_pb_config); bool DeserializeConfigDescriptionFromPb(const pb::ConfigDescription& pb_config, ConfigDescription* out_config); diff --git a/tools/aapt2/proto/ProtoSerialize.h b/tools/aapt2/proto/ProtoSerialize.h index 39c50038d599..8c46642e9090 100644 --- a/tools/aapt2/proto/ProtoSerialize.h +++ b/tools/aapt2/proto/ProtoSerialize.h @@ -30,11 +30,10 @@ namespace aapt { class CompiledFileOutputStream { public: - explicit CompiledFileOutputStream( - google::protobuf::io::ZeroCopyOutputStream* out); + explicit CompiledFileOutputStream(google::protobuf::io::ZeroCopyOutputStream* out); void WriteLittleEndian32(uint32_t value); - void WriteCompiledFile(const pb::CompiledFile* compiledFile); + void WriteCompiledFile(const pb::internal::CompiledFile* compiledFile); void WriteData(const BigBuffer* buffer); void WriteData(const void* data, size_t len); bool HadError(); @@ -52,7 +51,7 @@ class CompiledFileInputStream { explicit CompiledFileInputStream(const void* data, size_t size); bool ReadLittleEndian32(uint32_t* outVal); - bool ReadCompiledFile(pb::CompiledFile* outVal); + bool ReadCompiledFile(pb::internal::CompiledFile* outVal); bool ReadDataMetaData(uint64_t* outOffset, uint64_t* outLen); private: @@ -64,13 +63,12 @@ class CompiledFileInputStream { }; std::unique_ptr<pb::ResourceTable> SerializeTableToPb(ResourceTable* table); -std::unique_ptr<ResourceTable> DeserializeTableFromPb( - const pb::ResourceTable& pbTable, const Source& source, IDiagnostics* diag); +std::unique_ptr<ResourceTable> DeserializeTableFromPb(const pb::ResourceTable& pbTable, + const Source& source, IDiagnostics* diag); -std::unique_ptr<pb::CompiledFile> SerializeCompiledFileToPb( - const ResourceFile& file); +std::unique_ptr<pb::internal::CompiledFile> SerializeCompiledFileToPb(const ResourceFile& file); std::unique_ptr<ResourceFile> DeserializeCompiledFileFromPb( - const pb::CompiledFile& pbFile, const Source& source, IDiagnostics* diag); + const pb::internal::CompiledFile& pbFile, const Source& source, IDiagnostics* diag); } // namespace aapt diff --git a/tools/aapt2/proto/TableProtoDeserializer.cpp b/tools/aapt2/proto/TableProtoDeserializer.cpp index e891954bc523..b9d5878f2f71 100644 --- a/tools/aapt2/proto/TableProtoDeserializer.cpp +++ b/tools/aapt2/proto/TableProtoDeserializer.cpp @@ -61,54 +61,55 @@ class PackagePbDeserializer { } public: - bool DeserializeFromPb(const pb::Package& pbPackage, ResourceTable* table) { + bool DeserializeFromPb(const pb::Package& pb_package, ResourceTable* table) { Maybe<uint8_t> id; - if (pbPackage.has_package_id()) { - id = static_cast<uint8_t>(pbPackage.package_id()); + if (pb_package.has_package_id()) { + id = static_cast<uint8_t>(pb_package.package_id()); } - std::map<ResourceId, ResourceNameRef> idIndex; + std::map<ResourceId, ResourceNameRef> id_index; - ResourceTablePackage* pkg = table->CreatePackage(pbPackage.package_name(), id); - for (const pb::Type& pbType : pbPackage.types()) { - const ResourceType* resType = ParseResourceType(pbType.name()); - if (!resType) { - diag_->Error(DiagMessage(source_) << "unknown type '" << pbType.name() << "'"); + ResourceTablePackage* pkg = table->CreatePackage(pb_package.package_name(), id); + for (const pb::Type& pb_type : pb_package.type()) { + const ResourceType* res_type = ParseResourceType(pb_type.name()); + if (res_type == nullptr) { + diag_->Error(DiagMessage(source_) << "unknown type '" << pb_type.name() << "'"); return {}; } - ResourceTableType* type = pkg->FindOrCreateType(*resType); + ResourceTableType* type = pkg->FindOrCreateType(*res_type); - for (const pb::Entry& pbEntry : pbType.entries()) { - ResourceEntry* entry = type->FindOrCreateEntry(pbEntry.name()); + for (const pb::Entry& pb_entry : pb_type.entry()) { + ResourceEntry* entry = type->FindOrCreateEntry(pb_entry.name()); // Deserialize the symbol status (public/private with source and comments). - if (pbEntry.has_symbol_status()) { - const pb::SymbolStatus& pbStatus = pbEntry.symbol_status(); - if (pbStatus.has_source()) { - DeserializeSourceFromPb(pbStatus.source(), *source_pool_, &entry->symbol_status.source); + if (pb_entry.has_symbol_status()) { + const pb::SymbolStatus& pb_status = pb_entry.symbol_status(); + if (pb_status.has_source()) { + DeserializeSourceFromPb(pb_status.source(), *source_pool_, + &entry->symbol_status.source); } - if (pbStatus.has_comment()) { - entry->symbol_status.comment = pbStatus.comment(); + if (pb_status.has_comment()) { + entry->symbol_status.comment = pb_status.comment(); } - entry->symbol_status.allow_new = pbStatus.allow_new(); + entry->symbol_status.allow_new = pb_status.allow_new(); - SymbolState visibility = DeserializeVisibilityFromPb(pbStatus.visibility()); + SymbolState visibility = DeserializeVisibilityFromPb(pb_status.visibility()); entry->symbol_status.state = visibility; if (visibility == SymbolState::kPublic) { // This is a public symbol, we must encode the ID now if there is one. - if (pbEntry.has_id()) { - entry->id = static_cast<uint16_t>(pbEntry.id()); + if (pb_entry.has_id()) { + entry->id = static_cast<uint16_t>(pb_entry.id()); } if (type->symbol_status.state != SymbolState::kPublic) { // If the type has not been made public, do so now. type->symbol_status.state = SymbolState::kPublic; - if (pbType.has_id()) { - type->id = static_cast<uint8_t>(pbType.id()); + if (pb_type.has_id()) { + type->id = static_cast<uint8_t>(pb_type.id()); } } } else if (visibility == SymbolState::kPrivate) { @@ -118,37 +119,37 @@ class PackagePbDeserializer { } } - ResourceId resId(pbPackage.package_id(), pbType.id(), pbEntry.id()); - if (resId.is_valid()) { - idIndex[resId] = ResourceNameRef(pkg->name, type->type, entry->name); + ResourceId resid(pb_package.package_id(), pb_type.id(), pb_entry.id()); + if (resid.is_valid()) { + id_index[resid] = ResourceNameRef(pkg->name, type->type, entry->name); } - for (const pb::ConfigValue& pbConfigValue : pbEntry.config_values()) { - const pb::ConfigDescription& pbConfig = pbConfigValue.config(); + for (const pb::ConfigValue& pb_config_value : pb_entry.config_value()) { + const pb::ConfigDescription& pb_config = pb_config_value.config(); ConfigDescription config; - if (!DeserializeConfigDescriptionFromPb(pbConfig, &config)) { + if (!DeserializeConfigDescriptionFromPb(pb_config, &config)) { diag_->Error(DiagMessage(source_) << "invalid configuration"); return {}; } - ResourceConfigValue* configValue = entry->FindOrCreateValue(config, pbConfig.product()); - if (configValue->value) { + ResourceConfigValue* config_value = entry->FindOrCreateValue(config, pb_config.product()); + if (config_value->value) { // Duplicate config. diag_->Error(DiagMessage(source_) << "duplicate configuration"); return {}; } - configValue->value = - DeserializeValueFromPb(pbConfigValue.value(), config, &table->string_pool); - if (!configValue->value) { + config_value->value = + DeserializeValueFromPb(pb_config_value.value(), config, &table->string_pool); + if (!config_value->value) { return {}; } } } } - ReferenceIdToNameVisitor visitor(&idIndex); + ReferenceIdToNameVisitor visitor(&id_index); VisitAllValuesInPackage(pkg, &visitor); return true; } @@ -202,8 +203,6 @@ class PackagePbDeserializer { std::unique_ptr<Value> DeserializeValueFromPb(const pb::Value& pb_value, const ConfigDescription& config, StringPool* pool) { - const bool is_weak = pb_value.has_weak() ? pb_value.weak() : false; - std::unique_ptr<Value> value; if (pb_value.has_item()) { value = DeserializeItemFromPb(pb_value.item(), config, pool); @@ -215,11 +214,11 @@ class PackagePbDeserializer { const pb::CompoundValue& pb_compound_value = pb_value.compound_value(); if (pb_compound_value.has_attr()) { const pb::Attribute& pb_attr = pb_compound_value.attr(); - std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(is_weak); + std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(); attr->type_mask = pb_attr.format_flags(); attr->min_int = pb_attr.min_int(); attr->max_int = pb_attr.max_int(); - for (const pb::Attribute_Symbol& pb_symbol : pb_attr.symbols()) { + for (const pb::Attribute_Symbol& pb_symbol : pb_attr.symbol()) { Attribute::Symbol symbol; DeserializeItemCommon(pb_symbol, &symbol.symbol); if (!DeserializeReferenceFromPb(pb_symbol.name(), &symbol.symbol)) { @@ -246,7 +245,7 @@ class PackagePbDeserializer { } } - for (const pb::Style_Entry& pb_entry : pb_style.entries()) { + for (const pb::Style_Entry& pb_entry : pb_style.entry()) { Style::Entry entry; DeserializeItemCommon(pb_entry, &entry.key); if (!DeserializeReferenceFromPb(pb_entry.key(), &entry.key)) { @@ -266,7 +265,7 @@ class PackagePbDeserializer { } else if (pb_compound_value.has_styleable()) { const pb::Styleable& pb_styleable = pb_compound_value.styleable(); std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>(); - for (const pb::Styleable_Entry& pb_entry : pb_styleable.entries()) { + for (const pb::Styleable_Entry& pb_entry : pb_styleable.entry()) { Reference attr_ref; DeserializeItemCommon(pb_entry, &attr_ref); DeserializeReferenceFromPb(pb_entry.attr(), &attr_ref); @@ -277,21 +276,21 @@ class PackagePbDeserializer { } else if (pb_compound_value.has_array()) { const pb::Array& pb_array = pb_compound_value.array(); std::unique_ptr<Array> array = util::make_unique<Array>(); - for (const pb::Array_Entry& pb_entry : pb_array.entries()) { + for (const pb::Array_Element& pb_entry : pb_array.element()) { std::unique_ptr<Item> item = DeserializeItemFromPb(pb_entry.item(), config, pool); if (!item) { return {}; } DeserializeItemCommon(pb_entry, item.get()); - array->items.push_back(std::move(item)); + array->elements.push_back(std::move(item)); } value = std::move(array); } else if (pb_compound_value.has_plural()) { const pb::Plural& pb_plural = pb_compound_value.plural(); std::unique_ptr<Plural> plural = util::make_unique<Plural>(); - for (const pb::Plural_Entry& pb_entry : pb_plural.entries()) { + for (const pb::Plural_Entry& pb_entry : pb_plural.entry()) { size_t pluralIdx = DeserializePluralEnumFromPb(pb_entry.arity()); plural->values[pluralIdx] = DeserializeItemFromPb(pb_entry.item(), config, pool); if (!plural->values[pluralIdx]) { @@ -313,7 +312,7 @@ class PackagePbDeserializer { CHECK(value) << "forgot to set value"; - value->SetWeak(is_weak); + value->SetWeak(pb_value.weak()); DeserializeItemCommon(pb_value, value.get()); return value; } @@ -378,7 +377,7 @@ std::unique_ptr<ResourceTable> DeserializeTableFromPb(const pb::ResourceTable& p } PackagePbDeserializer package_pb_deserializer(&source_pool, source, diag); - for (const pb::Package& pb_package : pb_table.packages()) { + for (const pb::Package& pb_package : pb_table.package()) { if (!package_pb_deserializer.DeserializeFromPb(pb_package, table.get())) { return {}; } @@ -387,7 +386,7 @@ std::unique_ptr<ResourceTable> DeserializeTableFromPb(const pb::ResourceTable& p } std::unique_ptr<ResourceFile> DeserializeCompiledFileFromPb( - const pb::CompiledFile& pb_file, const Source& source, IDiagnostics* diag) { + const pb::internal::CompiledFile& pb_file, const Source& source, IDiagnostics* diag) { std::unique_ptr<ResourceFile> file = util::make_unique<ResourceFile>(); ResourceNameRef name_ref; @@ -403,19 +402,20 @@ std::unique_ptr<ResourceFile> DeserializeCompiledFileFromPb( file->source.path = pb_file.source_path(); DeserializeConfigDescriptionFromPb(pb_file.config(), &file->config); - for (const pb::CompiledFile_Symbol& pb_symbol : pb_file.exported_symbols()) { - // Need to create an lvalue here so that nameRef can point to something - // real. - if (!ResourceUtils::ParseResourceName(pb_symbol.resource_name(), - &name_ref)) { + for (const pb::internal::CompiledFile_Symbol& pb_symbol : pb_file.exported_symbol()) { + // Need to create an lvalue here so that nameRef can point to something real. + if (!ResourceUtils::ParseResourceName(pb_symbol.resource_name(), &name_ref)) { diag->Error(DiagMessage(source) << "invalid resource name for exported symbol in " "compiled file header: " << pb_file.resource_name()); return {}; } - file->exported_symbols.push_back( - SourcedResourceName{name_ref.ToResourceName(), pb_symbol.line_no()}); + size_t line = 0u; + if (pb_symbol.has_source()) { + line = pb_symbol.source().line_number(); + } + file->exported_symbols.push_back(SourcedResourceName{name_ref.ToResourceName(), line}); } return file; } diff --git a/tools/aapt2/proto/TableProtoSerializer.cpp b/tools/aapt2/proto/TableProtoSerializer.cpp index 3f486556da78..a08df71eae1e 100644 --- a/tools/aapt2/proto/TableProtoSerializer.cpp +++ b/tools/aapt2/proto/TableProtoSerializer.cpp @@ -98,7 +98,7 @@ class PbSerializerVisitor : public RawValueVisitor { pb_attr->set_max_int(attr->max_int); for (auto& symbol : attr->symbols) { - pb::Attribute_Symbol* pb_symbol = pb_attr->add_symbols(); + pb::Attribute_Symbol* pb_symbol = pb_attr->add_symbol(); SerializeItemCommonToPb(symbol.symbol, pb_symbol); SerializeReferenceToPb(symbol.symbol, pb_symbol->mutable_name()); pb_symbol->set_value(symbol.value); @@ -114,7 +114,7 @@ class PbSerializerVisitor : public RawValueVisitor { } for (Style::Entry& entry : style->entries) { - pb::Style_Entry* pb_entry = pb_style->add_entries(); + pb::Style_Entry* pb_entry = pb_style->add_entry(); SerializeReferenceToPb(entry.key, pb_entry->mutable_key()); pb::Item* pb_item = pb_entry->mutable_item(); @@ -127,7 +127,7 @@ class PbSerializerVisitor : public RawValueVisitor { void Visit(Styleable* styleable) override { pb::Styleable* pb_styleable = pb_compound_value()->mutable_styleable(); for (Reference& entry : styleable->entries) { - pb::Styleable_Entry* pb_entry = pb_styleable->add_entries(); + pb::Styleable_Entry* pb_entry = pb_styleable->add_entry(); SerializeItemCommonToPb(entry, pb_entry); SerializeReferenceToPb(entry, pb_entry->mutable_attr()); } @@ -135,10 +135,10 @@ class PbSerializerVisitor : public RawValueVisitor { void Visit(Array* array) override { pb::Array* pb_array = pb_compound_value()->mutable_array(); - for (auto& value : array->items) { - pb::Array_Entry* pb_entry = pb_array->add_entries(); - SerializeItemCommonToPb(*value, pb_entry); - PbSerializerVisitor sub_visitor(source_pool_, pb_entry->mutable_item()); + for (auto& value : array->elements) { + pb::Array_Element* pb_element = pb_array->add_element(); + SerializeItemCommonToPb(*value, pb_element); + PbSerializerVisitor sub_visitor(source_pool_, pb_element->mutable_item()); value->Accept(&sub_visitor); } } @@ -152,7 +152,7 @@ class PbSerializerVisitor : public RawValueVisitor { continue; } - pb::Plural_Entry* pb_entry = pb_plural->add_entries(); + pb::Plural_Entry* pb_entry = pb_plural->add_entry(); pb_entry->set_arity(SerializePluralEnumToPb(i)); pb::Item* pb_element = pb_entry->mutable_item(); SerializeItemCommonToPb(*plural->values[i], pb_entry); @@ -219,21 +219,21 @@ std::unique_ptr<pb::ResourceTable> SerializeTableToPb(ResourceTable* table) { StringPool source_pool; for (auto& package : table->packages) { - pb::Package* pb_package = pb_table->add_packages(); + pb::Package* pb_package = pb_table->add_package(); if (package->id) { pb_package->set_package_id(package->id.value()); } pb_package->set_package_name(package->name); for (auto& type : package->types) { - pb::Type* pb_type = pb_package->add_types(); + pb::Type* pb_type = pb_package->add_type(); if (type->id) { pb_type->set_id(type->id.value()); } pb_type->set_name(ToString(type->type).to_string()); for (auto& entry : type->entries) { - pb::Entry* pb_entry = pb_type->add_entries(); + pb::Entry* pb_entry = pb_type->add_entry(); if (entry->id) { pb_entry->set_id(entry->id.value()); } @@ -247,7 +247,7 @@ std::unique_ptr<pb::ResourceTable> SerializeTableToPb(ResourceTable* table) { pb_status->set_allow_new(entry->symbol_status.allow_new); for (auto& config_value : entry->values) { - pb::ConfigValue* pb_config_value = pb_entry->add_config_values(); + pb::ConfigValue* pb_config_value = pb_entry->add_config_value(); SerializeConfig(config_value->config, pb_config_value->mutable_config()); if (!config_value->product.empty()) { pb_config_value->mutable_config()->set_product(config_value->product); @@ -275,23 +275,22 @@ std::unique_ptr<pb::ResourceTable> SerializeTableToPb(ResourceTable* table) { return pb_table; } -std::unique_ptr<pb::CompiledFile> SerializeCompiledFileToPb( - const ResourceFile& file) { - auto pb_file = util::make_unique<pb::CompiledFile>(); +std::unique_ptr<pb::internal::CompiledFile> SerializeCompiledFileToPb(const ResourceFile& file) { + auto pb_file = util::make_unique<pb::internal::CompiledFile>(); pb_file->set_resource_name(file.name.ToString()); pb_file->set_source_path(file.source.path); SerializeConfig(file.config, pb_file->mutable_config()); for (const SourcedResourceName& exported : file.exported_symbols) { - pb::CompiledFile_Symbol* pb_symbol = pb_file->add_exported_symbols(); + pb::internal::CompiledFile_Symbol* pb_symbol = pb_file->add_exported_symbol(); pb_symbol->set_resource_name(exported.name.ToString()); - pb_symbol->set_line_no(exported.line); + pb_symbol->mutable_source()->set_line_number(exported.line); } return pb_file; } -CompiledFileOutputStream::CompiledFileOutputStream(ZeroCopyOutputStream* out) - : out_(out) {} +CompiledFileOutputStream::CompiledFileOutputStream(ZeroCopyOutputStream* out) : out_(out) { +} void CompiledFileOutputStream::EnsureAlignedWrite() { const int padding = out_.ByteCount() % 4; @@ -306,8 +305,7 @@ void CompiledFileOutputStream::WriteLittleEndian32(uint32_t val) { out_.WriteLittleEndian32(val); } -void CompiledFileOutputStream::WriteCompiledFile( - const pb::CompiledFile* compiled_file) { +void CompiledFileOutputStream::WriteCompiledFile(const pb::internal::CompiledFile* compiled_file) { EnsureAlignedWrite(); out_.WriteLittleEndian64(static_cast<uint64_t>(compiled_file->ByteSize())); compiled_file->SerializeWithCachedSizes(&out_); @@ -327,7 +325,9 @@ void CompiledFileOutputStream::WriteData(const void* data, size_t len) { out_.WriteRaw(data, len); } -bool CompiledFileOutputStream::HadError() { return out_.HadError(); } +bool CompiledFileOutputStream::HadError() { + return out_.HadError(); +} CompiledFileInputStream::CompiledFileInputStream(const void* data, size_t size) : in_(static_cast<const uint8_t*>(data), size) {} @@ -345,7 +345,7 @@ bool CompiledFileInputStream::ReadLittleEndian32(uint32_t* out_val) { return in_.ReadLittleEndian32(out_val); } -bool CompiledFileInputStream::ReadCompiledFile(pb::CompiledFile* out_val) { +bool CompiledFileInputStream::ReadCompiledFile(pb::internal::CompiledFile* out_val) { EnsureAlignedRead(); google::protobuf::uint64 pb_size = 0u; @@ -372,8 +372,7 @@ bool CompiledFileInputStream::ReadCompiledFile(pb::CompiledFile* out_val) { return true; } -bool CompiledFileInputStream::ReadDataMetaData(uint64_t* out_offset, - uint64_t* out_len) { +bool CompiledFileInputStream::ReadDataMetaData(uint64_t* out_offset, uint64_t* out_len) { EnsureAlignedRead(); google::protobuf::uint64 pb_size = 0u; diff --git a/tools/aapt2/proto/TableProtoSerializer_test.cpp b/tools/aapt2/proto/TableProtoSerializer_test.cpp index 3ba4e6b5cb72..80608b3d9c05 100644 --- a/tools/aapt2/proto/TableProtoSerializer_test.cpp +++ b/tools/aapt2/proto/TableProtoSerializer_test.cpp @@ -151,10 +151,10 @@ TEST(TableProtoSerializer, SerializeFileHeader) { std::string output_str; { - std::unique_ptr<pb::CompiledFile> pb_file1 = SerializeCompiledFileToPb(f); + std::unique_ptr<pb::internal::CompiledFile> pb_file1 = SerializeCompiledFileToPb(f); f.name.entry = "__" + f.name.entry + "$0"; - std::unique_ptr<pb::CompiledFile> pb_file2 = SerializeCompiledFileToPb(f); + std::unique_ptr<pb::internal::CompiledFile> pb_file2 = SerializeCompiledFileToPb(f); StringOutputStream out_stream(&output_str); CompiledFileOutputStream out_file_stream(&out_stream); @@ -173,7 +173,7 @@ TEST(TableProtoSerializer, SerializeFileHeader) { // Read the first compiled file. - pb::CompiledFile new_pb_file; + pb::internal::CompiledFile new_pb_file; ASSERT_TRUE(in_file_stream.ReadCompiledFile(&new_pb_file)); std::unique_ptr<ResourceFile> file = DeserializeCompiledFileFromPb( @@ -210,7 +210,7 @@ TEST(TableProtoSerializer, SerializeFileHeader) { TEST(TableProtoSerializer, DeserializeCorruptHeaderSafely) { ResourceFile f; - std::unique_ptr<pb::CompiledFile> pb_file = SerializeCompiledFileToPb(f); + std::unique_ptr<pb::internal::CompiledFile> pb_file = SerializeCompiledFileToPb(f); const std::string expected_data = "1234"; @@ -232,7 +232,7 @@ TEST(TableProtoSerializer, DeserializeCorruptHeaderSafely) { EXPECT_TRUE(in_file_stream.ReadLittleEndian32(&num_files)); EXPECT_EQ(1u, num_files); - pb::CompiledFile new_pb_file; + pb::internal::CompiledFile new_pb_file; EXPECT_FALSE(in_file_stream.ReadCompiledFile(&new_pb_file)); uint64_t offset, len; diff --git a/tools/aapt2/split/TableSplitter.cpp b/tools/aapt2/split/TableSplitter.cpp index 27e13d81ff49..9d49ca6c0aa9 100644 --- a/tools/aapt2/split/TableSplitter.cpp +++ b/tools/aapt2/split/TableSplitter.cpp @@ -32,8 +32,7 @@ namespace aapt { using ConfigClaimedMap = std::unordered_map<ResourceConfigValue*, bool>; -using ConfigDensityGroups = - std::map<ConfigDescription, std::vector<ResourceConfigValue*>>; +using ConfigDensityGroups = std::map<ConfigDescription, std::vector<ResourceConfigValue*>>; static ConfigDescription CopyWithoutDensity(const ConfigDescription& config) { ConfigDescription without_density = config; @@ -51,8 +50,7 @@ class SplitValueSelector { if (config.density == 0) { density_independent_configs_.insert(config); } else { - density_dependent_config_to_density_map_[CopyWithoutDensity(config)] = - config.density; + density_dependent_config_to_density_map_[CopyWithoutDensity(config)] = config.density; } } } @@ -94,9 +92,7 @@ class SplitValueSelector { ResourceConfigValue* best_value = nullptr; for (ResourceConfigValue* this_value : related_values) { - if (!best_value || - this_value->config.isBetterThan(best_value->config, - &target_density)) { + if (!best_value || this_value->config.isBetterThan(best_value->config, &target_density)) { best_value = this_value; } } @@ -120,9 +116,8 @@ class SplitValueSelector { }; /** - * Marking non-preferred densities as claimed will make sure the base doesn't - * include them, - * leaving only the preferred density behind. + * Marking non-preferred densities as claimed will make sure the base doesn't include them, leaving + * only the preferred density behind. */ static void MarkNonPreferredDensitiesAsClaimed( const std::vector<uint16_t>& preferred_densities, const ConfigDensityGroups& density_groups, @@ -161,8 +156,7 @@ bool TableSplitter::VerifySplitConstraints(IAaptContext* context) { for (size_t i = 0; i < split_constraints_.size(); i++) { for (size_t j = i + 1; j < split_constraints_.size(); j++) { for (const ConfigDescription& config : split_constraints_[i].configs) { - if (split_constraints_[j].configs.find(config) != - split_constraints_[j].configs.end()) { + if (split_constraints_[j].configs.find(config) != split_constraints_[j].configs.end()) { context->GetDiagnostics()->Error(DiagMessage() << "config '" << config << "' appears in multiple splits, " @@ -193,28 +187,22 @@ void TableSplitter::SplitTable(ResourceTable* original_table) { for (auto& entry : type->entries) { if (options_.config_filter) { // First eliminate any resource that we definitely don't want. - for (std::unique_ptr<ResourceConfigValue>& config_value : - entry->values) { + for (std::unique_ptr<ResourceConfigValue>& config_value : entry->values) { if (!options_.config_filter->Match(config_value->config)) { - // null out the entry. We will clean up and remove nulls at the - // end for performance reasons. + // null out the entry. We will clean up and remove nulls at the end for performance + // reasons. config_value.reset(); } } } - // Organize the values into two separate buckets. Those that are - // density-dependent - // and those that are density-independent. - // One density technically matches all density, it's just that some - // densities - // match better. So we need to be aware of the full set of densities to - // make this - // decision. + // Organize the values into two separate buckets. Those that are density-dependent and those + // that are density-independent. One density technically matches all density, it's just that + // some densities match better. So we need to be aware of the full set of densities to make + // this decision. ConfigDensityGroups density_groups; ConfigClaimedMap config_claimed_map; - for (const std::unique_ptr<ResourceConfigValue>& config_value : - entry->values) { + for (const std::unique_ptr<ResourceConfigValue>& config_value : entry->values) { if (config_value) { config_claimed_map[config_value.get()] = false; @@ -226,9 +214,8 @@ void TableSplitter::SplitTable(ResourceTable* original_table) { } } - // First we check all the splits. If it doesn't match one of the splits, - // we - // leave it in the base. + // First we check all the splits. If it doesn't match one of the splits, we leave it in the + // base. for (size_t idx = 0; idx < split_count; idx++) { const SplitConstraints& split_constraint = split_constraints_[idx]; ResourceTable* split_table = splits_[idx].get(); @@ -240,20 +227,16 @@ void TableSplitter::SplitTable(ResourceTable* original_table) { // No need to do any work if we selected nothing. if (!selected_values.empty()) { - // 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); + // 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); if (!split_type->id) { split_type->id = type->id; split_type->symbol_status = type->symbol_status; } - ResourceEntry* split_entry = - split_type->FindOrCreateEntry(entry->name); + ResourceEntry* split_entry = split_type->FindOrCreateEntry(entry->name); if (!split_entry->id) { split_entry->id = entry->id; split_entry->symbol_status = entry->symbol_status; @@ -262,8 +245,7 @@ void TableSplitter::SplitTable(ResourceTable* original_table) { // Copy the selected values into the new Split Entry. for (ResourceConfigValue* config_value : selected_values) { ResourceConfigValue* new_config_value = - split_entry->FindOrCreateValue(config_value->config, - config_value->product); + split_entry->FindOrCreateValue(config_value->config, config_value->product); new_config_value->value = std::unique_ptr<Value>( config_value->value->Clone(&split_table->string_pool)); } @@ -276,11 +258,9 @@ void TableSplitter::SplitTable(ResourceTable* original_table) { &config_claimed_map); } - // All splits are handled, now check to see what wasn't claimed and - // remove - // whatever exists in other splits. - for (std::unique_ptr<ResourceConfigValue>& config_value : - entry->values) { + // All splits are handled, now check to see what wasn't claimed and remove whatever exists + // in other splits. + for (std::unique_ptr<ResourceConfigValue>& config_value : entry->values) { if (config_value && config_claimed_map[config_value.get()]) { // Claimed, remove from base. config_value.reset(); diff --git a/tools/aapt2/test/Builders.cpp b/tools/aapt2/test/Builders.cpp index b5795451e749..57e3df442e3c 100644 --- a/tools/aapt2/test/Builders.cpp +++ b/tools/aapt2/test/Builders.cpp @@ -201,7 +201,7 @@ std::unique_ptr<xml::XmlResource> BuildXmlDom(const StringPiece& str) { StringInputStream in(input); StdErrDiagnostics diag; std::unique_ptr<xml::XmlResource> doc = xml::Inflate(&in, &diag, Source("test.xml")); - CHECK(doc != nullptr) << "failed to parse inline XML string"; + CHECK(doc != nullptr && doc->root != nullptr) << "failed to parse inline XML string"; return doc; } @@ -212,5 +212,63 @@ std::unique_ptr<xml::XmlResource> BuildXmlDomForPackageName(IAaptContext* contex return doc; } +PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::SetAbiGroup( + const std::string& name, const std::vector<configuration::Abi>& abis) { + config_.abi_groups[name] = abis; + return *this; +} + +PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::SetLocaleGroup( + const std::string& name, const std::vector<std::string>& locales) { + auto& group = config_.locale_groups[name]; + for (const auto& locale : locales) { + group.push_back(ParseConfigOrDie(locale)); + } + return *this; +} + +PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::SetDensityGroup( + const std::string& name, const std::vector<std::string>& densities) { + auto& group = config_.screen_density_groups[name]; + for (const auto& density : densities) { + group.push_back(ParseConfigOrDie(density)); + } + return *this; +} + +PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddArtifact( + const configuration::Artifact& artifact) { + config_.artifacts.push_back(artifact); + return *this; +} + +configuration::PostProcessingConfiguration PostProcessingConfigurationBuilder::Build() { + return config_; +} + +ArtifactBuilder& ArtifactBuilder::SetName(const std::string& name) { + artifact_.name = {name}; + return *this; +} + +ArtifactBuilder& ArtifactBuilder::SetAbiGroup(const std::string& name) { + artifact_.abi_group = {name}; + return *this; +} + +ArtifactBuilder& ArtifactBuilder::SetDensityGroup(const std::string& name) { + artifact_.screen_density_group = {name}; + return *this; +} + +ArtifactBuilder& ArtifactBuilder::SetLocaleGroup(const std::string& name) { + artifact_.locale_group = {name}; + return *this; +} + +configuration::Artifact ArtifactBuilder::Build() { + return artifact_; +} + } // namespace test } // namespace aapt diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h index d9f3912fb4c6..e8cefc1853b6 100644 --- a/tools/aapt2/test/Builders.h +++ b/tools/aapt2/test/Builders.h @@ -24,7 +24,9 @@ #include "Resource.h" #include "ResourceTable.h" #include "ResourceValues.h" +#include "configuration/ConfigurationParser.h" #include "process/IResourceTableConsumer.h" +#include "test/Common.h" #include "util/Maybe.h" #include "xml/XmlDom.h" @@ -149,6 +151,37 @@ std::unique_ptr<xml::XmlResource> BuildXmlDom(const android::StringPiece& str); std::unique_ptr<xml::XmlResource> BuildXmlDomForPackageName(IAaptContext* context, const android::StringPiece& str); +class PostProcessingConfigurationBuilder { + public: + PostProcessingConfigurationBuilder() = default; + + PostProcessingConfigurationBuilder& SetAbiGroup(const std::string& name, + const std::vector<configuration::Abi>& abis); + PostProcessingConfigurationBuilder& SetLocaleGroup(const std::string& name, + const std::vector<std::string>& locales); + PostProcessingConfigurationBuilder& SetDensityGroup(const std::string& name, + const std::vector<std::string>& densities); + PostProcessingConfigurationBuilder& AddArtifact(const configuration::Artifact& artifact); + configuration::PostProcessingConfiguration Build(); + + private: + configuration::PostProcessingConfiguration config_; +}; + +class ArtifactBuilder { + public: + ArtifactBuilder() = default; + + ArtifactBuilder& SetName(const std::string& name); + ArtifactBuilder& SetAbiGroup(const std::string& name); + ArtifactBuilder& SetDensityGroup(const std::string& name); + ArtifactBuilder& SetLocaleGroup(const std::string& name); + configuration::Artifact Build(); + + private: + configuration::Artifact artifact_; +}; + } // namespace test } // namespace aapt diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h index d7b46caf8c94..7482b8b627d3 100644 --- a/tools/aapt2/test/Common.h +++ b/tools/aapt2/test/Common.h @@ -41,7 +41,7 @@ IDiagnostics* GetDiagnostics(); inline ResourceName ParseNameOrDie(const android::StringPiece& str) { ResourceNameRef ref; - CHECK(ResourceUtils::ParseResourceName(str, &ref)) << "invalid resource name"; + CHECK(ResourceUtils::ParseResourceName(str, &ref)) << "invalid resource name: " << str; return ref.ToResourceName(); } @@ -142,10 +142,97 @@ MATCHER_P(StrEq, a, return android::StringPiece16(arg) == a; } -MATCHER_P(ValueEq, a, - std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) { - return arg.Equals(&a); -} +class ValueEq { + public: + template <typename arg_type> + class BaseImpl : public ::testing::MatcherInterface<arg_type> { + BaseImpl(const BaseImpl&) = default; + + void DescribeTo(::std::ostream* os) const override { + *os << "is equal to " << *expected_; + } + + void DescribeNegationTo(::std::ostream* os) const override { + *os << "is not equal to " << *expected_; + } + + protected: + BaseImpl(const Value* expected) : expected_(expected) { + } + + const Value* expected_; + }; + + template <typename T, bool> + class Impl {}; + + template <typename T> + class Impl<T, false> : public ::testing::MatcherInterface<T> { + public: + explicit Impl(const Value* expected) : expected_(expected) { + } + + bool MatchAndExplain(T x, ::testing::MatchResultListener* listener) const override { + return expected_->Equals(&x); + } + + void DescribeTo(::std::ostream* os) const override { + *os << "is equal to " << *expected_; + } + + void DescribeNegationTo(::std::ostream* os) const override { + *os << "is not equal to " << *expected_; + } + + private: + DISALLOW_COPY_AND_ASSIGN(Impl); + + const Value* expected_; + }; + + template <typename T> + class Impl<T, true> : public ::testing::MatcherInterface<T> { + public: + explicit Impl(const Value* expected) : expected_(expected) { + } + + bool MatchAndExplain(T x, ::testing::MatchResultListener* listener) const override { + return expected_->Equals(x); + } + + void DescribeTo(::std::ostream* os) const override { + *os << "is equal to " << *expected_; + } + + void DescribeNegationTo(::std::ostream* os) const override { + *os << "is not equal to " << *expected_; + } + + private: + DISALLOW_COPY_AND_ASSIGN(Impl); + + const Value* expected_; + }; + + ValueEq(const Value& expected) : expected_(&expected) { + } + ValueEq(const Value* expected) : expected_(expected) { + } + ValueEq(const ValueEq&) = default; + + template <typename T> + operator ::testing::Matcher<T>() const { + return ::testing::Matcher<T>(new Impl<T, std::is_pointer<T>::value>(expected_)); + } + + private: + const Value* expected_; +}; + +// MATCHER_P(ValueEq, a, +// std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) { +// return arg.Equals(&a); +//} MATCHER_P(StrValueEq, a, std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) { diff --git a/tools/aapt2/unflatten/BinaryResourceParser.cpp b/tools/aapt2/unflatten/BinaryResourceParser.cpp index 728d1f4207c4..892aee6fadcb 100644 --- a/tools/aapt2/unflatten/BinaryResourceParser.cpp +++ b/tools/aapt2/unflatten/BinaryResourceParser.cpp @@ -544,7 +544,7 @@ std::unique_ptr<Array> BinaryResourceParser::ParseArray( const ResTable_map_entry* map) { std::unique_ptr<Array> array = util::make_unique<Array>(); for (const ResTable_map& map_entry : map) { - array->items.push_back(ParseValue(name, config, map_entry.value)); + array->elements.push_back(ParseValue(name, config, map_entry.value)); } return array; } diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp index 6f97efe37921..bf8dc4d727f7 100644 --- a/tools/aapt2/util/Files.cpp +++ b/tools/aapt2/util/Files.cpp @@ -94,7 +94,9 @@ FileType GetFileType(const std::string& path) { bool mkdirs(const std::string& path) { constexpr const mode_t mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP; - size_t current_pos = 0u; + // Start after the first character so that we don't consume the root '/'. + // This is safe to do with unicode because '/' will never match with a continuation character. + size_t current_pos = 1u; while ((current_pos = path.find(sDirSep, current_pos)) != std::string::npos) { std::string parent_path = path.substr(0, current_pos); int result = ::android::base::utf8::mkdir(parent_path.c_str(), mode); diff --git a/tools/aapt2/util/Files.h b/tools/aapt2/util/Files.h index b6aa410f9421..b26e4fa26de6 100644 --- a/tools/aapt2/util/Files.h +++ b/tools/aapt2/util/Files.h @@ -34,8 +34,10 @@ namespace file { #ifdef _WIN32 constexpr const char sDirSep = '\\'; +constexpr const char sPathSep = ';'; #else constexpr const char sDirSep = '/'; +constexpr const char sPathSep = ':'; #endif enum class FileType { diff --git a/tools/aapt2/util/Util.h b/tools/aapt2/util/Util.h index f89f8bf9dc44..c928458786e4 100644 --- a/tools/aapt2/util/Util.h +++ b/tools/aapt2/util/Util.h @@ -228,6 +228,12 @@ class Tokenizer { public: class iterator { public: + using reference = android::StringPiece&; + using value_type = android::StringPiece; + using difference_type = size_t; + using pointer = android::StringPiece*; + using iterator_category = std::forward_iterator_tag; + iterator(const iterator&) = default; iterator& operator=(const iterator&) = default; @@ -250,9 +256,13 @@ class Tokenizer { Tokenizer(const android::StringPiece& str, char sep); - iterator begin() { return begin_; } + iterator begin() const { + return begin_; + } - iterator end() { return end_; } + iterator end() const { + return end_; + } private: const iterator begin_; diff --git a/tools/aapt2/xml/XmlActionExecutor.cpp b/tools/aapt2/xml/XmlActionExecutor.cpp index 352a93361633..cc664a5de722 100644 --- a/tools/aapt2/xml/XmlActionExecutor.cpp +++ b/tools/aapt2/xml/XmlActionExecutor.cpp @@ -78,7 +78,7 @@ bool XmlActionExecutor::Execute(XmlActionExecutorPolicy policy, IDiagnostics* di XmlResource* doc) const { SourcePathDiagnostics source_diag(doc->file.source, diag); - Element* el = FindRootElement(doc); + Element* el = doc->root.get(); if (!el) { if (policy == XmlActionExecutorPolicy::kWhitelist) { source_diag.Error(DiagMessage() << "no root XML tag found"); diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp index d6df7150214b..19de3afb9d62 100644 --- a/tools/aapt2/xml/XmlDom.cpp +++ b/tools/aapt2/xml/XmlDom.cpp @@ -39,17 +39,15 @@ namespace xml { constexpr char kXmlNamespaceSep = 1; struct Stack { - std::unique_ptr<xml::Node> root; - std::stack<xml::Node*> node_stack; + std::unique_ptr<xml::Element> root; + std::stack<xml::Element*> node_stack; + std::unique_ptr<xml::Element> pending_element; std::string pending_comment; std::unique_ptr<xml::Text> last_text_node; }; -/** - * Extracts the namespace and name of an expanded element or attribute name. - */ -static void SplitName(const char* name, std::string* out_ns, - std::string* out_name) { +// Extracts the namespace and name of an expanded element or attribute name. +static void SplitName(const char* name, std::string* out_ns, std::string* out_name) { const char* p = name; while (*p != 0 && *p != kXmlNamespaceSep) { p++; @@ -67,6 +65,7 @@ static void SplitName(const char* name, std::string* out_ns, static void FinishPendingText(Stack* stack) { if (stack->last_text_node != nullptr) { if (!stack->last_text_node->text.empty()) { + CHECK(!stack->node_stack.empty()); stack->node_stack.top()->AppendChild(std::move(stack->last_text_node)); } else { // Drop an empty text node. @@ -75,48 +74,27 @@ static void FinishPendingText(Stack* stack) { } } -static void AddToStack(Stack* stack, XML_Parser parser, - std::unique_ptr<Node> node) { - node->line_number = XML_GetCurrentLineNumber(parser); - node->column_number = XML_GetCurrentColumnNumber(parser); - - Node* this_node = node.get(); - if (!stack->node_stack.empty()) { - stack->node_stack.top()->AppendChild(std::move(node)); - } else { - stack->root = std::move(node); - } - - if (!NodeCast<Text>(this_node)) { - stack->node_stack.push(this_node); - } -} - -static void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix, - const char* uri) { +static void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix, const char* uri) { XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); FinishPendingText(stack); - std::unique_ptr<Namespace> ns = util::make_unique<Namespace>(); - if (prefix) { - ns->namespace_prefix = prefix; - } + NamespaceDecl decl; + decl.line_number = XML_GetCurrentLineNumber(parser); + decl.column_number = XML_GetCurrentColumnNumber(parser); + decl.prefix = prefix ? prefix : ""; + decl.uri = uri ? uri : ""; - if (uri) { - ns->namespace_uri = uri; + if (stack->pending_element == nullptr) { + stack->pending_element = util::make_unique<Element>(); } - - AddToStack(stack, parser, std::move(ns)); + stack->pending_element->namespace_decls.push_back(std::move(decl)); } -static void XMLCALL EndNamespaceHandler(void* user_data, const char* prefix) { +static void XMLCALL EndNamespaceHandler(void* user_data, const char* /*prefix*/) { XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); FinishPendingText(stack); - - CHECK(!stack->node_stack.empty()); - stack->node_stack.pop(); } static bool less_attribute(const Attribute& lhs, const Attribute& rhs) { @@ -124,28 +102,42 @@ static bool less_attribute(const Attribute& lhs, const Attribute& rhs) { std::tie(rhs.namespace_uri, rhs.name, rhs.value); } -static void XMLCALL StartElementHandler(void* user_data, const char* name, - const char** attrs) { +static void XMLCALL StartElementHandler(void* user_data, const char* name, const char** attrs) { XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); FinishPendingText(stack); - std::unique_ptr<Element> el = util::make_unique<Element>(); + std::unique_ptr<Element> el; + if (stack->pending_element != nullptr) { + el = std::move(stack->pending_element); + } else { + el = util::make_unique<Element>(); + } + + el->line_number = XML_GetCurrentLineNumber(parser); + el->column_number = XML_GetCurrentColumnNumber(parser); + el->comment = std::move(stack->pending_comment); + SplitName(name, &el->namespace_uri, &el->name); while (*attrs) { Attribute attribute; SplitName(*attrs++, &attribute.namespace_uri, &attribute.name); attribute.value = *attrs++; - - // Insert in sorted order. - auto iter = std::lower_bound(el->attributes.begin(), el->attributes.end(), attribute, - less_attribute); - el->attributes.insert(iter, std::move(attribute)); + el->attributes.push_back(std::move(attribute)); } - el->comment = std::move(stack->pending_comment); - AddToStack(stack, parser, std::move(el)); + // Sort the attributes. + std::sort(el->attributes.begin(), el->attributes.end(), less_attribute); + + // Add to the stack. + Element* this_el = el.get(); + if (!stack->node_stack.empty()) { + stack->node_stack.top()->AppendChild(std::move(el)); + } else { + stack->root = std::move(el); + } + stack->node_stack.push(this_el); } static void XMLCALL EndElementHandler(void* user_data, const char* name) { @@ -263,13 +255,13 @@ static void CopyAttributes(Element* el, android::ResXMLParser* parser, StringPoo std::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len, IDiagnostics* diag, const Source& source) { // We import the android namespace because on Windows NO_ERROR is a macro, not - // an enum, which - // causes errors when qualifying it with android:: + // an enum, which causes errors when qualifying it with android:: using namespace android; StringPool string_pool; - std::unique_ptr<Node> root; - std::stack<Node*> node_stack; + std::unique_ptr<Element> root; + std::stack<Element*> node_stack; + std::unique_ptr<Element> pending_element; ResXMLTree tree; if (tree.setTo(data, data_len) != NO_ERROR) { @@ -277,57 +269,79 @@ std::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len, IDiagnos } ResXMLParser::event_code_t code; - while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT && - code != ResXMLParser::END_DOCUMENT) { + while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT && code != ResXMLParser::END_DOCUMENT) { std::unique_ptr<Node> new_node; switch (code) { case ResXMLParser::START_NAMESPACE: { - std::unique_ptr<Namespace> node = util::make_unique<Namespace>(); + NamespaceDecl decl; + decl.line_number = tree.getLineNumber(); + size_t len; const char16_t* str16 = tree.getNamespacePrefix(&len); if (str16) { - node->namespace_prefix = util::Utf16ToUtf8(StringPiece16(str16, len)); + decl.prefix = util::Utf16ToUtf8(StringPiece16(str16, len)); } str16 = tree.getNamespaceUri(&len); if (str16) { - node->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len)); + decl.uri = util::Utf16ToUtf8(StringPiece16(str16, len)); } - new_node = std::move(node); + + if (pending_element == nullptr) { + pending_element = util::make_unique<Element>(); + } + pending_element->namespace_decls.push_back(std::move(decl)); break; } case ResXMLParser::START_TAG: { - std::unique_ptr<Element> node = util::make_unique<Element>(); + std::unique_ptr<Element> el; + if (pending_element != nullptr) { + el = std::move(pending_element); + } else { + el = util::make_unique<Element>(); + } + el->line_number = tree.getLineNumber(); + size_t len; const char16_t* str16 = tree.getElementNamespace(&len); if (str16) { - node->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len)); + el->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len)); } str16 = tree.getElementName(&len); if (str16) { - node->name = util::Utf16ToUtf8(StringPiece16(str16, len)); + el->name = util::Utf16ToUtf8(StringPiece16(str16, len)); } - CopyAttributes(node.get(), &tree, &string_pool); + Element* this_el = el.get(); + CopyAttributes(el.get(), &tree, &string_pool); - new_node = std::move(node); + if (!node_stack.empty()) { + node_stack.top()->AppendChild(std::move(el)); + } else { + root = std::move(el); + } + node_stack.push(this_el); break; } case ResXMLParser::TEXT: { - std::unique_ptr<Text> node = util::make_unique<Text>(); + std::unique_ptr<Text> text = util::make_unique<Text>(); + text->line_number = tree.getLineNumber(); size_t len; const char16_t* str16 = tree.getText(&len); if (str16) { - node->text = util::Utf16ToUtf8(StringPiece16(str16, len)); + text->text = util::Utf16ToUtf8(StringPiece16(str16, len)); } - new_node = std::move(node); + CHECK(!node_stack.empty()); + node_stack.top()->AppendChild(std::move(text)); break; } case ResXMLParser::END_NAMESPACE: + break; + case ResXMLParser::END_TAG: CHECK(!node_stack.empty()); node_stack.pop(); @@ -337,74 +351,32 @@ std::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len, IDiagnos LOG(FATAL) << "unhandled XML chunk type"; break; } - - if (new_node) { - new_node->line_number = tree.getLineNumber(); - - Node* this_node = new_node.get(); - if (!root) { - CHECK(node_stack.empty()) << "node stack should be empty"; - root = std::move(new_node); - } else { - CHECK(!node_stack.empty()) << "node stack should not be empty"; - node_stack.top()->AppendChild(std::move(new_node)); - } - - if (!NodeCast<Text>(this_node)) { - node_stack.push(this_node); - } - } } return util::make_unique<XmlResource>(ResourceFile{}, std::move(string_pool), std::move(root)); } -std::unique_ptr<Node> Namespace::Clone(const ElementCloneFunc& el_cloner) { - auto ns = util::make_unique<Namespace>(); - ns->comment = comment; - ns->line_number = line_number; - ns->column_number = column_number; - ns->namespace_prefix = namespace_prefix; - ns->namespace_uri = namespace_uri; - ns->children.reserve(children.size()); - for (const std::unique_ptr<xml::Node>& child : children) { - ns->AppendChild(child->Clone(el_cloner)); - } - return std::move(ns); -} - -Element* FindRootElement(XmlResource* doc) { - return FindRootElement(doc->root.get()); -} - Element* FindRootElement(Node* node) { - if (!node) { + if (node == nullptr) { return nullptr; } - Element* el = nullptr; - while ((el = NodeCast<Element>(node)) == nullptr) { - if (node->children.empty()) { - return nullptr; - } - // We are looking for the first element, and namespaces can only have one - // child. - node = node->children.front().get(); + while (node->parent != nullptr) { + node = node->parent; } - return el; + return NodeCast<Element>(node); } -void Node::AppendChild(std::unique_ptr<Node> child) { +void Element::AppendChild(std::unique_ptr<Node> child) { child->parent = this; children.push_back(std::move(child)); } -void Node::InsertChild(size_t index, std::unique_ptr<Node> child) { +void Element::InsertChild(size_t index, std::unique_ptr<Node> child) { child->parent = this; children.insert(children.begin() + index, std::move(child)); } -Attribute* Element::FindAttribute(const StringPiece& ns, - const StringPiece& name) { +Attribute* Element::FindAttribute(const StringPiece& ns, const StringPiece& name) { for (auto& attr : attributes) { if (ns == attr.namespace_uri && name == attr.name) { return &attr; @@ -426,21 +398,11 @@ Element* Element::FindChild(const StringPiece& ns, const StringPiece& name) { return FindChildWithAttribute(ns, name, {}, {}, {}); } -Element* Element::FindChildWithAttribute(const StringPiece& ns, - const StringPiece& name, - const StringPiece& attr_ns, - const StringPiece& attr_name, +Element* Element::FindChildWithAttribute(const StringPiece& ns, const StringPiece& name, + const StringPiece& attr_ns, const StringPiece& attr_name, const StringPiece& attr_value) { - for (auto& child_node : children) { - Node* child = child_node.get(); - while (NodeCast<Namespace>(child)) { - if (child->children.empty()) { - break; - } - child = child->children[0].get(); - } - - if (Element* el = NodeCast<Element>(child)) { + for (auto& child : children) { + if (Element* el = NodeCast<Element>(child.get())) { if (ns == el->namespace_uri && name == el->name) { if (attr_ns.empty() && attr_name.empty()) { return el; @@ -459,23 +421,16 @@ Element* Element::FindChildWithAttribute(const StringPiece& ns, std::vector<Element*> Element::GetChildElements() { std::vector<Element*> elements; for (auto& child_node : children) { - Node* child = child_node.get(); - while (NodeCast<Namespace>(child)) { - if (child->children.empty()) { - break; - } - child = child->children[0].get(); - } - - if (Element* el = NodeCast<Element>(child)) { - elements.push_back(el); + if (Element* child = NodeCast<Element>(child_node.get())) { + elements.push_back(child); } } return elements; } -std::unique_ptr<Node> Element::Clone(const ElementCloneFunc& el_cloner) { +std::unique_ptr<Node> Element::Clone(const ElementCloneFunc& el_cloner) const { auto el = util::make_unique<Element>(); + el->namespace_decls = namespace_decls; el->comment = comment; el->line_number = line_number; el->column_number = column_number; @@ -490,7 +445,17 @@ std::unique_ptr<Node> Element::Clone(const ElementCloneFunc& el_cloner) { return std::move(el); } -std::unique_ptr<Node> Text::Clone(const ElementCloneFunc&) { +std::unique_ptr<Element> Element::CloneElement(const ElementCloneFunc& el_cloner) const { + return std::unique_ptr<Element>(static_cast<Element*>(Clone(el_cloner).release())); +} + +void Element::Accept(Visitor* visitor) { + visitor->BeforeVisitElement(this); + visitor->Visit(this); + visitor->AfterVisitElement(this); +} + +std::unique_ptr<Node> Text::Clone(const ElementCloneFunc&) const { auto t = util::make_unique<Text>(); t->comment = comment; t->line_number = line_number; @@ -499,36 +464,41 @@ std::unique_ptr<Node> Text::Clone(const ElementCloneFunc&) { return std::move(t); } -void PackageAwareVisitor::Visit(Namespace* ns) { - bool added = false; - if (Maybe<ExtractedPackage> maybe_package = - ExtractPackageFromNamespace(ns->namespace_uri)) { - ExtractedPackage& package = maybe_package.value(); - package_decls_.push_back( - PackageDecl{ns->namespace_prefix, std::move(package)}); - added = true; - } - - Visitor::Visit(ns); +void Text::Accept(Visitor* visitor) { + visitor->Visit(this); +} - if (added) { - package_decls_.pop_back(); +void PackageAwareVisitor::BeforeVisitElement(Element* el) { + std::vector<PackageDecl> decls; + for (const NamespaceDecl& decl : el->namespace_decls) { + if (Maybe<ExtractedPackage> maybe_package = ExtractPackageFromNamespace(decl.uri)) { + decls.push_back(PackageDecl{decl.prefix, std::move(maybe_package.value())}); + } } + package_decls_.push_back(std::move(decls)); +} + +void PackageAwareVisitor::AfterVisitElement(Element* el) { + package_decls_.pop_back(); } -Maybe<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias( - const StringPiece& alias, const StringPiece& local_package) const { +Maybe<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias(const StringPiece& alias) const { if (alias.empty()) { - return ExtractedPackage{local_package.to_string(), false /* private */}; + return ExtractedPackage{{}, false /*private*/}; } const auto rend = package_decls_.rend(); for (auto iter = package_decls_.rbegin(); iter != rend; ++iter) { - if (alias == iter->prefix) { - if (iter->package.package.empty()) { - return ExtractedPackage{local_package.to_string(), iter->package.private_namespace}; + const std::vector<PackageDecl>& decls = *iter; + const auto rend2 = decls.rend(); + for (auto iter2 = decls.rbegin(); iter2 != rend2; ++iter2) { + const PackageDecl& decl = *iter2; + if (alias == decl.prefix) { + if (decl.package.package.empty()) { + return ExtractedPackage{{}, decl.package.private_namespace}; + } + return decl.package; } - return iter->package; } } return {}; diff --git a/tools/aapt2/xml/XmlDom.h b/tools/aapt2/xml/XmlDom.h index 54a70333fad2..9a9151da4ab7 100644 --- a/tools/aapt2/xml/XmlDom.h +++ b/tools/aapt2/xml/XmlDom.h @@ -33,45 +33,33 @@ namespace aapt { namespace xml { -class RawVisitor; - class Element; +class Visitor; // Base class for all XML nodes. class Node { public: - Node* parent = nullptr; - size_t line_number = 0; - size_t column_number = 0; - std::string comment; - std::vector<std::unique_ptr<Node>> children; - virtual ~Node() = default; - void AppendChild(std::unique_ptr<Node> child); - void InsertChild(size_t index, std::unique_ptr<Node> child); - virtual void Accept(RawVisitor* visitor) = 0; + Element* parent = nullptr; + size_t line_number = 0u; + size_t column_number = 0u; + std::string comment; + + virtual void Accept(Visitor* visitor) = 0; using ElementCloneFunc = std::function<void(const Element&, Element*)>; // Clones the Node subtree, using the given function to decide how to clone an Element. - virtual std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) = 0; -}; - -// Base class that implements the visitor methods for a subclass of Node. -template <typename Derived> -class BaseNode : public Node { - public: - virtual void Accept(RawVisitor* visitor) override; + virtual std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) const = 0; }; -// A Namespace XML node. Can only have one child. -class Namespace : public BaseNode<Namespace> { - public: - std::string namespace_prefix; - std::string namespace_uri; - - std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) override; +// A namespace declaration (xmlns:prefix="uri"). +struct NamespaceDecl { + std::string prefix; + std::string uri; + size_t line_number = 0u; + size_t column_number = 0u; }; struct AaptAttribute { @@ -94,31 +82,46 @@ struct Attribute { }; // An Element XML node. -class Element : public BaseNode<Element> { +class Element : public Node { public: + // Ordered namespace prefix declarations. + std::vector<NamespaceDecl> namespace_decls; + std::string namespace_uri; std::string name; std::vector<Attribute> attributes; + std::vector<std::unique_ptr<Node>> children; + + void AppendChild(std::unique_ptr<Node> child); + void InsertChild(size_t index, std::unique_ptr<Node> child); Attribute* FindAttribute(const android::StringPiece& ns, const android::StringPiece& name); const Attribute* FindAttribute(const android::StringPiece& ns, const android::StringPiece& name) const; - xml::Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name); - xml::Element* FindChildWithAttribute(const android::StringPiece& ns, - const android::StringPiece& name, - const android::StringPiece& attr_ns, - const android::StringPiece& attr_name, - const android::StringPiece& attr_value); - std::vector<xml::Element*> GetChildElements(); - std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) override; + Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name); + Element* FindChildWithAttribute(const android::StringPiece& ns, const android::StringPiece& name, + const android::StringPiece& attr_ns, + const android::StringPiece& attr_name, + const android::StringPiece& attr_value); + std::vector<Element*> GetChildElements(); + + // Due to overriding of subtypes not working with unique_ptr, define a convenience Clone method + // that knows cloning an element returns an element. + std::unique_ptr<Element> CloneElement(const ElementCloneFunc& el_cloner) const; + + std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) const override; + + void Accept(Visitor* visitor) override; }; // A Text (CDATA) XML node. Can not have any children. -class Text : public BaseNode<Text> { +class Text : public Node { public: std::string text; - std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) override; + std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) const override; + + void Accept(Visitor* visitor) override; }; // An XML resource with a source, name, and XML tree. @@ -131,7 +134,7 @@ class XmlResource { // is destroyed. StringPool string_pool; - std::unique_ptr<xml::Node> root; + std::unique_ptr<xml::Element> root; }; // Inflates an XML DOM from an InputStream, logging errors to the logger. @@ -143,42 +146,38 @@ std::unique_ptr<XmlResource> Inflate(io::InputStream* in, IDiagnostics* diag, co std::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len, IDiagnostics* diag, const Source& source); -Element* FindRootElement(XmlResource* doc); Element* FindRootElement(Node* node); -// A visitor interface for the different XML Node subtypes. This will not traverse into children. -// Use Visitor for that. -class RawVisitor { - public: - virtual ~RawVisitor() = default; - - virtual void Visit(Namespace* node) {} - virtual void Visit(Element* node) {} - virtual void Visit(Text* text) {} -}; - // Visitor whose default implementation visits the children nodes of any node. -class Visitor : public RawVisitor { +class Visitor { public: - using RawVisitor::Visit; + virtual ~Visitor() = default; - void Visit(Namespace* node) override { - VisitChildren(node); + virtual void Visit(Element* el) { + VisitChildren(el); } - void Visit(Element* node) override { - VisitChildren(node); + virtual void Visit(Text* text) { } - void Visit(Text* text) override { - VisitChildren(text); - } + protected: + Visitor() = default; - void VisitChildren(Node* node) { - for (auto& child : node->children) { + void VisitChildren(Element* el) { + for (auto& child : el->children) { child->Accept(this); } } + + virtual void BeforeVisitElement(Element* el) { + } + virtual void AfterVisitElement(Element* el) { + } + + private: + DISALLOW_COPY_AND_ASSIGN(Visitor); + + friend class Element; }; // An XML DOM visitor that will record the package name for a namespace prefix. @@ -186,41 +185,69 @@ class PackageAwareVisitor : public Visitor, public IPackageDeclStack { public: using Visitor::Visit; - void Visit(Namespace* ns) override; - Maybe<ExtractedPackage> TransformPackageAlias( - const android::StringPiece& alias, const android::StringPiece& local_package) const override; + Maybe<ExtractedPackage> TransformPackageAlias(const android::StringPiece& alias) const override; + + protected: + PackageAwareVisitor() = default; + + void BeforeVisitElement(Element* el) override; + void AfterVisitElement(Element* el) override; private: + DISALLOW_COPY_AND_ASSIGN(PackageAwareVisitor); + struct PackageDecl { std::string prefix; ExtractedPackage package; }; - std::vector<PackageDecl> package_decls_; + std::vector<std::vector<PackageDecl>> package_decls_; }; -// Implementations +namespace internal { -template <typename Derived> -void BaseNode<Derived>::Accept(RawVisitor* visitor) { - visitor->Visit(static_cast<Derived*>(this)); -} +// Base class that overrides the default behaviour and does not descend into child nodes. +class NodeCastBase : public Visitor { + public: + void Visit(Element* el) override { + } + void Visit(Text* el) override { + } + + protected: + NodeCastBase() = default; + + void BeforeVisitElement(Element* el) override { + } + void AfterVisitElement(Element* el) override { + } + + private: + DISALLOW_COPY_AND_ASSIGN(NodeCastBase); +}; template <typename T> -class NodeCastImpl : public RawVisitor { +class NodeCastImpl : public NodeCastBase { public: - using RawVisitor::Visit; + using NodeCastBase::Visit; + + NodeCastImpl() = default; T* value = nullptr; void Visit(T* v) override { value = v; } + + private: + DISALLOW_COPY_AND_ASSIGN(NodeCastImpl); }; +} // namespace internal + template <typename T> T* NodeCast(Node* node) { - NodeCastImpl<T> visitor; + internal::NodeCastImpl<T> visitor; node->Accept(&visitor); return visitor.value; } diff --git a/tools/aapt2/xml/XmlDom_test.cpp b/tools/aapt2/xml/XmlDom_test.cpp index 1340ada6d953..10a45870e556 100644 --- a/tools/aapt2/xml/XmlDom_test.cpp +++ b/tools/aapt2/xml/XmlDom_test.cpp @@ -25,8 +25,10 @@ using ::aapt::io::StringInputStream; using ::testing::Eq; using ::testing::NotNull; using ::testing::SizeIs; +using ::testing::StrEq; namespace aapt { +namespace xml { TEST(XmlDomTest, Inflate) { std::string input = R"(<?xml version="1.0" encoding="utf-8"?> @@ -40,24 +42,23 @@ TEST(XmlDomTest, Inflate) { StdErrDiagnostics diag; StringInputStream in(input); - std::unique_ptr<xml::XmlResource> doc = xml::Inflate(&in, &diag, Source("test.xml")); + std::unique_ptr<XmlResource> doc = Inflate(&in, &diag, Source("test.xml")); ASSERT_THAT(doc, NotNull()); - xml::Namespace* ns = xml::NodeCast<xml::Namespace>(doc->root.get()); - ASSERT_THAT(ns, NotNull()); - EXPECT_THAT(ns->namespace_uri, Eq(xml::kSchemaAndroid)); - EXPECT_THAT(ns->namespace_prefix, Eq("android")); + Element* el = doc->root.get(); + EXPECT_THAT(el->namespace_decls, SizeIs(1u)); + EXPECT_THAT(el->namespace_decls[0].uri, StrEq(xml::kSchemaAndroid)); + EXPECT_THAT(el->namespace_decls[0].prefix, StrEq("android")); } // Escaping is handled after parsing of the values for resource-specific values. TEST(XmlDomTest, ForwardEscapes) { - std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"( + std::unique_ptr<XmlResource> doc = test::BuildXmlDom(R"( <element value="\?hello" pattern="\\d{5}">\\d{5}</element>)"); - xml::Element* el = xml::FindRootElement(doc.get()); - ASSERT_THAT(el, NotNull()); + Element* el = doc->root.get(); - xml::Attribute* attr = el->FindAttribute({}, "pattern"); + Attribute* attr = el->FindAttribute({}, "pattern"); ASSERT_THAT(attr, NotNull()); EXPECT_THAT(attr->value, Eq("\\\\d{5}")); @@ -67,21 +68,48 @@ TEST(XmlDomTest, ForwardEscapes) { ASSERT_THAT(el->children, SizeIs(1u)); - xml::Text* text = xml::NodeCast<xml::Text>(el->children[0].get()); + Text* text = xml::NodeCast<xml::Text>(el->children[0].get()); ASSERT_THAT(text, NotNull()); EXPECT_THAT(text->text, Eq("\\\\d{5}")); } TEST(XmlDomTest, XmlEscapeSequencesAreParsed) { - std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<element value=""" />)"); - - xml::Element* el = xml::FindRootElement(doc.get()); - ASSERT_THAT(el, NotNull()); - - xml::Attribute* attr = el->FindAttribute({}, "value"); + std::unique_ptr<XmlResource> doc = test::BuildXmlDom(R"(<element value=""" />)"); + Attribute* attr = doc->root->FindAttribute({}, "value"); ASSERT_THAT(attr, NotNull()); - EXPECT_THAT(attr->value, Eq("\"")); } +class TestVisitor : public PackageAwareVisitor { + public: + using PackageAwareVisitor::Visit; + + void Visit(Element* el) override { + if (el->name == "View1") { + EXPECT_THAT(TransformPackageAlias("one"), Eq(make_value(ExtractedPackage{"com.one", false}))); + } else if (el->name == "View2") { + EXPECT_THAT(TransformPackageAlias("one"), Eq(make_value(ExtractedPackage{"com.one", false}))); + EXPECT_THAT(TransformPackageAlias("two"), Eq(make_value(ExtractedPackage{"com.two", false}))); + } else if (el->name == "View3") { + EXPECT_THAT(TransformPackageAlias("one"), Eq(make_value(ExtractedPackage{"com.one", false}))); + EXPECT_THAT(TransformPackageAlias("two"), Eq(make_value(ExtractedPackage{"com.two", false}))); + EXPECT_THAT(TransformPackageAlias("three"), + Eq(make_value(ExtractedPackage{"com.three", false}))); + } + } +}; + +TEST(XmlDomTest, PackageAwareXmlVisitor) { + std::unique_ptr<XmlResource> doc = test::BuildXmlDom(R"( + <View1 xmlns:one="http://schemas.android.com/apk/res/com.one"> + <View2 xmlns:two="http://schemas.android.com/apk/res/com.two"> + <View3 xmlns:three="http://schemas.android.com/apk/res/com.three" /> + </View2> + </View1>)"); + + TestVisitor visitor; + doc->root->Accept(&visitor); +} + +} // namespace xml } // namespace aapt diff --git a/tools/aapt2/xml/XmlPullParser.cpp b/tools/aapt2/xml/XmlPullParser.cpp index 30bdc507303b..402e5a459f4e 100644 --- a/tools/aapt2/xml/XmlPullParser.cpp +++ b/tools/aapt2/xml/XmlPullParser.cpp @@ -141,17 +141,16 @@ const std::string& XmlPullParser::namespace_uri() const { return event_queue_.front().data2; } -Maybe<ExtractedPackage> XmlPullParser::TransformPackageAlias( - const StringPiece& alias, const StringPiece& local_package) const { +Maybe<ExtractedPackage> XmlPullParser::TransformPackageAlias(const StringPiece& alias) const { if (alias.empty()) { - return ExtractedPackage{local_package.to_string(), false /* private */}; + return ExtractedPackage{{}, false /*private*/}; } const auto end_iter = package_aliases_.rend(); for (auto iter = package_aliases_.rbegin(); iter != end_iter; ++iter) { if (alias == iter->prefix) { if (iter->package.package.empty()) { - return ExtractedPackage{local_package.to_string(), iter->package.private_namespace}; + return ExtractedPackage{{}, iter->package.private_namespace}; } return iter->package; } diff --git a/tools/aapt2/xml/XmlPullParser.h b/tools/aapt2/xml/XmlPullParser.h index a00caa139061..63db66f0b2b7 100644 --- a/tools/aapt2/xml/XmlPullParser.h +++ b/tools/aapt2/xml/XmlPullParser.h @@ -119,8 +119,7 @@ class XmlPullParser : public IPackageDeclStack { * If xmlns:app="http://schemas.android.com/apk/res-auto", then * 'package' will be set to 'defaultPackage'. */ - Maybe<ExtractedPackage> TransformPackageAlias( - const android::StringPiece& alias, const android::StringPiece& local_package) const override; + Maybe<ExtractedPackage> TransformPackageAlias(const android::StringPiece& alias) const override; // // Remaining methods are for retrieving information about attributes diff --git a/tools/aapt2/xml/XmlUtil.cpp b/tools/aapt2/xml/XmlUtil.cpp index fb8cee8b5634..c1186e83369c 100644 --- a/tools/aapt2/xml/XmlUtil.cpp +++ b/tools/aapt2/xml/XmlUtil.cpp @@ -62,19 +62,15 @@ Maybe<ExtractedPackage> ExtractPackageFromNamespace( return {}; } -void TransformReferenceFromNamespace(IPackageDeclStack* decl_stack, - const StringPiece& local_package, - Reference* in_ref) { +void ResolvePackage(const IPackageDeclStack* decl_stack, Reference* in_ref) { if (in_ref->name) { if (Maybe<ExtractedPackage> transformed_package = - decl_stack->TransformPackageAlias(in_ref->name.value().package, - local_package)) { + decl_stack->TransformPackageAlias(in_ref->name.value().package)) { ExtractedPackage& extracted_package = transformed_package.value(); in_ref->name.value().package = std::move(extracted_package.package); // If the reference was already private (with a * prefix) and the - // namespace is public, - // we keep the reference private. + // namespace is public, we keep the reference private. in_ref->private_reference |= extracted_package.private_namespace; } } diff --git a/tools/aapt2/xml/XmlUtil.h b/tools/aapt2/xml/XmlUtil.h index 1650ac2124ac..4eb359a9eed4 100644 --- a/tools/aapt2/xml/XmlUtil.h +++ b/tools/aapt2/xml/XmlUtil.h @@ -26,81 +26,57 @@ namespace aapt { namespace xml { constexpr const char* kSchemaAuto = "http://schemas.android.com/apk/res-auto"; -constexpr const char* kSchemaPublicPrefix = - "http://schemas.android.com/apk/res/"; -constexpr const char* kSchemaPrivatePrefix = - "http://schemas.android.com/apk/prv/res/"; -constexpr const char* kSchemaAndroid = - "http://schemas.android.com/apk/res/android"; +constexpr const char* kSchemaPublicPrefix = "http://schemas.android.com/apk/res/"; +constexpr const char* kSchemaPrivatePrefix = "http://schemas.android.com/apk/prv/res/"; +constexpr const char* kSchemaAndroid = "http://schemas.android.com/apk/res/android"; constexpr const char* kSchemaTools = "http://schemas.android.com/tools"; constexpr const char* kSchemaAapt = "http://schemas.android.com/aapt"; -/** - * Result of extracting a package name from a namespace URI declaration. - */ +// Result of extracting a package name from a namespace URI declaration. struct ExtractedPackage { - /** - * The name of the package. This can be the empty string, which means that the - * package - * should be assumed to be the package being compiled. - */ + // The name of the package. This can be the empty string, which means that the package + // should be assumed to be the same as the CallSite it was defined in. std::string package; - /** - * True if the package's private namespace was declared. This means that - * private resources - * are made visible. - */ + // True if the package's private namespace was declared. This means that private resources + // are made visible. bool private_namespace; + + friend inline bool operator==(const ExtractedPackage& a, const ExtractedPackage& b) { + return a.package == b.package && a.private_namespace == b.private_namespace; + } }; -/** - * Returns an ExtractedPackage struct if the namespace URI is of the form: - * http://schemas.android.com/apk/res/<package> or - * http://schemas.android.com/apk/prv/res/<package> - * - * Special case: if namespaceUri is http://schemas.android.com/apk/res-auto, - * returns an empty package name. - */ -Maybe<ExtractedPackage> ExtractPackageFromNamespace( - const std::string& namespace_uri); +// Returns an ExtractedPackage struct if the namespace URI is of the form: +// http://schemas.android.com/apk/res/<package> or +// http://schemas.android.com/apk/prv/res/<package> +// +// Special case: if namespaceUri is http://schemas.android.com/apk/res-auto, returns an empty +// package name. +Maybe<ExtractedPackage> ExtractPackageFromNamespace(const std::string& namespace_uri); -/** - * Returns an XML Android namespace for the given package of the form: - * - * http://schemas.android.com/apk/res/<package> - * - * If privateReference == true, the package will be of the form: - * - * http://schemas.android.com/apk/prv/res/<package> - */ +// Returns an XML Android namespace for the given package of the form: +// http://schemas.android.com/apk/res/<package> +// +// If privateReference == true, the package will be of the form: +// http://schemas.android.com/apk/prv/res/<package> std::string BuildPackageNamespace(const android::StringPiece& package, bool private_reference = false); -/** - * Interface representing a stack of XML namespace declarations. When looking up - * the package - * for a namespace prefix, the stack is checked from top to bottom. - */ +// Interface representing a stack of XML namespace declarations. When looking up the package for a +// namespace prefix, the stack is checked from top to bottom. struct IPackageDeclStack { virtual ~IPackageDeclStack() = default; - /** - * Returns an ExtractedPackage struct if the alias given corresponds with a - * package declaration. - */ + // Returns an ExtractedPackage struct if the alias given corresponds with a package declaration. virtual Maybe<ExtractedPackage> TransformPackageAlias( - const android::StringPiece& alias, const android::StringPiece& local_package) const = 0; + const android::StringPiece& alias) const = 0; }; -/** - * Helper function for transforming the original Reference inRef to a fully - * qualified reference - * via the IPackageDeclStack. This will also mark the Reference as private if - * the namespace of the package declaration was private. - */ -void TransformReferenceFromNamespace(IPackageDeclStack* decl_stack, - const android::StringPiece& local_package, Reference* in_ref); +// Helper function for transforming the original Reference inRef to a fully qualified reference +// via the IPackageDeclStack. This will also mark the Reference as private if the namespace of the +// package declaration was private. +void ResolvePackage(const IPackageDeclStack* decl_stack, Reference* in_ref); } // namespace xml } // namespace aapt diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py index 77c1c24b17eb..2eab22e8ec14 100644 --- a/tools/apilint/apilint.py +++ b/tools/apilint/apilint.py @@ -1127,6 +1127,80 @@ def verify_closable(clazz): return +def verify_member_name_not_kotlin_keyword(clazz): + """Prevent method names which are keywords in Kotlin.""" + + # https://kotlinlang.org/docs/reference/keyword-reference.html#hard-keywords + # This list does not include Java keywords as those are already impossible to use. + keywords = [ + 'as', + 'fun', + 'in', + 'is', + 'object', + 'typealias', + 'val', + 'var', + 'when', + ] + + for m in clazz.methods: + if m.name in keywords: + error(clazz, m, None, "Method name must not be a Kotlin keyword") + for f in clazz.fields: + if f.name in keywords: + error(clazz, f, None, "Field name must not be a Kotlin keyword") + + +def verify_method_name_not_kotlin_operator(clazz): + """Warn about method names which become operators in Kotlin.""" + + binary = set() + + def unique_binary_op(m, op): + if op in binary: + error(clazz, m, None, "Only one of '{0}' and '{0}Assign' methods should be present for Kotlin".format(op)) + binary.add(op) + + for m in clazz.methods: + if 'static' in m.split: + continue + + # https://kotlinlang.org/docs/reference/operator-overloading.html#unary-prefix-operators + if m.name in ['unaryPlus', 'unaryMinus', 'not'] and len(m.args) == 0: + warn(clazz, m, None, "Method can be invoked as a unary operator from Kotlin") + + # https://kotlinlang.org/docs/reference/operator-overloading.html#increments-and-decrements + if m.name in ['inc', 'dec'] and len(m.args) == 0 and m.typ != 'void': + # This only applies if the return type is the same or a subtype of the enclosing class, but we have no + # practical way of checking that relationship here. + warn(clazz, m, None, "Method can be invoked as a pre/postfix inc/decrement operator from Kotlin") + + # https://kotlinlang.org/docs/reference/operator-overloading.html#arithmetic + if m.name in ['plus', 'minus', 'times', 'div', 'rem', 'mod', 'rangeTo'] and len(m.args) == 1: + warn(clazz, m, None, "Method can be invoked as a binary operator from Kotlin") + unique_binary_op(m, m.name) + + # https://kotlinlang.org/docs/reference/operator-overloading.html#in + if m.name == 'contains' and len(m.args) == 1 and m.typ == 'boolean': + warn(clazz, m, None, "Method can be invoked as a 'in' operator from Kotlin") + + # https://kotlinlang.org/docs/reference/operator-overloading.html#indexed + if (m.name == 'get' and len(m.args) > 0) or (m.name == 'set' and len(m.args) > 1): + warn(clazz, m, None, "Method can be invoked with an indexing operator from Kotlin") + + # https://kotlinlang.org/docs/reference/operator-overloading.html#invoke + if m.name == 'invoke': + warn(clazz, m, None, "Method can be invoked with function call syntax from Kotlin") + + # https://kotlinlang.org/docs/reference/operator-overloading.html#assignments + if m.name in ['plusAssign', 'minusAssign', 'timesAssign', 'divAssign', 'remAssign', 'modAssign'] \ + and len(m.args) == 1 \ + and m.typ == 'void': + warn(clazz, m, None, "Method can be invoked as a compound assignment operator from Kotlin") + unique_binary_op(m, m.name[:-6]) # Remove 'Assign' suffix + + def examine_clazz(clazz): """Find all style issues in the given class.""" if clazz.pkg.name.startswith("java"): return @@ -1178,6 +1252,8 @@ def examine_clazz(clazz): verify_error(clazz) verify_units(clazz) verify_closable(clazz) + verify_member_name_not_kotlin_keyword(clazz) + verify_method_name_not_kotlin_operator(clazz) def examine_stream(stream): diff --git a/tools/incident_report/main.cpp b/tools/incident_report/main.cpp index 78e5c054a904..250d1186c672 100644 --- a/tools/incident_report/main.cpp +++ b/tools/incident_report/main.cpp @@ -97,6 +97,8 @@ read_message(CodedInputStream* in, Descriptor const* descriptor, GenericMessage* message->addInt64(fieldId, value64); break; } else { + fprintf(stderr, "bad VARINT: 0x%x (%d) at index %d\n", tag, tag, + in->CurrentPosition()); return false; } case WireFormatLite::WIRETYPE_FIXED64: @@ -104,10 +106,14 @@ read_message(CodedInputStream* in, Descriptor const* descriptor, GenericMessage* message->addInt64(fieldId, value64); break; } else { + fprintf(stderr, "bad VARINT: 0x%x (%d) at index %d\n", tag, tag, + in->CurrentPosition()); return false; } case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: if (!read_length_delimited(in, fieldId, descriptor, message)) { + fprintf(stderr, "bad LENGTH_DELIMITED: 0x%x (%d) at index %d\n", + tag, tag, in->CurrentPosition()); return false; } break; @@ -116,6 +122,8 @@ read_message(CodedInputStream* in, Descriptor const* descriptor, GenericMessage* message->addInt32(fieldId, value32); break; } else { + fprintf(stderr, "bad FIXED32: 0x%x (%d) at index %d\n", tag, tag, + in->CurrentPosition()); return false; } default: @@ -146,7 +154,7 @@ print_value(Out* out, FieldDescriptor const* field, GenericMessage::Node const& out->printf("%f", *(float*)&node.value32); break; default: - out->printf("(unexpected value %d (0x%x)", node.value32, node.value32); + out->printf("(unexpected value32 %d (0x%x)", node.value32, node.value32); break; } break; @@ -177,8 +185,11 @@ print_value(Out* out, FieldDescriptor const* field, GenericMessage::Node const& } break; case FieldDescriptor::TYPE_ENUM: + out->printf("%s", field->enum_type()->FindValueByNumber((int)node.value64) + ->name().c_str()); + break; default: - out->printf("(unexpected value %ld (0x%x))", node.value64, node.value64); + out->printf("(unexpected value64 %ld (0x%x))", node.value64, node.value64); break; } break; diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp index 15f622cf9461..e76fef549d7c 100644 --- a/tools/incident_section_gen/main.cpp +++ b/tools/incident_section_gen/main.cpp @@ -17,27 +17,34 @@ #include <frameworks/base/core/proto/android/os/incident.pb.h> - #include <map> +#include <string> +using namespace android; using namespace android::os; using namespace google::protobuf; using namespace google::protobuf::io; using namespace google::protobuf::internal; using namespace std; -int -main(int, const char**) -{ - map<string,FieldDescriptor const*> sections; - int N; +static inline void emptyline() { + printf("\n"); +} +static void generateHead(const char* header) { printf("// Auto generated file. Do not modify\n"); - printf("\n"); - printf("#include \"incident_sections.h\"\n"); - printf("\n"); + emptyline(); + printf("#include \"%s.h\"\n", header); + emptyline(); +} - Descriptor const* descriptor = IncidentProto::descriptor(); +// ================================================================================ +static bool generateIncidentSectionsCpp(Descriptor const* descriptor) +{ + generateHead("incident_sections"); + + map<string,FieldDescriptor const*> sections; + int N; N = descriptor->field_count(); for (int i=0; i<N; i++) { const FieldDescriptor* field = descriptor->field(i); @@ -63,5 +70,185 @@ main(int, const char**) printf("const int INCIDENT_SECTION_COUNT = %d;\n", N); - return 0; + return true; +} + +// ================================================================================ +static void splitAndPrint(const string& args) { + size_t base = 0; + size_t found; + while (true) { + found = args.find_first_of(" ", base); + if (found != base) { + string arg = args.substr(base, found - base); + printf(" \"%s\",", arg.c_str()); + } + if (found == args.npos) break; + base = found + 1; + } +} + +static const char* replaceAll(const string& field_name, const char oldC, const string& newS) { + if (field_name.find_first_of(oldC) == field_name.npos) return field_name.c_str(); + size_t pos = 0, idx = 0; + char* res = new char[field_name.size() * newS.size() + 1]; // assign a larger buffer + while (pos != field_name.size()) { + char cur = field_name[pos++]; + if (cur != oldC) { + res[idx++] = cur; + continue; + } + + for (size_t i=0; i<newS.size(); i++) { + res[idx++] = newS[i]; + } + } + res[idx] = '\0'; + return res; +} + +static inline bool isDefaultDest(const FieldDescriptor* field) { + return field->options().GetExtension(privacy).dest() == PrivacyFlags::default_instance().dest(); +} + +// Returns true if the descriptor doesn't have any non default privacy flags set, including its submessages +static bool generatePrivacyFlags(const Descriptor* descriptor, const char* alias, map<string, bool> &msgNames) { + bool hasDefaultFlags[descriptor->field_count()]; + // iterate though its field and generate sub flags first + for (int i=0; i<descriptor->field_count(); i++) { + hasDefaultFlags[i] = true; // set default to true + const FieldDescriptor* field = descriptor->field(i); + const char* field_name = replaceAll(field->full_name(), '.', "__"); + // check if the same name is already defined + if (msgNames.find(field_name) != msgNames.end()) { + hasDefaultFlags[i] = msgNames[field_name]; + continue; + }; + + PrivacyFlags p = field->options().GetExtension(privacy); + + switch (field->type()) { + case FieldDescriptor::TYPE_MESSAGE: + if (generatePrivacyFlags(field->message_type(), field_name, msgNames) && + isDefaultDest(field)) break; + + printf("static Privacy %s = { %d, %d, %d, NULL, %s_LIST };\n", field_name, field->number(), + (int) field->type(), p.dest(), field_name); + hasDefaultFlags[i] = false; + break; + case FieldDescriptor::TYPE_STRING: + if (isDefaultDest(field) && p.patterns_size() == 0) break; + + printf("static const char* %s_patterns[] = {\n", field_name); + for (int i=0; i<p.patterns_size(); i++) { + // the generated string need to escape backslash as well, need to dup it here + printf(" \"%s\",\n", replaceAll(p.patterns(i), '\\', "\\\\")); + } + printf(" NULL };\n"); + printf("static Privacy %s = { %d, %d, %d, %s_patterns };\n", field_name, field->number(), + (int) field->type(), p.dest(), field_name); + hasDefaultFlags[i] = false; + break; + default: + if (isDefaultDest(field)) break; + printf("static Privacy %s = { %d, %d, %d };\n", field_name, field->number(), + (int) field->type(), p.dest()); + hasDefaultFlags[i] = false; + } + // add the field name to message map, true means it has default flags + msgNames[field_name] = hasDefaultFlags[i]; + } + + bool allDefaults = true; + for (int i=0; i<descriptor->field_count(); i++) { + allDefaults &= hasDefaultFlags[i]; + } + if (allDefaults) return true; + + emptyline(); + printf("const Privacy* %s_LIST[] = {\n", alias); + for (int i=0; i<descriptor->field_count(); i++) { + const FieldDescriptor* field = descriptor->field(i); + if (hasDefaultFlags[i]) continue; + printf(" &%s,\n", replaceAll(field->full_name(), '.', "__")); + } + printf(" NULL };\n"); + emptyline(); + return false; +} + +static bool generateSectionListCpp(Descriptor const* descriptor) { + generateHead("section_list"); + + // generates SECTION_LIST + printf("const Section* SECTION_LIST[] = {\n"); + for (int i=0; i<descriptor->field_count(); i++) { + const FieldDescriptor* field = descriptor->field(i); + + if (field->type() != FieldDescriptor::TYPE_MESSAGE) { + continue; + } + const SectionFlags s = field->options().GetExtension(section); + switch (s.type()) { + case SECTION_NONE: + continue; + case SECTION_FILE: + printf(" new FileSection(%d, \"%s\"),\n", field->number(), s.args().c_str()); + break; + case SECTION_COMMAND: + printf(" new CommandSection(%d,", field->number()); + splitAndPrint(s.args()); + printf(" NULL),\n"); + break; + case SECTION_DUMPSYS: + printf(" new DumpsysSection(%d,", field->number()); + splitAndPrint(s.args()); + printf(" NULL),\n"); + break; + } + } + printf(" NULL };\n"); + emptyline(); + + // generates DESTINATION enum values + EnumDescriptor const* destination = Destination_descriptor(); + for (int i=0; i<destination->value_count(); i++) { + EnumValueDescriptor const* val = destination->value(i); + printf("const uint8_t %s = %d;\n", val->name().c_str(), val->number()); + } + emptyline(); + printf("const uint8_t DEST_DEFAULT_VALUE = %d;\n", PrivacyFlags::default_instance().dest()); + emptyline(); + // populates string type and message type values + printf("const uint8_t TYPE_STRING = %d;\n", (int) FieldDescriptor::TYPE_STRING); + printf("const uint8_t TYPE_MESSAGE = %d;\n", (int) FieldDescriptor::TYPE_MESSAGE); + emptyline(); + + // generates PRIVACY_POLICY + map<string, bool> messageNames; + if (generatePrivacyFlags(descriptor, "PRIVACY_POLICY", messageNames)) { + // if no privacy options set at all, define an empty list + printf("const Privacy* PRIVACY_POLICY_LIST[] = { NULL };\n"); + } + + return true; +} + +// ================================================================================ +int main(int argc, char const *argv[]) +{ + if (argc != 2) return 1; + const char* module = argv[1]; + + Descriptor const* descriptor = IncidentProto::descriptor(); + + if (strcmp(module, "incident") == 0) { + return !generateIncidentSectionsCpp(descriptor); + } + if (strcmp(module, "incidentd") == 0 ) { + return !generateSectionListCpp(descriptor); + } + + // return failure if not called by the whitelisted modules + return 1; } diff --git a/tools/locked_region_code_injection/Android.mk b/tools/locked_region_code_injection/Android.mk index d9217834f871..77d5163c1b78 100644 --- a/tools/locked_region_code_injection/Android.mk +++ b/tools/locked_region_code_injection/Android.mk @@ -10,6 +10,6 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ asm-commons-5.2 \ asm-tree-5.2 \ asm-analysis-5.2 \ - guava-20.0 \ + guava-21.0 \ include $(BUILD_HOST_JAVA_LIBRARY) diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java index ac5df05373c1..dc5ba0cc83b5 100644 --- a/wifi/java/android/net/wifi/RttManager.java +++ b/wifi/java/android/net/wifi/RttManager.java @@ -1,5 +1,6 @@ package android.net.wifi; +import android.Manifest; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; @@ -313,6 +314,7 @@ public class RttManager { }; } + @RequiresPermission(Manifest.permission.LOCATION_HARDWARE) public RttCapabilities getRttCapabilities() { synchronized (mCapabilitiesLock) { if (mRttCapabilities == null) { @@ -925,6 +927,51 @@ public class RttManager { public void onAborted(); } + /** + * A parcelable that contains rtt client information. + * + * @hide + */ + public static class RttClient implements Parcelable { + // Package name of RttClient. + private final String mPackageName; + + public RttClient(String packageName) { + mPackageName = packageName; + } + + protected RttClient(Parcel in) { + mPackageName = in.readString(); + } + + public static final Creator<RttManager.RttClient> CREATOR = + new Creator<RttManager.RttClient>() { + @Override + public RttManager.RttClient createFromParcel(Parcel in) { + return new RttManager.RttClient(in); + } + + @Override + public RttManager.RttClient[] newArray(int size) { + return new RttManager.RttClient[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int i) { + parcel.writeString(mPackageName); + } + + public String getPackageName() { + return mPackageName; + } + } + private boolean rttParamSanity(RttParams params, int index) { if (mRttCapabilities == null) { if(getRttCapabilities() == null) { @@ -1236,7 +1283,8 @@ public class RttManager { mAsyncChannel.connectSync(mContext, handler, messenger); // We cannot use fullyConnectSync because it sends the FULL_CONNECTION message // synchronously, which causes RttService to receive the wrong replyTo value. - mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); + mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION, + new RttClient(context.getPackageName())); mAsyncChannel.sendMessage(CMD_OP_REG_BINDER, key[0]); } diff --git a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java index f61dfdc2f6f9..b22ae07015c8 100755 --- a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java +++ b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java @@ -26,15 +26,14 @@ import android.net.ScoredNetwork; import android.os.Handler; import android.os.Process; import android.util.Log; +import android.util.LruCache; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; import java.io.FileDescriptor; import java.io.PrintWriter; -import java.util.HashMap; import java.util.List; -import java.util.Map; /** * {@link INetworkScoreCache} implementation for Wifi Networks. @@ -50,18 +49,21 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { // scorer to provide an RSSI threshold below which a network should not be used. public static final int INVALID_NETWORK_SCORE = Byte.MIN_VALUE; + /** Default number entries to be stored in the {@link LruCache}. */ + private static final int DEFAULT_MAX_CACHE_SIZE = 100; + // See {@link #CacheListener}. @Nullable - @GuardedBy("mCacheLock") + @GuardedBy("mLock") private CacheListener mListener; private final Context mContext; - private final Object mCacheLock = new Object(); + private final Object mLock = new Object(); // The key is of the form "<ssid>"<bssid> // TODO: What about SSIDs that can't be encoded as UTF-8? - private final Map<String, ScoredNetwork> mNetworkCache; - + @GuardedBy("mLock") + private final LruCache<String, ScoredNetwork> mCache; public WifiNetworkScoreCache(Context context) { this(context, null /* listener */); @@ -74,9 +76,14 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { * @param listener CacheListener for cache updates */ public WifiNetworkScoreCache(Context context, @Nullable CacheListener listener) { + this(context, listener, DEFAULT_MAX_CACHE_SIZE); + } + + public WifiNetworkScoreCache( + Context context, @Nullable CacheListener listener, int maxCacheSize) { mContext = context.getApplicationContext(); mListener = listener; - mNetworkCache = new HashMap<>(); + mCache = new LruCache<>(maxCacheSize); } @Override public final void updateScores(List<ScoredNetwork> networks) { @@ -89,7 +96,7 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { boolean changed = false; - synchronized(mNetworkCache) { + synchronized(mLock) { for (ScoredNetwork network : networks) { String networkKey = buildNetworkKey(network); if (networkKey == null) { @@ -98,12 +105,10 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { } continue; } - mNetworkCache.put(networkKey, network); + mCache.put(networkKey, network); changed = true; } - } - synchronized (mCacheLock) { if (mListener != null && changed) { mListener.post(networks); } @@ -111,8 +116,8 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { } @Override public final void clearScores() { - synchronized (mNetworkCache) { - mNetworkCache.clear(); + synchronized (mLock) { + mCache.evictAll(); } } @@ -138,7 +143,6 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { } public int getNetworkScore(ScanResult result) { - int score = INVALID_NETWORK_SCORE; ScoredNetwork network = getScoredNetwork(result); @@ -164,7 +168,6 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { } public int getNetworkScore(ScanResult result, boolean isActiveNetwork) { - int score = INVALID_NETWORK_SCORE; ScoredNetwork network = getScoredNetwork(result); @@ -185,8 +188,8 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { String key = buildNetworkKey(result); if (key == null) return null; - synchronized(mNetworkCache) { - ScoredNetwork network = mNetworkCache.get(key); + synchronized(mLock) { + ScoredNetwork network = mCache.get(key); return network; } } @@ -201,8 +204,8 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { } return null; } - synchronized (mNetworkCache) { - return mNetworkCache.get(key); + synchronized (mLock) { + return mCache.get(key); } } @@ -248,33 +251,35 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { mContext.getPackageName(), Process.myUid()); writer.println(header); writer.println(" All score curves:"); - for (ScoredNetwork score : mNetworkCache.values()) { - writer.println(" " + score); - } - writer.println(" Current network scores:"); - WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); - for (ScanResult scanResult : wifiManager.getScanResults()) { - writer.println(" " + buildNetworkKey(scanResult) + ": " + getNetworkScore(scanResult)); + synchronized (mLock) { + for (ScoredNetwork score : mCache.snapshot().values()) { + writer.println(" " + score); + } + writer.println(" Network scores for latest ScanResults:"); + WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); + for (ScanResult scanResult : wifiManager.getScanResults()) { + writer.println( + " " + buildNetworkKey(scanResult) + ": " + getNetworkScore(scanResult)); + } } } /** Registers a CacheListener instance, replacing the previous listener if it existed. */ public void registerListener(CacheListener listener) { - synchronized (mCacheLock) { + synchronized (mLock) { mListener = listener; } } /** Removes the registered CacheListener. */ public void unregisterListener() { - synchronized (mCacheLock) { + synchronized (mLock) { mListener = null; } } /** Listener for updates to the cache inside WifiNetworkScoreCache. */ public abstract static class CacheListener { - private Handler mHandler; /** diff --git a/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java new file mode 100644 index 000000000000..7c99c497c54b --- /dev/null +++ b/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi.aware; + +import android.net.NetworkSpecifier; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; + +import libcore.util.HexEncoding; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.StringJoiner; + +/** + * A network specifier object used to represent the capabilities of an network agent. A collection + * of multiple WifiAwareNetworkSpecifier objects whose matching critiera (satisfiedBy) is an OR: + * a match on any of the network specifiers in the collection is a match. + * + * This class is not intended for use in network requests. + * + * @hide + */ +public class WifiAwareAgentNetworkSpecifier extends NetworkSpecifier implements Parcelable { + private static final String TAG = "WifiAwareAgentNs"; + + private static final boolean VDBG = false; // STOPSHIP if true + + private Set<ByteArrayWrapper> mNetworkSpecifiers = new HashSet<>(); + private MessageDigest mDigester; + + public WifiAwareAgentNetworkSpecifier() { + // do nothing, already initialized to empty + } + + public WifiAwareAgentNetworkSpecifier(WifiAwareNetworkSpecifier ns) { + initialize(); + mNetworkSpecifiers.add(convert(ns)); + } + + public WifiAwareAgentNetworkSpecifier(WifiAwareNetworkSpecifier[] nss) { + initialize(); + for (WifiAwareNetworkSpecifier ns : nss) { + mNetworkSpecifiers.add(convert(ns)); + } + } + + public boolean isEmpty() { + return mNetworkSpecifiers.isEmpty(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeArray(mNetworkSpecifiers.toArray()); + } + + public static final Creator<WifiAwareAgentNetworkSpecifier> CREATOR = + new Creator<WifiAwareAgentNetworkSpecifier>() { + @Override + public WifiAwareAgentNetworkSpecifier createFromParcel(Parcel in) { + WifiAwareAgentNetworkSpecifier agentNs = new WifiAwareAgentNetworkSpecifier(); + Object[] objs = in.readArray(null); + for (Object obj : objs) { + agentNs.mNetworkSpecifiers.add((ByteArrayWrapper) obj); + } + return agentNs; + } + + @Override + public WifiAwareAgentNetworkSpecifier[] newArray(int size) { + return new WifiAwareAgentNetworkSpecifier[size]; + } + }; + + @Override + public int hashCode() { + return mNetworkSpecifiers.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof WifiAwareAgentNetworkSpecifier)) { + return false; + } + return mNetworkSpecifiers.equals(((WifiAwareAgentNetworkSpecifier) obj).mNetworkSpecifiers); + } + + @Override + public String toString() { + StringJoiner sj = new StringJoiner(","); + for (ByteArrayWrapper baw: mNetworkSpecifiers) { + sj.add(baw.toString()); + } + return sj.toString(); + } + + @Override + public boolean satisfiedBy(NetworkSpecifier other) { + if (!(other instanceof WifiAwareAgentNetworkSpecifier)) { + return false; + } + WifiAwareAgentNetworkSpecifier otherNs = (WifiAwareAgentNetworkSpecifier) other; + + // called as old.satifiedBy(new): satisfied if old contained in new + for (ByteArrayWrapper baw: mNetworkSpecifiers) { + if (!otherNs.mNetworkSpecifiers.contains(baw)) { + return false; + } + } + + return true; + } + + public boolean satisfiesAwareNetworkSpecifier(WifiAwareNetworkSpecifier ns) { + if (VDBG) Log.v(TAG, "satisfiesAwareNetworkSpecifier: ns=" + ns); + ByteArrayWrapper nsBytes = convert(ns); + return mNetworkSpecifiers.contains(nsBytes); + } + + @Override + public void assertValidFromUid(int requestorUid) { + throw new SecurityException( + "WifiAwareAgentNetworkSpecifier should not be used in network requests"); + } + + private void initialize() { + try { + mDigester = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e) { + Log.e(TAG, "Can not instantiate a SHA-256 digester!? Will match nothing."); + return; + } + } + + private ByteArrayWrapper convert(WifiAwareNetworkSpecifier ns) { + if (mDigester == null) { + return null; + } + + Parcel parcel = Parcel.obtain(); + ns.writeToParcel(parcel, 0); + byte[] bytes = parcel.marshall(); + + mDigester.reset(); + mDigester.update(bytes); + return new ByteArrayWrapper(mDigester.digest()); + } + + private static class ByteArrayWrapper implements Parcelable { + private byte[] mData; + + ByteArrayWrapper(byte[] data) { + mData = data; + } + + @Override + public int hashCode() { + return Arrays.hashCode(mData); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof ByteArrayWrapper)) { + return false; + } + return Arrays.equals(((ByteArrayWrapper) obj).mData, mData); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeBlob(mData); + } + + public static final Creator<ByteArrayWrapper> CREATOR = + new Creator<ByteArrayWrapper>() { + @Override + public ByteArrayWrapper createFromParcel(Parcel in) { + return new ByteArrayWrapper(in.readBlob()); + } + + @Override + public ByteArrayWrapper[] newArray(int size) { + return new ByteArrayWrapper[size]; + } + }; + + @Override + public String toString() { + return new String(HexEncoding.encode(mData)); + } + } +} diff --git a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java index eeabbfa25892..6e37fcf4d338 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java +++ b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java @@ -193,6 +193,9 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements @Override public boolean satisfiedBy(NetworkSpecifier other) { // MatchAllNetworkSpecifier is taken care in NetworkCapabilities#satisfiedBySpecifier. + if (other instanceof WifiAwareAgentNetworkSpecifier) { + return ((WifiAwareAgentNetworkSpecifier) other).satisfiesAwareNetworkSpecifier(this); + } return equals(other); } diff --git a/wifi/tests/Android.mk b/wifi/tests/Android.mk index afab1a3721db..c98e40a2c2d9 100644 --- a/wifi/tests/Android.mk +++ b/wifi/tests/Android.mk @@ -49,14 +49,15 @@ LOCAL_JACK_COVERAGE_INCLUDE_FILTER := $(jacoco_include) LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := $(jacoco_exclude) LOCAL_STATIC_JAVA_LIBRARIES := \ - android-support-test \ - core-test-rules \ - guava \ - mockito-target-minus-junit4 \ - frameworks-base-testutils \ + android-support-test \ + core-test-rules \ + guava \ + mockito-target-minus-junit4 \ + frameworks-base-testutils \ + truth-prebuilt \ LOCAL_JAVA_LIBRARIES := \ - android.test.runner \ + android.test.runner \ LOCAL_PACKAGE_NAME := FrameworksWifiApiTests LOCAL_COMPATIBILITY_SUITE := device-tests diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java index 18f6bc848081..997282b24b46 100644 --- a/wifi/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java +++ b/wifi/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java @@ -16,9 +16,9 @@ package android.net.wifi; -import static org.junit.Assert.*; -import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.verify; +import static com.google.common.truth.Truth.assertThat; + +import static org.junit.Assert.fail; import static org.mockito.Mockito.when; import android.content.Context; @@ -34,12 +34,9 @@ import android.support.test.runner.AndroidJUnit4; import com.google.common.collect.ImmutableList; -import org.junit.Rule; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -54,7 +51,11 @@ import java.util.concurrent.TimeUnit; public class WifiNetworkScoreCacheTest { public static final String SSID = "ssid"; + public static final String SSID2 = "ssid2"; + public static final String SSID3 = "ssid3"; public static final String FORMATTED_SSID = "\"" + SSID + "\""; + public static final String FORMATTED_SSID2 = "\"" + SSID2 + "\""; + public static final String FORMATTED_SSID3 = "\"" + SSID3 + "\""; public static final String BSSID = "AA:AA:AA:AA:AA:AA"; public static final WifiKey VALID_KEY = new WifiKey(FORMATTED_SSID, BSSID); @@ -120,13 +121,13 @@ public class WifiNetworkScoreCacheTest { @Test public void isScoredNetworkShouldReturnTrueAfterUpdateScoresIsCalled() { - assertTrue(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)); + assertThat(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)).isTrue(); } @Test public void isScoredNetworkShouldReturnFalseAfterClearScoresIsCalled() { mScoreCache.clearScores(); - assertFalse(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)); + assertThat(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)).isFalse(); } @Test @@ -137,19 +138,19 @@ public class WifiNetworkScoreCacheTest { mScoreCache.updateScores(ImmutableList.of(network2)); - assertTrue(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)); - assertTrue(mScoreCache.isScoredNetwork(result2)); + assertThat(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)).isTrue(); + assertThat(mScoreCache.isScoredNetwork(result2)).isTrue(); } @Test public void hasScoreCurveShouldReturnTrue() { - assertTrue(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)); + assertThat(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)).isTrue(); } @Test public void hasScoreCurveShouldReturnFalseWhenNoCachedNetwork() { ScanResult unscored = buildScanResult("fake", BSSID); - assertFalse(mScoreCache.hasScoreCurve(unscored)); + assertThat(mScoreCache.hasScoreCurve(unscored)).isFalse(); } @Test @@ -157,7 +158,7 @@ public class WifiNetworkScoreCacheTest { ScoredNetwork noCurve = buildScoredNetwork(VALID_KEY, null /* rssiCurve */); mScoreCache.updateScores(ImmutableList.of(noCurve)); - assertFalse(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)); + assertThat(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)).isFalse(); } @Test @@ -169,12 +170,12 @@ public class WifiNetworkScoreCacheTest { when(mockRssiCurve.lookupScore(rssi)).thenReturn(score); - assertEquals(score, mScoreCache.getNetworkScore(result)); + assertThat(mScoreCache.getNetworkScore(result)).isEqualTo(score); } @Test public void getMeteredHintShouldReturnFalse() { - assertFalse(mScoreCache.getMeteredHint(VALID_SCAN_RESULT)); + assertThat(mScoreCache.getMeteredHint(VALID_SCAN_RESULT)).isFalse(); } @Test @@ -184,7 +185,7 @@ public class WifiNetworkScoreCacheTest { new NetworkKey(VALID_KEY), mockRssiCurve, true /* metered Hint */); mScoreCache.updateScores(ImmutableList.of(network)); - assertTrue(mScoreCache.getMeteredHint(VALID_SCAN_RESULT)); + assertThat(mScoreCache.getMeteredHint(VALID_SCAN_RESULT)).isTrue(); } @Test @@ -197,7 +198,28 @@ public class WifiNetworkScoreCacheTest { } catch (InterruptedException e) { fail("Interrupted Exception while waiting for listener to be invoked."); } - assertEquals("One network should be updated", 1, mUpdatedNetworksCaptor.size()); - assertEquals(mValidScoredNetwork, mUpdatedNetworksCaptor.get(0)); + // One network should be updated. + assertThat(mUpdatedNetworksCaptor.size()).isEqualTo(1); + assertThat(mUpdatedNetworksCaptor.get(0)).isEqualTo(mValidScoredNetwork); + } + + @Test + public void leastRecentlyUsedScore_shouldBeEvictedFromCache() { + mScoreCache = new WifiNetworkScoreCache(mockContext, mCacheListener, 2 /* maxCacheSize */); + + ScoredNetwork network1 = mValidScoredNetwork; + ScoredNetwork network2 = buildScoredNetwork( + new WifiKey(FORMATTED_SSID2, BSSID), mockRssiCurve); + ScoredNetwork network3 = buildScoredNetwork( + new WifiKey(FORMATTED_SSID3, BSSID), mockRssiCurve); + mScoreCache.updateScores(ImmutableList.of(network1)); + mScoreCache.updateScores(ImmutableList.of(network2)); + + // First score should be evicted because max cache size has been reached. + mScoreCache.updateScores(ImmutableList.of(network3)); + + assertThat(mScoreCache.hasScoreCurve(buildScanResult(SSID2, BSSID))).isTrue(); + assertThat(mScoreCache.hasScoreCurve(buildScanResult(SSID3, BSSID))).isTrue(); + assertThat(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)).isFalse(); } } diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java new file mode 100644 index 000000000000..2dd0537a7aff --- /dev/null +++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi.aware; + +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertEquals; + +import android.os.Parcel; +import android.test.suitebuilder.annotation.SmallTest; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ErrorCollector; + +import java.util.HashSet; +import java.util.Set; + +/** + * Unit test harness for WifiAwareAgentNetworkSpecifier class. + */ +@SmallTest +public class WifiAwareAgentNetworkSpecifierTest { + @Rule + public ErrorCollector collector = new ErrorCollector(); + + @Test + public void testParcel() { + final int numNs = 10; + + Set<WifiAwareNetworkSpecifier> nsSet = new HashSet<>(); + for (int i = 0; i < numNs; ++i) { + nsSet.add(getDummyNetworkSpecifier(10 + i)); + } + WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier( + nsSet.toArray(new WifiAwareNetworkSpecifier[numNs])); + + Parcel parcelW = Parcel.obtain(); + dut.writeToParcel(parcelW, 0); + byte[] bytes = parcelW.marshall(); + parcelW.recycle(); + + Parcel parcelR = Parcel.obtain(); + parcelR.unmarshall(bytes, 0, bytes.length); + parcelR.setDataPosition(0); + WifiAwareAgentNetworkSpecifier rereadDut = + WifiAwareAgentNetworkSpecifier.CREATOR.createFromParcel(parcelR); + + assertEquals(dut, rereadDut); + } + + /** + * Validate that an empty agent network specifier doesn't match any base network specifier. + */ + @Test + public void testEmptyDoesntMatchAnything() { + WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier(); + WifiAwareNetworkSpecifier ns = getDummyNetworkSpecifier(6); + collector.checkThat("No match expected", ns.satisfiedBy(dut), equalTo(false)); + } + + /** + * Validate that an agent network specifier constructed with a single entry matches that entry, + * and only that entry. + */ + @Test + public void testSingleMatch() { + WifiAwareNetworkSpecifier nsThis = getDummyNetworkSpecifier(6); + WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier(nsThis); + WifiAwareNetworkSpecifier nsOther = getDummyNetworkSpecifier(8); + collector.checkThat("Match expected", nsThis.satisfiedBy(dut), equalTo(true)); + collector.checkThat("No match expected", nsOther.satisfiedBy(dut), equalTo(false)); + } + + /** + * Validate that an agent network specifier constructed with multiple entries matches all those + * entries - but none other. + */ + @Test + public void testMultipleMatchesAllMembers() { + final int numNs = 10; + + Set<WifiAwareNetworkSpecifier> nsSet = new HashSet<>(); + for (int i = 0; i < numNs; ++i) { + nsSet.add(getDummyNetworkSpecifier(10 + i)); + } + + WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier( + nsSet.toArray(new WifiAwareNetworkSpecifier[numNs])); + WifiAwareNetworkSpecifier nsOther = getDummyNetworkSpecifier(10000); + + for (WifiAwareNetworkSpecifier nsThis: nsSet) { + collector.checkThat("Match expected", nsThis.satisfiedBy(dut), equalTo(true)); + } + collector.checkThat("No match expected", nsOther.satisfiedBy(dut), equalTo(false)); + } + + /** + * Validate that agent network specifier matches against a super-set. + */ + @Test + public void testMatchSuperset() { + final int numNs = 10; + + Set<WifiAwareNetworkSpecifier> nsSet = new HashSet<>(); + for (int i = 0; i < numNs; ++i) { + nsSet.add(getDummyNetworkSpecifier(10 + i)); + } + + WifiAwareAgentNetworkSpecifier oldNs = new WifiAwareAgentNetworkSpecifier( + nsSet.toArray(new WifiAwareNetworkSpecifier[nsSet.size()])); + + nsSet.add(getDummyNetworkSpecifier(100 + numNs)); + WifiAwareAgentNetworkSpecifier newNs = new WifiAwareAgentNetworkSpecifier( + nsSet.toArray(new WifiAwareNetworkSpecifier[nsSet.size()])); + + collector.checkThat("Match expected", oldNs.satisfiedBy(newNs), equalTo(true)); + } + + /** + * Validate that agent network specifier does not match against a sub-set. + */ + @Test + public void testNoMatchSubset() { + final int numNs = 10; + + Set<WifiAwareNetworkSpecifier> nsSet = new HashSet<>(); + for (int i = 0; i < numNs; ++i) { + nsSet.add(getDummyNetworkSpecifier(10 + i)); + } + + WifiAwareAgentNetworkSpecifier newNs = new WifiAwareAgentNetworkSpecifier( + nsSet.toArray(new WifiAwareNetworkSpecifier[nsSet.size()])); + + nsSet.add(getDummyNetworkSpecifier(100 + numNs)); + WifiAwareAgentNetworkSpecifier oldNs = new WifiAwareAgentNetworkSpecifier( + nsSet.toArray(new WifiAwareNetworkSpecifier[nsSet.size()])); + + collector.checkThat("Match unexpected", oldNs.satisfiedBy(newNs), equalTo(false)); + } + + /** + * Validate that agent network specifier cannot be used as in network requests - i.e. that + * throws an exception when queried for UID validity. + */ + @Test(expected = SecurityException.class) + public void testNoUsageInRequest() { + WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier(); + + dut.assertValidFromUid(0); + } + + // utilities + + /** + * Returns a WifiAwareNetworkSpecifier with dummy (but valid) entries. Each can be + * differentiated (made unique) by specifying a different client ID. + */ + WifiAwareNetworkSpecifier getDummyNetworkSpecifier(int clientId) { + return new WifiAwareNetworkSpecifier(WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB, + WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR, clientId, 0, 0, new byte[6], + null, null, 0); + } +} |